riazosama
riazosama

Reputation: 535

How to logout the user using Firebase Admin SDK?

So, I have created a cloud function using Firebase Admin SDK. The purpose of that function is to disable the user and after successfully disabling it, I want that user to be logged out from my application. I have disabled user but can't figure out how to log out the user.

I was wondering if there is any function of a workaround to achieve this?

Upvotes: 1

Views: 6328

Answers (2)

cbreezier
cbreezier

Reputation: 1314

There are two main types of tokens used in Firebase Auth that are relevant to your question here:

  1. Refresh token
  2. ID token (aka, access token)

Firebase ID tokens are short lived and last for an hour; the refresh token can be used to retrieve new ID tokens. Refresh tokens expire only when one of the following occurs:

  • The user is deleted
  • The user is disabled
  • A major account change is detected for the user. This includes events like password or email address updates.

https://firebase.google.com/docs/auth/admin/manage-sessions

So in your case, when you disable the user, the refresh token will be automatically revoked. This means that once the short-lived ID token expires, they won't be able to retrieve a new one.

But you want them to be logged out immediately after being disabled. There are two main considerations here:

  1. if you control the well-behaved client application, you can voluntarily log them out in the client
  2. if you want to truly protect against malicious actors, you can revoke the ID token on the backend

Voluntarily logging out in a well-behaved client

If the token is revoked via the Admin SDK, the client is informed of the revocation and the user is expected to reauthenticate or is signed out:

https://firebase.google.com/docs/auth/admin/manage-sessions#respond_to_token_revocation_on_the_client

However, the docs are very misleading here. There is no built-in behaviour to automatically inform the client of a revocation. Instead, you can follow the suggestions in this thread (https://groups.google.com/g/firebase-talk/c/cJjo9oknG6g/m/XG24x8SqEgAJ) which talk about how to implement this behaviour. The two main options presented are:

  1. Use Firebase Realtime Database to build your own real-time "push" mechanism to detect revocations
  2. Use currentUser.getIdToken(true) to force-fetch a new id token, which will detect the refresh token revocation, and log the user out (you should get an even on the onAuthStateChanged listener).

For option 2, note the parameter true passed in to forceRefresh. This is generally not a good option - you don't want to force refresh on every API request, but if you don't, it's hard to know when to do a force refresh.

When you refresh the page, the Firebase client SDK will typically automatically perform a force refresh.

Server-side detection

When a user's ID token is to be verified, the additional checkRevoked boolean flag has to be passed to verifyIdToken. If the user's token is revoked, the user should be signed out on the client or asked to reauthenticate using reauthentication APIs provided by the Firebase Authentication client SDKs.

https://firebase.google.com/docs/auth/admin/manage-sessions#detect_id_token_revocation_in_the_sdk

Note that using the checkRevoked=true option results in a network request from your backend to Firebase's backend, which is expensive. Again, it's hard to know when it's worth using checkRevoked. Perhaps it's worth the cost to always perform the network check on a small subset of highly sensitive APIs.

Summary

You should read through the docs in full (https://firebase.google.com/docs/auth/admin/manage-sessions) and see which approach suits you best.

Frank van Puffelen has already covered the other standard option - using rules to guard Firebase backend services.

But in general, there isn't anything that helps out of the box. If you understand the concept behind refresh tokens and id tokens, you'll notice that it's fundamentally not possible to revoke the ID token while retaining the performance benefits (ie, reducing network traffic) that is the entire reason for using the refresh+id model to begin with.

I'd just let the token expire, and accept that any "disable" can be delayed by up to 1 hour.

Upvotes: 2

Frank van Puffelen
Frank van Puffelen

Reputation: 599166

A user that is signed in to your app has a ID token that is valid for up to an hour. Once that token has been created, there is no way to revoke it.

The typical way to handle your use-case is to also flag the user in a server-side database once you disable their account, and then check that flag in any operations.

For example, if your using the Firebase Realtime Database, and disable the user with Node.js, the code to also flag the user in the database could look like this:

// Disable the user in Firebase Authentication to prevent them from signing in or refreshing their token
admin.auth().updateUser(uid, {
  disabled: true
}).then(function() {
  // Flag the user as disabled in the database, so that we can prevent their reads/writes
  firebase.database().ref("blacklist").child(uid).set(true);
});

And you can then check this in the server-side security rules with something like this:

{
  "rules": {
    ".read": "auth.uid !== null && !root.child('blacklist').child(auth.uid).exists()"
  }
}

This rule allows all users that are signed in (auth.uid !== null) full read access to the database, but blocks users who you've flagged (!root.child('blacklist').child(auth.uid).exists()).

For an (even) more elaborate example of this approach, see the documentation on session management.

Upvotes: 3

Related Questions