-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cognito.user.signOut() does not invalidate tokens #3435
Comments
@jiachen247 Cognito issues short lived bearer access tokens (valid up to 1 hour). The access tokens are short lived (up to 1 hour) and Cognito has GlobalSignOut Api to invalidate all tokens issued in past. If you are using the cognito-identity-js sdk directly, then the cognitoUser.globalSignOut(callback); |
@mlabieniec Thanks for your response! yes and no actually. Its closer but its still different. Global sign out invalidates all open sessions. For example, lets say I log into the webapp and a mobile app both use Cognito for authentication at the same time. On global signout, both will get logged out. However, signout should just invalidate that particular session on the client side as well as the server side and not touch the other open sessions. That makes the most sense on reading the docs for the function is intended for. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
I could not agree more with @jiachen247. I have the same situation of mobile and app usage and the session should be invalidated for each one separately. What actually concerns me more is the fact that I can still use the token after using the "signOut" method of @aws-amplify/auth. |
Yes, i am facing the same issue. I am using Auth.SignOut({global: ture}) and it is kicking user to login page of that particuler window. If i open the app in another tab in the same window / access the app from other browser or machine they still find a valid user object from id token. I can still get hold of the application. I am looking for a solution where if i logout from other tab and come back to another tab and do any operation, it should kick me back to login page. Any workaround solution for this? |
Is there some API endpoint we can hit to invalidate a single Refresh token? There must be some middleground available.... |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
We are all waiting for it to be fixed. |
Any news on this? It seems ridiculous that you can't invalidate a single set of tokens on the back end. |
any updates from? |
Is there someone to actually answer these issues/questions? Too frequently I see only tags added and more people writing they have the same problem. No actual support whatsoever and that's sad. I also need the ability to:
|
We encountered the same problem with the AWS Cognito PHP SDK. It seems the documentation is clear for the AdminUserGlobalSignOut function :
A much-needed feature would be to invalidate all tokens on AdminUserGlobalSignOut. Our use case : a user password as been changed by an admin or user, thus the user should be logged out automatically. By the documentation, the user would only be disconnected one hour after... |
By their nature, there is no mechanism to invalidate an access or id token. The likely solution for your scenario is to track any revoke token events in your app. Then, as part of your token validation process, you can check to see if you've revoked that specific token and if so not authorize the request. You could maintain a database table of revoked tokens, cache the values for performance and have a hygiene process to remove expired, revoked tokens. Your use-case / scenario is different from the original issue. |
That's my understanding of JWTs as well. However, I've seen evidence that Cognito tracks individual access tokens. If you do a global signout, but save your JWT tokens, and then try to hit another Cognito endpoint (like "global signout" again), you'll get a 400 with the message |
I thought that when you do Global Signout, secret key(or private key and with that also public key) is changed and every token that was created before calling Signout is invalid. That would mean that validation of each issued token fails. But only thing that is invalid is refresh token. Access token and ID token remain valid until their expiration. More here: Beside that, there is no way to invalid token. You can only wait for token to expire and become invalid. There is a way to track by yourself which tokens should be revoked(after user logout put that token in database) and to check every time if token that is being used currently is in that database(that means it's invalid) or not(it is valid). But by doing this, you are loosing tokens stateless feature. More about this you can find here(maybe best approach gave Ashtonian): This is the best way to deal with everything in Cognito: |
Facing the same issue with cognito-identity for JS. |
Only way(for now) that is verified from AWS technical support team is explained here: So, idea is to user CognitoIdentityServiceProvider. More about all its methods here: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html CognitoIdentityServiceProvider.globalSingOutUser(accessToken) revokes access token So, in your case, each time when user sings out(logs out) from application, you should call this globalSingOutUser(accessToken) method. And in case you want to check if user is singed out or not(if token is revoked or not) you should be checking also access token using this getUser(accessToken) method. That should be done before calling API Gateway. And if you are worried about someone calling API Gateway with just ID token, you can add this check inside for example Lambda(if API Gateway is calling Lambda afterwards). I don't know whole scenario that you are facing with, but you can find some workaround with this. |
Thanks @maros96 for the detailed explanation. However, when I tried using accessToken as the Authorisation header to connect with API gateway, my API call failed with 401 -Unauthorised. The same call works fine while sending idToken in the Authorisation header. The AWS doc here says we can use either of idToken or accessToken. Is that correct. Can you suggest any cause for this behaviour. |
Yes, thing is that Authorizer can depend on ID Token OR Access Token, but implementation of Authorizer is not the same for those 2 cases. You've created your authorizer to use ID Token. If you want to change it to use Access Token, you have to change firs implementation of authorizer and then put accessToken in Authorization header. That is why you get Unauthorized when you pass accessToken - Authorizer expects ID Token instead. On that link you've sent, on the end, you have links for doing everything in steps(obtain permissions, first create Cognito User Pool, ...) and you should read Integrate a REST API with an Amazon Cognito User Pool. So, you can try to implement Authorizer to use Access Token(I've never done that and I am not 100% sure that in case that Access Token is revoked, authorizer will return Unauthorized or will let you use your API, but you should try that). You can try that and after testing that, put a comment here for everyone else, including me, to see how does that work :) In case you don't manage to do that, you can still use ID Token for authorizer and call CognitoIdentitiServiceProvider.getUser(accessToken) after calling API Gateway and before doing everything else. Put that check between API Gateway and rest of your application. For example, as I suggested in previous comment, if you call Lambda from your API Gateway, you can first do this check in Lambda and in case access token is revoked, return error status with message "Access Token is revoked". Otherwise you just continue with Lambda execution(which means that access token is valid). One more thing, in case access token is invalid in any sense(expired, wrong token use, revoked, signature is not the same as decode(hash(header.payload), publicKey) - which means that someone has change something inside that token), this getUser(accessToken) method will return error. If token is valid, it will return some user data. So, you are not just checking if token is revoked, you are also checking whole validity of Access Token. |
We still need a way to invalidate an individual refresh token. I don't want to use Global Sign Out because a user might want to be signed in on multiple devices but just want to sign out of one specific device. It would be a poor user experience. The current system relies solely on each device just "forgetting" the refresh token if a user logs out on that device. This is not a very secure or reliable way to discard refresh tokens because the tokens themselves remain usable. If you do the forgetting wrong, then the user stays logged in without realizing it. API calls using the "logged out" session still return 200, and so forth. |
Hi @jpignata and @sammartinez, it sounds like you are from AWS. As per my post from before, I upgraded all packages to the latest version, but the individual invalidation of a refresh-token doesn't work; there is no client-side call visible, as compare to "global: true", where you can clearly see the call of invalidation in Network commands. Can you please confirm:
|
@ramburg make sure that you have enabled token revocation for your user pool client(s). I didn't see the client-side calls until I did this. |
@sethhitch thanks for highlighting! There should be also a hint about it in the Amplify docs https://docs.amplify.aws/lib/auth/emailpassword/q/platform/js/#re-send-confirmation-code near "Amazon Cognito now supports token revocation and Amplify (from version 4.1.0) will revoke Amazon Cognito tokens if the application is online." in order to ensure this is clear. |
Hi @sethhitch How to verify if the option is enabled in the pool? From what I read, the option should be enabled by default. |
It is enabled by default only for newly created user pools (after Jun 11th or so). |
@KristobalJunta @sethhitch Thanks. So with https://aws.amazon.com/about-aws/whats-new/2021/06/amazon-cognito-now-supports-targeted-sign-out-through-refresh-token-revocation/ - just the refresh token is revoked, the existing idToken and accessToken continue to be valid-This is what I am reading in comments BUT here https://docs.aws.amazon.com/cognito/latest/developerguide/token-revocation.html it says Which one is it? Are access tokens revoked or is that not the case? |
@s1mrankaur my experience is consistent with the AWS documentation at https://docs.aws.amazon.com/cognito/latest/developerguide/token-revocation.html
So if you try to use an access token associated with the revoked refresh token to make a Cognito API call like |
I'm asking because i am implementing my first backend authentication flow... would it be a big security issue to just let the token expire? whereas the token expires in 60 minutes. Currently what I do is clear the localstorage that holds my token, and every request my endpoint receives depends on receiving the token in the autorization bearer, so without the token in the localstorage the user will have to log in again to use the endpoint again. Someone mentioned a problem with tabs, the point is that using localStorage is different from using sessionStorage, since localStorage shares the token between tabs, so if I clear localstorage in one tab, the other tab won't be able to use the token anymore because it was cleaned. But of course it's important to invalidate the token on the endpoint, I'm just asking if there are other situations to consider besides the problem with tabs. |
@leonardopaiva the issue people are running into now is an issue inherent to the design or Json Web Tokens. The design goal was to have something that could be issued by a Security Token Service and then validated without a micro service needing to call the STS to validate the token. To do that JWTs are cryptographically signed with an expiration date. The micro service can validate the signature, check the expiration, and say “yep token is still good, off you go to what ever protected resource”. The “fix” is to identify super critical resources and have that service validate the JWT with the STS. Most of the time, a lag of 5 to 60 min won’t matter. Adding items to a cart for example. Checking out is an example where you would want to validate the token with the STS. |
@RubberChickenParadise that's an excellent, clear description of the inherent design challenge here, and it highlights the big remaining gap in the Cognito feature set - the ability to explicitly check a token for revocation when the risk is high. Obviously this is possible, since the Cognito APIs reject JWTs associated with revoked refresh tokens. I'd love to see an API that let the rest of us check revocation as well. |
I'm having a problem where a user logs out in a browser extension, invalidating their access token which is shared by the website associated with the extension. The token is successfully revoked, however the Auth API doesn't seem to know what to do when it gets an error from the API. Ideally the amplify/cognito/auth library would react to this error automatically by removing the access token from storage and logging the user out, since they clearly aren't logged in anymore. Instead my user is stuck in an in-between state where they're "logged in" but calls to |
This is unbelievable! API Gateway :(( |
Still facing this issue, do we have a proper solution for it? |
why don't you use different app clients, for mobile and web separately ? that's why there are app clients, no? |
Because from a user experience point of view it's super lame to ask a user to sign in twice in the same browser, once to your extension and once to your website (in my case) |
Solid suggestion. |
With these items you can revoke a single refresh token RevokeTokenCommand https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RevokeToken.html Here you can see how the implementation is: |
@murdaneta This is providerClient variable: Do I miss something? |
From 2019 to 2023 & this is still an issue |
use supabase |
Working workaround: (even if the Cognito team would invalidate |
At this point, AWS should just let us in and do it for them. |
Still an issue in 2024. If this issue were a child, I would be sending it to its first day of school soon. |
Is this seriously still not addressed? AWS support said this is "expected behavior." For the life of me, I cannot figure out how this could possibly be as designed. @sammartinez why was this closed? Linking to this comment for my own sanity. |
Lots of information have already been said here, I'd just like to add that the Amplify's documentation makes it seem like the token revocation happens if you call But this is not quite I'm looking for, I don't necessarily want to log out the user from their other devices, I just want a SDK call for this endpoint: https://docs.aws.amazon.com/cognito/latest/developerguide/revocation-endpoint.html, which is a functionality that AWS added only in 2021, but this issue was closed in 2019, so as far as I can tell it wasn't really implemented, or at least for some reason it was blended with the global sign out unnecessarily—there's also an use case for a separate endpoint or parameter where I can do a local sign out, revoking the local refresh token, leaving the global ones untouched. @HuiSF @ashika112 @israx it's been years since the last AWS employee last commented here, are you able to shed a light here with a plan for this to be addressed? Should a new issue be created or could this be possibly reopened, or better clarified? |
Hey folks in the thread 👋 As @rdsedmundo and others have mentioned, calling In versions 5 and 6 of the |
Describe the bug
On calling
state.cognito.user.signOut()
, session tokens are just removed localstorage.The actual access tokens and refresh tokens are still valid for the lifecycle of the token.
Expected behavior
This is a security issue. Best practice dictates session tokens should be invalidated server side on a logout request not just deleted on the client. (OWASP session management)
Source Code found here
https://github.com/aws-amplify/amplify-js/blob/68a5ad2fe2b1d9f03cce80d1bf449e454b621760/packages/aws-amplify-react/src/Auth/SignOut.jsx
The text was updated successfully, but these errors were encountered: