amazon-cognito-auth-js icon indicating copy to clipboard operation
amazon-cognito-auth-js copied to clipboard

Refresh access and id tokens in a React/Angular SPA

Open ravenscar opened this issue 7 years ago • 39 comments

Summary

I would say that without Cognito implementing prompt=none on the /oauth2/authorize endpoint, and whilst the cognito cookie on <your_domain>.auth.<region>.amazoncognito.com/ expires after 60 minutes instead of 30 days (or what is set for the user pool) it is unsuitable to be used as an out-of-the-box solution for Single Page Applications.

Details

The recommended OAuth2 flow for a Single Page Application (SPA) is the Implicit Grant. This flow, by design, does not issue a refresh token to the web app.

There are many issues in this project around refreshing tokens that seem to be resolved by switching to Authorization Code Grant instead, which is OK for some native apps and some non-SPA web apps (e.g. where there are round trips to a server) but is unsuitable for SPA apps.

It is considered unsafe and bad practice for a web application to store a refresh token in session storage, local storage, or in javascript accessible memory as this opens up the app to many attacks which could result in the refresh token being exposed to a malicious third party which is now able to obtain ID/API tokens for the user.

The OpenID Provider (OP) usually sets an http only secure cookie on user login, and this is used for refreshing in this case the OP is awscognito and the cookie would be set on <your_domain>.auth.<region>.amazoncognito.com/. Cognito does set this cookie.

The typical process for refreshing tokens in an SPA is to call the OP's authorize endpoint with a prompt=none in the query string. This would normally occur in an embedded iframe in the SPA so as to not alter the UI and would either return new tokens which can be stored or an error, which deletes the tokens.

This is not a standard or requirement as it is up the the OpenID Provider to determine how a user is authorized, however if this is not implemented and it means that an SPA must choose to log in whenever the access token expires, or to adopt poor practices and store refresh tokens in the SPA (there is another option where we could have our own server which stores the refresh tokens and can refresh api/id tokens and deliver them to the SPA).

This partially works using cognito hosted UI, there is a cognito cookie stored when you login at <your_domain>auth.<region>.amazoncognito.com/login?client_id=<your_client_id>&response_type=token&redirect_uri=<your_redirect> and if you subsequently call <your_domain>auth.<region>.amazoncognito.com/oauth2/authorize?client_id=<your_client_id>&response_type=token&redirect_uri=<your_redirect> it will redirect with new tokens, with updated timestamps, without requiring interaction.

Unfortunately the cognito token expires after 60 minutes so it can only be used to extend the session to a maximum of 120 minutes. Also since the prompt parameter is not implemented there is no way for the iframe to get an error so it cannot be used in an iframe.

References

ravenscar avatar Feb 20 '18 09:02 ravenscar

Any thoughts on this? It seems to me that it makes implicit grant totally impractical to use.

hhp21 avatar Feb 23 '18 17:02 hhp21

I'd prefer if AWS allows the configuration the id_token and session cookie expiry TTL based on your own requirements.

a053a avatar Mar 01 '18 21:03 a053a

This seems like a deal breaker for using Cognito User Pools for SPA development. I am seeing the cognito cookie valid for 8 hours though now, so that is a little better. I agree though that without the prompt=none option, the re-authorize cannot be transparent to the user.

cervantek avatar Jul 02 '18 18:07 cervantek

Why there is no response from aws team on this??? This is making implicit flow absolutely useless. I am not sure how @cervantek got cognito cookie to work for 8 hours. I see only 1 hour, so you are stuck with maximum 2 hour for tokens if you do a workaround and make a call to oauth2/authorize endpoint for hosted login.

ppasmanik avatar Jul 09 '18 21:07 ppasmanik

Wondering the same thing! This is a MUST feature for any real-world use.

luomavaltteri avatar Jul 11 '18 09:07 luomavaltteri

This seems to be a vital feature for user experience. @cervantek do you have details on how to increase the cognito cookie timeout? Though even that would not fully solve the issue.

gercorr-gw avatar Aug 01 '18 15:08 gercorr-gw

The document that you referenced assumes that refresh tokens last indefinitely, but I believe that with Cognito User Pools you can configure the refresh token TTL

I don't know what security experts think about e.g. reducing the refresh token TTL to 1 day and storing it in the local storage of a SPA, but it seems no worse than increasing the TTL of the access token.

nihakue avatar Aug 01 '18 19:08 nihakue

AWS needs to implement this properly by giving us the ability to configure cognito cookie timeout. If implemented, then using a proper Oidc JS library would get a new id_token and token periodically.

a053a avatar Aug 01 '18 20:08 a053a

We need this feature too

Beretta1979 avatar Sep 11 '18 09:09 Beretta1979

I agree with @nihakue . After talking to AWS team we went with that solution - setting refresh token ttl to 1 day, and doing refresh token every hour with auth code flow.

ppasmanik avatar Sep 12 '18 13:09 ppasmanik

@ppasmanik @nihakue Although this is technically possible, it’s considered bad practice to store refresh tokens for SPA apps. AWS really needs to close in on this so they don’t keep putting applications at risk.

a053a avatar Sep 12 '18 14:09 a053a

Could someone from the AWS team respond to this? Came across this issue whilst trying to implement silent refresh. I am now considering moving away from Cognito to something that supports the implicit flow better for SPAs.

rajwilkhu avatar Sep 26 '18 11:09 rajwilkhu

Could someone from the AWS team respond to this? Came across this issue whilst trying to implement silent refresh. I am now considering moving away from Cognito to something that supports the implicit flow better for SPAs.

@rajwilkhu It's been very quiet for a long time. Choose something that supports silent refresh.

luomavaltteri avatar Sep 26 '18 16:09 luomavaltteri

While this may sound (very) crazy. What if the refreshToken had a more granular TTL, such as minutes or hours. Wouldn't this get us slightly closer to a silent auth/refresh solution?

maziarz avatar Oct 16 '18 15:10 maziarz

@maziarz while it might help, it's actually the wrong solution. Refresh tokens shouldn't be used in SPA apps; rather, use the session cookie controlling the refresh, e.g. cognito to use session cookie to see if session cookie is still valid and reissue another token and update session cookie if warranted.

a053a avatar Oct 16 '18 15:10 a053a

@salmonz its not that i disagree, i ran into this problem 1.5 years ago and ended up implementing Cognito with passport.js in the back utilising secure cookies. But eventually it removed all benefits from being truly "serverless" and having low maintenance on a SPA. I do not believe that anyone has solved this issue in an elegant way, even auth0 is relying on a valid SSO session in order for this to actually work with prompt=none. It does not look like Cognito team are going to introduce a cookie mechanism any time soon..

maziarz avatar Oct 16 '18 16:10 maziarz

AWS - do you have an update on this issue? Seems to me that the sign-in cookie expiry should be configurable in the AWS portal for a cognito instance, or per client configuration.

a053a avatar Dec 05 '18 03:12 a053a

Any update on this?

adlaika avatar Jan 11 '19 22:01 adlaika

Any updates??

carvercj avatar Feb 13 '19 11:02 carvercj

Any progress on this?

vanpra1 avatar Feb 18 '19 18:02 vanpra1

any updates?

valecarlos avatar Mar 04 '19 20:03 valecarlos

+1 for silent renew support on implicit grants

AshUK avatar Mar 15 '19 20:03 AshUK

Sub'd, this is a deal breaker for using cognito user pools with SPA, would be nice to hear something from AWS.

dpistole avatar Mar 17 '19 22:03 dpistole

AWS: please give us some sort of update on this issue? What workarounds can you propose for SPA apps, do you have any plans to deal with this? The silence is deafening!

sjbthfc2 avatar Mar 25 '19 16:03 sjbthfc2

I guess we'll have to use Auth0 again.

jeremiahsmall avatar Apr 16 '19 00:04 jeremiahsmall

The typical process for refreshing tokens in an SPA is to call the OP's authorize endpoint with a prompt=none in the query string. This would normally occur in an embedded iframe in the SPA so as to not alter the UI and would either return new tokens which can be stored or an error, which deletes the tokens.

The iFrame flow does not work on the latest Safari. Auth0 warns about it here: https://auth0.com/docs/api-auth/token-renewal-in-safari

So I guess all we have left is

there is another option where we could have our own server which stores the refresh tokens and can refresh api/id tokens and deliver them to the SPA

sebastienfi avatar Apr 19 '19 21:04 sebastienfi

I agree with @nihakue . After talking to AWS team we went with that solution - setting refresh token ttl to 1 day, and doing refresh token every hour with auth code flow.

@ppasmanik Can you please elaborate?

sebastienfi avatar Apr 19 '19 21:04 sebastienfi

@sebastienfi

I believe they are using the Authorization Code Grant instead of the Implicit Grant to get a code that can be exchanged for a refresh token, storing the refresh token in the SPA, and refreshing the access/id tokens hourly.

Storing the refresh token client side in a web app would normally be considered very insecure however they have limited the lifetime of the refresh token to 24 hours, which is a tradeoff they have had to make as AWS provides no silent auth.

I guess the upshot is that users would have to authenticate daily rather than hourly.

ravenscar avatar Apr 23 '19 00:04 ravenscar

@ravenscar Thank you for mentioning me - and for these clarifications!

sebastienfi avatar Apr 23 '19 08:04 sebastienfi

@ravenscarhttps://github.com/ravenscar You are correct. The cognito-auth-js library provides various APIs to get refresh token, session, etc. It stores them in local storage. We wrote a small library that wraps amazon-cognito-auth-js and provides React components that know how to handle both types of the flows depending on configuration, perform refresh of tokens using oauth2/authorize endpoint of hosted cognito at configurable intervals (between 10 and 55 minutes depending on user roles). The minimum refresh token ttl is 1 day for cognito pool and it is sufficient for our users. You can set it to longer if you need. We also integrated idle timeout into that library that logs a user out after a configurable time interval.


From: Sébastien Fichot [email protected] Sent: Tuesday, April 23, 2019 4:39 AM To: aws/amazon-cognito-auth-js Cc: Pasmanik, Paul; Mention Subject: Re: [aws/amazon-cognito-auth-js] Refresh access and id tokens in a React/Angular SPA (#92)

@ravenscarhttps://github.com/ravenscar Thank you for mentioning me - and for these clarifications!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/aws/amazon-cognito-auth-js/issues/92#issuecomment-485700128, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AA2674YCPIHPLQLU5RAIQXTPR3DKTANCNFSM4EROSASA.


The information contained in this electronic transmission is intended only for the use of the recipient and may be confidential and privileged. Unauthorized use, disclosure, or reproduction is strictly prohibited and may be unlawful. If you have received this electronic transmission in error, please notify the sender immediately. In order to make sure you receive our emails with the latest news on Dante, please add [email protected] to your contact list.

ppasmanik avatar Apr 25 '19 14:04 ppasmanik