Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass Firebase Auth token to webView and register for notifications on Android

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.

like image 755
icuham Avatar asked Oct 13 '19 22:10

icuham


People also ask

How can we get device token for Android for push notification?

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.

How do I send notifications to specific users with FCM console?

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.


1 Answers

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).

like image 108
Marcin Urbanski Avatar answered Oct 20 '22 18:10

Marcin Urbanski