我们正在使用Firebase进行用户身份验证。
我可以在客户端登录用户,然后从python应用程序运行以下命令:
import firebase_admin
import firebase_admin.auth
from firebase_admin import credentials
from datetime import datetime
cred = credentials.Certificate('my_creds.json')
app = firebase_admin.initialize_app(cred)
firebase_admin.auth.revoke_refresh_tokens('some-user-id', app=app)
u = firebase_admin.auth.get_user('some-user-id')
print(datetime.fromtimestamp(u.tokens_valid_after_timestamp / 1000))
显示当前时间戳,至少据我所知managing user sessions documentation,它应该吊销令牌。我认为应该做到的,这样我在客户端进行的任何进一步操作都将失败。
但是,这是不正确的。我可以弹出打开已登录'some-user-id'
的控制台并运行:
firebase.database().ref('some/key').once('value').then(function(snap){ console.log(snap.val()); });
稍后,我会观察到some/key
的值很好。
这不好。
当我运行firebase.auth().currentUser.reload()
然后时,它将实际上断开我的会话,并且我将无法再获得该值。但是我想在服务器端做一些事情,这样来自客户端的每个后续请求都会因身份验证问题而失败。
这可能吗?如果是这样,我该怎么办?
答案 0 :(得分:0)
revoke_refresh_token()
使“刷新令牌”无效。它不会使已登录的用户会话无效。实际上,当前正在会话中的任何“ ID令牌”都可以保持长达一个小时的有效期(此后将强制用户登录)。如果您想进一步了解这两种令牌之间的区别,请查看this article。
为防止使用旧的(吊销)ID令牌访问数据库,应使用Firebase安全规则。您可以将tokens_valid_after_timestamp
写入数据库:
auth.revoke_refresh_tokens(uid)
user = auth.get_user(uid)
revocation_second = user.tokens_valid_after_timestamp / 1000
# Write the revoke time to database as part of the
# server-side revoke operaition
metadata_ref = firebase_admin.db.reference("metadata/" + uid)
metadata_ref.set({'revokeTime': revocation_second})
然后实施一个规则,根据该规则检查ID令牌。
{
"rules": {
"users": {
"$user_id": {
".read": "$user_id === auth.uid && auth.token.auth_time > (root.child('metadata').child(auth.uid).child('revokeTime').val() || 0)",
".write": "$user_id === auth.uid && auth.token.auth_time > (root.child('metadata').child(auth.uid).child('revokeTime').val() || 0)"
}
}
}
}
此配置可防止用户使用撤销之前获得的ID令牌访问users/{uid}
节点。
documentation中概述了该解决方案。