Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is storing aws cognito JWT key in frontend javascript insecure?

I was reviewing a website's javascript files to find an endpoint i wanted,during this i found a line like this.

DASHBOARD_API_Token=eyJraWQiOiJVS2paTnB3SWdBK292QzB3RWdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

When i decoded the Above JWT i found entities like kid, username, useremail, iss = http://cognito-idp.us-east-1.amazonaws.com/{pool-id}

I have read few amazon resources which tell that its possible to fetch aws credentials using the above token. Given that i only have the jwt token what is possible and is it that i have to contact the website to revoke the current token?

like image 843
StackB00m Avatar asked Dec 17 '22 23:12

StackB00m


1 Answers

Well, AWS Cognito is quite an interesting beast when it comes to its JWT tokens and what you can do with them.

Firstly, when you authenticate the user against Cognito User Pool, you get 3 different tokens: AccessToken, IdToken, and RefreshToken. Both AccessToken and IdToken are valid for exactly 1 hour (and you can't change it). This is why you get RefreshToken, which you can use to get new pair of AccessToken and IdToken by calling, for example, InitiateAuth. RefreshToken is by default valid for 30 days, but you can change it in the settings of your Cognito User Pool.

AccessToken

This is the most powerful token that is given by Cognito. If you possess a valid AccessToken, you can call several quite sensitive Cognito APIs.

One very surprising example is that you can call DeleteUser API by providing AccessToken and it will completely remove your account from Cognito User Pool. The "nicest" thing here is that app developer can't stop you from doing it if you've got a valid AccessToken. AWS devs are saying that "its by design". That was one of the strongest reasons why we decided not to pass Cognito Access Token onto the application frontend.

Speaking of the payload of AccessToken, the only potentially sensitive claim is the client_id, which contains the Cognito Client Id, which was used to authenticate the user. If this client does not have a client secret (which should probably be considered a security flaw in the first place), then the client_id can be used to call quite wide range of Cognito APIs. However, Cognito considers client_id to be public information. All other claims are considered public, you can see the full list of claims here.

IdToken

Contains the information about the player. It may contain some personal information about the player depending on what standard claims and custom attributes were configured in your Cognito User Pool, however it is also possible to suppress or override those claims using Pre Token Generation Lambda Trigger. Using this trigger allows one to hide or mask player attributes, which are considered sensitive and should not appear in IdToken.

As far as I'm aware, you cannot user IdToken to call Cognito APIs.

RefreshToken

Can only be used to request new AccessToken and IdToken, cannot be used to call Cognito APIs. In our particular use case we had to avoid passing RefreshToken to the app frontend, since it can be used to get AccessToken against public Cognito API (meaning that we cannot stop the user from doing that).

Using Cognito tokens to get AWS credentials

This is only possible if Cognito User Pool has been explicitly integrated with Cognito Identity Pool (which assumes that app developers knew what they were doing). When you exchange your Cognito JWT tokens, you get temporary AWS credentials with permissions bounded to a specific IAM role configured in Cognito Identity Pool. It is completely legitimate flow and intended behaviour. Moreover, if Cognito Identity Pool is configured to allow unauthenticated access, you can even get temporary AWS credentials without having Cognito JWT tokens (but those will be tied to another, presumably, more restrictive IAM role).

Using Cognito tokens with API Gateway

AWS API Gateway resources can be integrated with Cognito User Pools. Depending on how the integration is done, you can use either an AccessToken or IdToken from the integrated Cognito User Pool.

Revoking the tokens

You can revoke all tokens issued for your account in Cognito User Pool by calling GlobalSignOut API and providing a valid AccessToken. As this API is public, you don't need to contact the website if you possess a valid AccessToken.

like image 53
Dmitry Deryabin Avatar answered Jan 05 '23 01:01

Dmitry Deryabin