问题
We're using Firebase for our user authentication.
I can log a user in on the client side and then run the following from a python app:
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))
Which displays the current timestamp, and at least as far as I understand the managing user sessions documentation, it should be revoking the tokens. Which I thought should make it so any further operations I do on the client side would fail.
This, however, is not true. I can pop open the console where 'some-user-id'
has been logged in and run:
firebase.database().ref('some/key').once('value').then(function(snap){ console.log(snap.val()); });
And after a moment, I will observe the value of some/key
just fine.
This is not fine.
When I run firebase.auth().currentUser.reload()
then it will actually disconnect my session and I won't be able to get that value any more. But I want to do something on the server side to make it so every subsequent request from the client will fail with an authentication problem.
Is this possible? And if so, how can I do that?
回答1:
revoke_refresh_token()
invalidates "refresh tokens". It doesn't invalidate already logged in user sessions. In fact any "ID tokens" that are currently in session can remain valid up to an hour (after which users will be forced to log in). Check out this article, if you want to know more about the difference between these two types of tokens.
To prevent database access with old (pre-revocation) ID tokens, you should use Firebase security rules. You can write the tokens_valid_after_timestamp
to the database:
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})
Then implement a rule that checks the ID token against that.
{
"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)"
}
}
}
}
This configuration prevents users from accessing the users/{uid}
node with an ID token obtained prior to a revocation.
This solution is outlined in the documentation.
来源:https://stackoverflow.com/questions/52046579/how-can-you-log-a-user-out-of-firebase