amazon-archives / amazon-cognito-auth-js

The Amazon Cognito Auth SDK for JavaScript simplifies adding sign-up, sign-in with user profile functionality to web apps.
Apache License 2.0
424 stars 232 forks source link

Redirect to login screen when refresh_token expires #118

Open mymattcarroll opened 6 years ago

mymattcarroll commented 6 years ago

I would some some clarification on what should be happening in the SDK when a refresh_token has expired. I'm currently only testing this on my local machine but we have successfully implemented requesting and using a refresh_token to refresh id_tokens and access_tokens when the access_token expires.

We are currently experiencing some strange behaviour when the refresh_token expires. We have it set to only 1 day in the Cognito Console for development purposes and testing. When calling the getSession() function, the SDK gets to the makePOSTRequest() function which makes a request to the following:

POST https://{{my-domain}}.auth.ap-southeast-2.amazoncognito.com/oauth2/token
grant_type: refresh_token
client_id: {{client_id}}
redirect_uri: https://localhost:8080/callback
refresh_token: {{refresh_token}}

As mentioned above this request is always successful when the refresh_token has not expired yet. However, when it has expired the response status code is 400 and the payload is as follows:

{
  "error": "invalid_grant"
}

This results in the userhandler.onFailure() function being calling with that response passed as the only argument (and not as an object but as a string).

Is this the desired behaviour? I can see in the onSuccessRefreshToken() function (that only gets called if the response status code is 200), there is a check for an error property in the response payload and if it exists, the SDK redirects to the hosted login screen. Should the SDK being catching 400 response status codes and also redirecting to the hosted login page? It seems a bit unreasonable to have to handle expired refresh_tokens manually.

If developers have to handle expired refresh_tokens themselves, could the SDK be updated (happy submit a pull request if required) to call the userhandler.onFailure() function with an Error object instead of a string.

kocur4d commented 5 years ago

@mymattcarroll did you get anywhere with this? I just got a same problem with users being hit with "error": "invalid_grant" and the only available fix it is to clear local storage.

mymattcarroll commented 5 years ago

@kocur4d The only thing I could do was to check for the "invalid_grant" and then redirect to the login page.

mymattcarroll commented 5 years ago

Possible duplicate of #183

kocur4d commented 5 years ago

@mymattcarroll

The only thing I could do was to check for the "invalid_grant" and then redirect to the login page.

There is a small problem with this approach, maybe it is not common so it is not really a problem. The "invalid_grant" can happen anytime so we can have a situation when user opens a page starts doing something and after an hour he gets redirected to the login screen, because the refresh token expired during that session and he couldn't refresh his id token.

I found a bit better solution last night, I think.

The access token when decoded have field "auth_time" which is the time when the user authenticated last time.

What I can do is to add a small function on the page load and check if that time is longer then lets say 20 days and log user off and redirect to login page if it is.

That would provide a bit better experience because it would only force relogin on a page refresh.

What do you think?

mymattcarroll commented 5 years ago

Our application is an SPA, so we cannot rely on page refreshes. However, checking auth_time might be a bit cleaner than attempting a refresh and catching the error. Only small issue is that the application must know how long the refresh token lasts instead of just checking an expired property. I personally like that the refresh token expiry is configured outside of the application code.