如何将Firebase身份验证令牌传递到WebView并在Android上注册通知 [英] How to pass Firebase Auth token to webView and register for notifications on Android
问题描述
我有一个Firebase WebApp,它可以向用户提供信息.除了该应用程序外,我还需要通过Firebase Cloud Messaging向具有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.
目标:用户应先登录到该应用程序,该应用程序既要注册它们以获取通知,又要通过WebView加载WebApp.
Goal: The user should have one login to the app which both registers them for notifications and loads the WebApp through a WebView.
问题:我找不到通过一次登录即可实现此目标的方法.在每种情况下,我都需要登录一次本机应用程序,然后再次通过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身份验证用户界面: https://firebase.google.com/docs/auth/android/firebaseui
Firebase Auth UI: https://firebase.google.com/docs/auth/android/firebaseui
Firebase数据库: https://firebase.google.com/docs/database/android/read-and-write
Firebase DB: https://firebase.google.com/docs/database/android/read-and-write
Firebase云消息传递: https://firebase.google.com/docs/cloud-messaging/android/topic-messaging
Firebase Cloud Messaging: https://firebase.google.com/docs/cloud-messaging/android/topic-messaging
背景:我能够使用Firebase Auth UI分别处理每个身份验证,以本地处理通知身份验证,然后通过Firebase服务器处理webView身份验证.这行得通,但是用户体验很差.由于本机身份验证已经提供了令牌,因此我应该能够以某种方式跳过第二阶段并直接登录用户.这是我尝试过的方法:
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:
第一种方法:
先进行本机登录,然后再进行Webapp登录(有效,但需要两次登录):通过遵循Firebase Auth UI教程,我可以成功登录:
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'不为null,可用于从firebase数据库读取数据.然后根据FCM文档使用主题ID订阅主题.
'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.
订阅通知后,我们使用以下代码建立与Web应用程序的连接:
With notifications subscribed we then establish a connection to the webapp using this line:
myWebView.loadUrl("https://someproject.appspot.com/index.html");
第二种方法:
使用myWebView.loadUrl()传递用户令牌(拒绝授权)...根据此信息: https://firebase.google.com/docs/cloud-messaging/auth-server
Pass user token with myWebView.loadUrl() (authorization is rejected) ...Based on this info: https://firebase.google.com/docs/cloud-messaging/auth-server
我希望与此类似:
...
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);
...
*这似乎是最有可能达到目的的方式,也许我需要在服务器端添加一些代码来显式处理请求,而不是依赖onStateChanged处理程序?也曾尝试使用?auth =和?access_token =基于: https://firebase.google.com/docs/database/rest/auth#authenticate_with_an_id_token 有点在黑暗中射击......
*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....
第三种方法:
打开webApp,并在授权完成后触发onAuthStateChanged.(处理程序似乎从未触发过.我怀疑没有FirebaseAuth对象会受到webView的影响)
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("<a href="https://someproject.appspot.com/index.html" rel="noreferrer"> https://someproject.appspot.com/index.html );
myWebView.loadUrl("https://someproject.appspot.com/index.html");
似乎这里有一个最佳实践,在firebase教程中没有得到很好的记录.对于在Android上使用Firebase的人来说,这似乎也是一项典型任务.有人可以提供一种方法来注册通知主题并一次登录即可访问WebApp吗?我想念什么?
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?
预期结果将是一次登录,此后用户可以访问Web应用程序并注册为单独的推送通知.
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.
推荐答案
以下是React Native中使用WebView进行Firebase Auth的解决方案:
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',
}}
/>
}
Android(JS注入)中可能需要类似的逻辑.
Similar logic might be required in Android (JS injection).
这篇关于如何将Firebase身份验证令牌传递到WebView并在Android上注册通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!