I have a Firebase WebApp which provides info to a user. In addition to the app I need to send push notifications via Firebase Cloud Messaging to users with an Android App.
Goal: The user should have one login to the app which both registers them for notifications and loads the WebApp through a WebView.
Problem: I can't find an approach which achieves this with a single login. In every case I need to login once for the native app and then once again through the webView.
First, some references for others who may be figuring things out:
Firebase Auth UI: https://firebase.google.com/docs/auth/android/firebaseui
Firebase DB: https://firebase.google.com/docs/database/android/read-and-write
Firebase Cloud Messaging: https://firebase.google.com/docs/cloud-messaging/android/topic-messaging
Background: I'm able to process each authentication separately using Firebase Auth UI to handle the notification auth natively and then process the webView authentication through the firebase server. This works but is a poor user experience. Since the native authentication already supplies a token I should, somehow, be able to skip the second stage and sign the user in directly. Here's the approaches I've tried:
FIRST APPROACH:
Native sign-on followed by webapp sign on (working but requires two logins): By following the Firebase Auth UI tutorial I can complete a successful sign in:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
'user' is not null and can be used to read data from firebase database. Topics IDs are then used to subscribe to topics per FCM documentation.
With notifications subscribed we then establish a connection to the webapp using this line:
myWebView.loadUrl("https://someproject.appspot.com/index.html");
SECOND APPROACH:
Pass user token with myWebView.loadUrl() (authorization is rejected) ...Based on this info: https://firebase.google.com/docs/cloud-messaging/auth-server
Something similar to this, I expect:
...
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
//get the user id token
user.getIdToken(true).addOnCompleteListener(new
OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
//here is the idToken
String idToken = task.getResult().getToken();
}}}}
HashMap<String, String> map = new HashMap<String, String>();
String bearer = "Bearer " + idToken;
//Create header of the form "Authorization: Bearer <token>"
map.put("Authorization",bearer);
myWebView.loadUrl("https://someproject.appspot.com/index.html", map);
...
*This seems to be the mostly likely way this is intended to work, maybe I need to add some code server-side to process the request explicitly rather than relying on the onStateChanged handler? Have also attempted using ?auth= and ?access_token= based on: https://firebase.google.com/docs/database/rest/auth#authenticate_with_an_id_token Sort of shooting in the dark here....
THIRD APPROACH:
Open webApp and trigger onAuthStateChanged when authorization is finished. (Handler never seems to fire. I suspect no FirebaseAuth object is impacted by webView)
...
//Register a FirebaseAuth Listener
FirebaseAuth.AuthStateListener mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
//Register notification subscriptions per tutorial
}
...
myWebView.loadUrl("https://someproject.appspot.com/index.html");
It seems like there is a best practise here that is not well documented in the firebase tutorials. This also seems like a typical task for someone using firebase on Android. Can someone offer an approach that registers the notification topics and accesses a webApp in one login? What am I missing?
The expected results are to have a single login, following which the user has access to the web app and is registered for individual push notifications.
To receive the Device Token (and updates to the token value) and push notifications, you must create a custom class that extends FirebaseMessagingService . The onNewToken callback fires whenever a new token is generated.
For sending FCM notification payload you can use Firebase Cloud Messaging Tool in firebase console. And click on Send your first message. Then enter the Title and body field. If you wish to send it to a particular device then click on Send test message and enter the FCM registration token.
Here is solution for Firebase Auth with WebView in React Native:
import React from 'react'
import WebView from 'react-native-webview'
export default function HomeScreen(props) {
// props.user represents firebase user
const apiKey = props.user.toJSON().apiKey
const authJS = `
if (!("indexedDB" in window)) {
alert("This browser doesn't support IndexedDB")
} else {
let indexdb = window.indexedDB.open('firebaseLocalStorageDb', 1)
indexdb.onsuccess = function() {
let db = indexdb.result
let transaction = db.transaction('firebaseLocalStorage', 'readwrite')
let storage = transaction.objectStore('firebaseLocalStorage')
const request = storage.put({
fbase_key: "firebase:authUser:${apiKey}:[DEFAULT]",
value: ${JSON.stringify(props.user.toJSON())}
});
}
}
`
return <WebView
injectedJavaScriptBeforeContentLoaded={authJS}
source={{
uri: 'http://192.168.1.102:3000',
baseUrl: 'http://192.168.1.102:3000',
}}
/>
}
Similar logic might be required in Android (JS injection).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With