如何从应用程序远程强制注销firebase auth用户
Posted
技术标签:
【中文标题】如何从应用程序远程强制注销firebase auth用户【英文标题】:How to force logout firebase auth user from app remotely 【发布时间】:2019-04-04 21:17:52 【问题描述】:我有一个项目,它使用 firebase auth 和 firebaseUI 对用户进行身份验证。我已启用 Google、Facebook 和电子邮件提供商。我需要的是远程注销或禁用一些用户。
我希望用户在这样做时退出应用。我尝试在 firebase 控制台中禁用用户,并使用 firebase admin SDK (https://firebase.google.com/docs/auth/admin/manage-sessions) 撤销刷新令牌。
我等了 2 天多,仍然注意到用户已登录并且可以访问 firestore 数据。
我也经历过并尝试过 Firebase still retrieving authData after deletion
谁能指出我做错了什么?
【问题讨论】:
【参考方案1】:您也不能远程强制用户退出。任何注销都必须在用户登录的设备上进行。
访问令牌一旦生成,就无法撤销。这意味着即使您禁用该用户的帐户,他们也可以继续访问长达一个小时。
如果这太长,诀窍(正如我对您链接的问题的回答中所提到的)是在您的数据库(或其他地方)中维护一个被阻止用户的列表,然后在您的安全规则中检查该列表(或其他授权层)。
例如在实时数据库中,您可以创建一个被屏蔽用户的 UID 列表:
banned_uids:
"uid1": true
"uid2": true
然后在您的安全规则中检查:
".read": "auth.uid !== null && !root.child('banned_uids').child(auth.uid).exists()"
【讨论】:
谢谢,@frank-van-puffelen。在我们的案例中,我们尝试禁用用户并尝试撤销他/她的刷新令牌,但即使等待 1 小时后用户仍然能够访问数据(我们也等待了 2 天 :))。我们还在 Firestore 中添加了规则,只允许经过身份验证的用户。如果我的理解有误,请帮助我理解何时撤销用户刷新令牌? 我注意到我说的是 ID 令牌,我的意思是访问令牌,所以我解决了这个问题。撤销访问令牌是不够的,这就是安全规则的用武之地。如果这些步骤对您不起作用,请准确显示您所做的事情。没有代码或精确的重现步骤,任何人都很难说出你在哪里犯了错误。 @FrankvanPuffelen 在 Firebase 身份验证控制台中禁用用户后,用户需要多长时间才能注销?有这方面的文档吗? "如果您禁用该用户的帐户,他们最多可以继续访问一个小时" 这是一个愚蠢的问题,但是您实际上是如何在 Firebase 规则 DSL 中定义banned_uuids 的?只是复制粘贴是行不通的?【参考方案2】:您可以使用 FCM 发送消息数据以强制注销。
例如,如果用户使用 android 应用程序。
-
将 FCM 令牌保存在 firebase Realtime 的集合中。
在服务中配置 Android 客户端应用程序。 LINK你必须在收到带有特殊字符串的消息时强制退出。
在云功能中做你需要的触发器,当你需要用户退出时发送数据LINK。
成功!
【讨论】:
我们如何使用 nodejs sdk 来实现这一点,我也没有使用 firebase db 只需保存令牌并使用api发送数据firebase.google.com/docs/cloud-messaging/… 不知道Android App在后台运行的情况下是否有效?【参考方案3】:根据您的情况,我假设您需要在用户被禁用时让用户注销。 使用一个全局变量来存储 TokenNo(可能在共享偏好或 sqlite 中):
将以下代码添加到您的清单中:
<service android:name=".YourFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
在您的
中添加以下代码public class LogoutOntokenchange extends FirebaseMessagingService
@Override
public void onNewToken (String token)
if(TokenNo=>1) //if tokenNo >=1 means he already logged in
TokenNo=0;
FirebaseAuth.getInstance().signOut(); //Then call signout method
else
TokenNo=1; //store token no in db
这里发生了什么: 当用户第一次登录时调用 onNewToken 然后它进入 else 然后 TokenNo 从 0 更新为 1。 当您禁用任何用户时,会自动刷新令牌。然后调用 OnNewToken 然后 TokenNo>=1 ,因此用户将被注销。 注意: 当用户第一次登录时,即如果没有存储 TokenNo 变量,则将其存储为 0。 供参考:https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService
【讨论】:
据我所知,以上onNewToken
属于FCM。您能否解释一下为什么我们在刷新 FCM 令牌时将用户注销?【参考方案4】:
尚未测试,因为我们负责设置 Firestore 规则的后端程序员已经离开了一天,但理论上这应该可以工作:(明天我会测试)
有一个 FirebaseAuth.AuthStateListener 负责根据用户的状态为 UI 提供服务
这与firestore中的规则相结合
match /collection
allow read: if isAuth();
isAuth 在哪里:
function isAuth()
return request.auth.uid != null;
如果用户随后被禁用,则在登录时,每当用户尝试从集合中读取数据时,他都应该被拒绝,并且应该进行 signOut() 调用。 然后 AuthStateListener 将检测到它,并将用户注销。
【讨论】:
【参考方案5】:我能想到的唯一方法是在您的开始活动中添加一个 if-else 块。 将用户的状态(已验证/禁止/删除)存储在 Firebase 实时数据库中。然后在应用程序启动时检索用户的状态并添加代码:
if (currentUserStatus.equals("banned"))
currentUser.logout();
【讨论】:
【参考方案6】:我所做的是在注册时为每个用户创建一个以 UID 作为文档 ID 的 Firestore 文档。在本文档中,我存储了一个数组,该数组存储了单个用户在登录新设备时收到的所有 fcm 令牌。这样,我始终跟踪用户登录的位置。当用户手动注销时,fcm 令牌将从 Firestore 以及设备上的文档中删除。
为了能够在用户登录的任何地方注销用户,我执行了以下操作。启动应用程序时,一旦用户登录,我就会启动一个快照侦听器来侦听用户文档中的所有更改。一旦发生更改,我就会检索新的 fcm 令牌数组,在数组中搜索本地当前设备 fcm 令牌。如果找到了,我什么也不做。如果 fcm 令牌不再在数组中,我将调用本地注销方法并返回登录屏幕。
这是我在 ios 上 swift 中使用的方法。闭包(passOnMethod)只会触发登录视图控制器的展开segue。
import Foundation
import Firebase
class FB_Auth_Methods
let db = Firestore.firestore()
var listener: ListenerRegistration?
func trackLoginStatus(passOnMethod: @escaping () -> () )
listener?.remove()
if let loggedInUserA_UID = Auth.auth().currentUser?.uid
listener = db.collection(K.FStore.collectionOf_RegisteredUsers_Name)
.document(loggedInUserA_UID)
.addSnapshotListener (snapshotDocument, error) in
if let error = error
print(error)
else
if let document = snapshotDocument
if let data = document.data()
if let fcmTokens = data[K.FStore.Users.fcmTokens] as? [String]
print("Found the following tokens: \(fcmTokens)")
self.compareTokensAgainstCurrentDeviceToken(fcmTokens: fcmTokens, passOnMethod: () in
passOnMethod()
)
func compareTokensAgainstCurrentDeviceToken(fcmTokens: [String], passOnMethod: @escaping () -> () )
InstanceID.instanceID().instanceID (result, error) in
if let error = error
print(error)
else if let result = result
if fcmTokens.contains(result.token)
print("Token found, doing nothing")
else
print("Token no longer found, logout user")
do
try Auth.auth().signOut()
InstanceID.instanceID().deleteID error in
if let error = error
print(error)
else
passOnMethod()
catch let signOutError as NSError
print (signOutError)
这是我在除当前设备之外的任何地方注销用户时使用的方法。
func deleteAllFcmTokensExceptCurrent(loggedInUserA: User, passOnMethod: @escaping () -> () )
InstanceID.instanceID().instanceID (result, error) in
if let error = error
print(error)
else if let result = result
let batch = self.db.batch()
let deleteAllFcmRef = self.db.collection(K.FStore.collectionOf_RegisteredUsers_Name).document(loggedInUserA.uid)
batch.updateData([K.FStore.Users.fcmTokens: FieldValue.delete()], forDocument: deleteAllFcmRef)
let updateFcmTokenRef = self.db.collection(K.FStore.collectionOf_RegisteredUsers_Name).document(loggedInUserA.uid)
batch.updateData([K.FStore.Users.fcmTokens: FieldValue.arrayUnion([result.token])], forDocument: updateFcmTokenRef)
batch.commit (error) in
if let error = error
print(error)
else
passOnMethod()
【讨论】:
以上是关于如何从应用程序远程强制注销firebase auth用户的主要内容,如果未能解决你的问题,请参考以下文章