firebase-js-sdk icon indicating copy to clipboard operation
firebase-js-sdk copied to clipboard

Auth User Token still works after logout

Open polyglotinc opened this issue 8 years ago • 28 comments

  • Operating System version: OSX 10.12.6
  • Firebase SDK version: firebase 4.3.0
  • Firebase Product: auth

Describe the problem

When I reload my Angular-4-based webpage, I reacquire the Firebase user token, via:

firebase.auth().onIdTokenChanged( user => {
    if (user) {  user.getIdToken().then( (token:string) => {
        ...save token...
    })
})

and I have access to my password-protected Firebase database. However, this still works after I have logged out, via:

firebase.auth().signOut();

How can this happen? How should I be logging out if that is not correct? How do I get a status back from signOut()?

polyglotinc avatar Sep 12 '17 13:09 polyglotinc

signOut() returns a promise which you can monitor for completion.

What exactly is it that still works after signing out? Using the SDK normally surely would not. But without a minimal and complete repro here it's hard to say what you're getting at.

If you're manually managing the Firebase ID token and passing that to a server process or something similar, the token is good until it expires (standard JWT). Since you've gone into DIY territory, it's your job to dispose of it when you want it to stop working, or wait for the expiration.

Note that I'm fairly sure you can manually revoke access from the admin panel, but that's a bit of a different process and probably not what you're looking for here.

katowulf avatar Sep 12 '17 16:09 katowulf

arrrg...i was doing a nice detailed reply, when I did a sanity check that it happens in safari too, and not just chrome...once I logged out in safari, I stopped getting the symptom on chrome. D'OH! (I was using the same login on both browsers). This smells really bad, but I'll leave this on the far back burner until I have the time to sort out the (now more arcane) steps to reproduce the actual problem.

polyglotinc avatar Sep 12 '17 19:09 polyglotinc

That does seem bad. Looking forward to getting some more repro steps!

katowulf avatar Sep 12 '17 20:09 katowulf

@katowulf This happens to me as well in an Emberfire App.

  1. I am logged in with more than one browser (Firefox & Chrome on Ubuntu)
  2. I logout in one browser
  3. The promise firebase.auth().signOut(); completes fine
  4. I refresh the App it thinks I am logged in still.

If I logout in ALL browsers I stay logged out after refresh.

brendanoh avatar Oct 19 '17 16:10 brendanoh

There was a small synchronization issue, which should be fixed in the upcoming 4.6.0 release. Though, I think your situation is different. The other issue happened only rarely.

bojeil-google avatar Oct 19 '17 18:10 bojeil-google

@bojeil-google what happens to ME and to @polyglotinc is the same so are you saying that OUR issue is really a "Multiple Browser signin prevents signout" issue?

brendanoh avatar Oct 19 '17 21:10 brendanoh

I meant, the issue that was solved by the bug I mentioned which was fixed in https://firebase.google.com/support/release-notes/js#4.6.0 Can you check after sign out that localStorage is cleared from the currentUser?

bojeil-google avatar Oct 19 '17 23:10 bojeil-google

@bojeil-google cc: @polyglotinc

  1. I am logged in with more than one browser (Firefox & Chrome on Ubuntu)
  2. In Chrome I see it is IN Local Storage
  3. I logout in one browser (Chrome)
  4. The promise firebase.auth().signOut(); completes fine
  5. In Chrome I see it is NO LONGER IN Local Storage
  6. I refresh the App it thinks I am logged in still
  7. In Chrome I see it is AGAIN IN Local Storage

brendanoh avatar Oct 19 '17 23:10 brendanoh

Hey @brendanoh, can you try testing with the latest version 4.6.0? I tested with Chrome and Firefox in a Linux environment and was not able to reproduce it with that version. I opened multiple windows, signed in in one and then signed out in the same one, refreshed and the user was still signed out.

bojeil-google avatar Oct 20 '17 02:10 bojeil-google

@bojeil-google

I am on 3.9 now as installed via EmberFire. I will try 4.6. Also, I am having the issue on localhost but I havent tested on a production domain.

brendanoh avatar Oct 20 '17 03:10 brendanoh

Wow, very broken api, im having the same issues.

AmitShah avatar Nov 03 '17 23:11 AmitShah

Hey @AmitShah can you provide more context on your issue? Is this regarding the user not signing out properly? As I mentioned, there was an edge case issue which we recently fixed. This should no longer be an issue. I am just not sure what exactly you are encountering as I can't replicate the above scenario described by @brendanoh. The topic title is confusing here. I want to clarify that a token will remain active until the end of its natural lifetime even after sign out. In fact, you can keep a reference to a user and then sign out. The user would still be functional but will stop being persisted as currentUser. This is the expected behavior. If you are having that user persist after sign out, please provide us with a way to replicate it so we can fix it.

bojeil-google avatar Nov 04 '17 03:11 bojeil-google

Thanks @bojeil-google for a bit of clarification. I didn't realize that a token would still be active until its natural lifetime expiration. So I was seeing my Java verification of ID Token was still passing even after signing out. That works for me. I can simply handle it on the client side. Thank you.

liester avatar Nov 27 '17 03:11 liester

Is there any progress on this issue?

Just to clarify is it expected for the user's auth credentials to persist in local storage after logout? and is it the client side job to removed credentials from local storage?

Thanks,

jhardin293 avatar Jul 08 '18 10:07 jhardin293

Should this issue be closed it looks like firebase has switched from local storage to IndexDb. This issue looks more current https://github.com/firebase/firebase-js-sdk/issues/449

jhardin293 avatar Jul 08 '18 10:07 jhardin293

For anyone looking for clean-ish workaround, you can append a query string param right before redirecting the user away using signInWithRedirect. Current page query params will be picked up by signInWithRedirect and will be carried back by the flow. Then, after user is redirected back, just check for presence of the parameter. If the query param is absent on page load, clearly the user did not come back from redirect flow and you can skip calling getRedirectResult entirely, thus avoiding the whole issue.

In addition however, I would expect sign out to be able to purge all user data from the browser, even if as optional API.

Addvilz avatar Mar 31 '19 15:03 Addvilz

I was facing similar issue. Below is the link which provides workaround,

https://groups.google.com/forum/#!topic/firebase-talk/gxBm0WKCuIY

nikhilbhalwankar avatar Apr 06 '19 04:04 nikhilbhalwankar

For internally tracking the clarification/update to the docs, b/156547460

MeghaB avatar May 14 '20 01:05 MeghaB

For anyone looking for clean-ish workaround, you can append a query string param right before redirecting the user away using signInWithRedirect. Current page query params will be picked up by signInWithRedirect and will be carried back by the flow. Then, after user is redirected back, just check for presence of the parameter. If the query param is absent on page load, clearly the user did not come back from redirect flow and you can skip calling getRedirectResult entirely, thus avoiding the whole issue.

In addition however, I would expect sign out to be able to purge all user data from the browser, even if as optional API.

The firebase realize auto auth from back result with session data, how to prevent that auto auth and signInWithCredential? This error persiste here.

joaoeudes7 avatar Jan 24 '21 02:01 joaoeudes7

logout simply doesn't "revoke" the idToken.

this is very bad and insecure. the expected behavior is that when the user clicks logout, it won't be able to use the token again. logout simply doesn't "revoke" the idToken.

  1. I copied the request (curl) of a regular request that requires auth
  2. logout
  3. execute the request with the "old" token
  4. request returns 200.

I even have "checkRevoked" set to true on server side

      const checkRevoked = true
      const decodedToken = await firebaseService.admin
        .auth()
        .verifyIdToken(idToken, checkRevoked);

EDIT

I was able to MANUALLY revoke the token by using this method: await firebaseService.admin.auth().revokeRefreshTokens(request.context.uid); not great, as I need to do an extra call to the server. but it's actually working as expected (only if you check have checkRevoked flag on verifyIdToken )

AlonMiz avatar Apr 16 '23 17:04 AlonMiz

Thanks for the update. You're right that logging out does not revoke the idToken automatically. we will document this in the reference docs.

prameshj avatar Apr 17 '23 17:04 prameshj

I'm sorry but this seems a really lazy "solution" to not fix a security risk and merely put an obscure, sure to be missed, note someplace that the logout function doesn't really logout. WHY ISN'T THIS REALLY BEING FIXED? AND, after all these years?! I wrote this bug report so many years ago, that I've been retired for 4 years already! (no, not joking)

On Apr 26, 2023, at 5:18 AM, prameshj @.***> wrote:

Closed #158 https://github.com/firebase/firebase-js-sdk/issues/158 as completed via #7253 https://github.com/firebase/firebase-js-sdk/pull/7253.

— Reply to this email directly, view it on GitHub https://github.com/firebase/firebase-js-sdk/issues/158#event-9098546891, or unsubscribe https://github.com/notifications/unsubscribe-auth/AASDJ7PP52F6K56ABSJJTYTXDCHYFANCNFSM4D2SRDQQ. You are receiving this because you were mentioned.

polyglotinc avatar Apr 26 '23 06:04 polyglotinc

Fair point. The documentation fix was needed at the minimum, but we can make it more easy to find. Revoking the idToken(including all id and refresh tokens for a given user) can be done using the admin SDK as called out above - https://github.com/firebase/firebase-admin-node/blob/294bffdd0b438ce9cd3a440fbadd40b52cfe0a6c/src/auth/auth-api-request.ts#L1514 does it.

Modifying signOut to revoke ALL idTokens and refresh tokens issued before that time is a breaking change and would not be the intended behavior. (user signed in on multiple devices, clicks signOut on device1, their login session on device2 is also lost). idTokens have a lifetime of 1 hour

I am reopening this, so we can document this behavior more clearly in the sign out sections of our documentation

prameshj avatar Apr 26 '23 18:04 prameshj

cc @kevinthecheung @prameshj

prameshj avatar Apr 26 '23 18:04 prameshj

Modifying signOut to revoke ALL idTokens and refresh tokens issued before that time is a breaking change and would not be the intended behavior. (user signed in on multiple devices, clicks signOut on device1, their login session on device2 is also lost). idTokens have a lifetime of 1 hour

agree about the above, but you need to revoke that specific refresh token and id token, not the whole tokens. so other devices using different tokens won't get affected

AlonMiz avatar Apr 29 '23 12:04 AlonMiz

agree about the above, but you need to revoke that specific refresh token and id token, not the whole tokens. so other devices using different tokens won't get affected

What's the most effective approach to accomplish this ^^ today?

This specific behavior appears to pose a security risk. After the signout() function is invoked, if the user retains the refreshToken, they are still able to generate a new access token using it. What is the optimal method to revoke both the refreshToken and accessToken for that specific session without impacting the user's session on other devices?

From the documentation if we follow the approach mentioned here, we would just revoke all the refresh tokens for that user. https://github.com/firebase/firebase-js-sdk/issues/158#issuecomment-1510436547

batflarrow avatar Feb 08 '24 12:02 batflarrow

Hi, I ran into this problem as well. Removing tokens across all devices is a very annoying experience. Firebase, can you please make the revoke function revoke only the token being used on the device?

ShaulAmranS avatar Feb 25 '24 10:02 ShaulAmranS

Same issue I am facing even after 5 years. I am calling firebase function using client SDK where I am checking "request.auth.uid" to find user state (before login). Even after calling "auth.signOut" idToken is sent in the request.

hkhamitk avatar Jun 27 '24 03:06 hkhamitk