Amazon-cognito-identity-js: Security / Best Practice for poolData (UserPoolId, ClientId) in a browser JS app

Created on 26 Feb 2017  路  20Comments  路  Source: amazon-archives/amazon-cognito-identity-js

I have a simple browser JS app (using React) nearing completing to test using AWS Cognito Identity JS as the auth platform. Throughout the examples here the UserPoolID and ClientId is set using a poolData variable like:

var poolData = { 
  UserPoolId : '...', // Your user pool id here
  ClientId : '...' // Your client id here
};

When you build a browser JS app, of course these values are visible on the client-side JS.

If you use PHP/.NET for auth, those values would not be visible on the client-side, so they are private and not distributed.

My question, in JS (using amazon-cognito-identity-js) - is it ok for these values to be public?

My experience of building with security in mind is paranoid about those being available client-side. What is preventing a malicious script from using those details and, say, registering multiple users (DDoS style)? Ok those users would need to be verified/MFA so those accounts won't necessarily get access to an app, but there could be a lot of un-requested signups that might cause a problem.

I've searched through documentation, but can't seem to find this being discussed. Excuse me if the answer is obvious - this is my first project experimenting with AWS Cognito.

Thanks in advance all.

Most helpful comment

I asked this same question on the forums. Don't know if it helps but you can see the answer here. Basically, the user pool ID and client ID can only be used to call unauthenticated APIs (sign up, authenticate, reset password, etc). Still, exposing any IDs that could potentially bring an attacker one step closer to getting credentials makes me nervous. Enforcing MFA and securing tokens in transit and in storage seem like reasonable security measures.

All 20 comments

I asked this same question on the forums. Don't know if it helps but you can see the answer here. Basically, the user pool ID and client ID can only be used to call unauthenticated APIs (sign up, authenticate, reset password, etc). Still, exposing any IDs that could potentially bring an attacker one step closer to getting credentials makes me nervous. Enforcing MFA and securing tokens in transit and in storage seem like reasonable security measures.

Thanks, reading that AWS themselves consider the poolData being public helps. Although I can't help but wonder how to stop the even the unauthenticated APIs from being abused. Further AWS security products I expect for a production app.

Secure tokens in transit and storage were on my radar as I move forward to a more complex app, but also good to hear and thank you for the link.

Just to add, you should be serving the website from HTTPS only.

SSL definitely agree. That would protect the poolData variables, responses and future API calls in transmit.

It's worth noting though that SSL wouldn't prevent a DDoS style attack using the initial poolData details (that are in plain text in the code) and the unauthenticated APIs. We would have to use the advanced MFA and verification components of Cognito as a way of block malicious/fraud account signups. Furthermore, we would need to write clear instructions in the verification/notification emails/SMS sent to account signup email addresses, to help prevent people from verifying accounts they didn't request.

Just wanted to note that we do have throttling in place on a number of variables. However, I cannot comment on the exact specifics.

Thanks for the info, so there are various things that together achieve as much protection as is possible for client-neutral unauthenticated APIs.

Precisely. Closing the issue, feel free to reopen if there are any more questions.

I just got into this issue with the same question, i can agree about user pool id being public. But I just managed to delete a user with the aws-php-sdk : v3, without any credentials, i don't know if it's a cognito-wide issue or it's only an issue for aws-php-sdk.

I deleted the user using the following code

$client = new CognitoIdentityProviderClient([
    'region' => 'us-east-1',
    'version' => '2016-04-18'
]);

$client->adminDeleteUser([
    'UserPoolId' => '[POOL_ID]',
    'Username' => '[USERNAME]'
]);

I even could listUsers

$result = $client->listUsers([
    'UserPoolId' => '[POOL_ID]'
]);

There's no way that worked without credentials; in your example it must have used the credentials stored under ~/.aws

Yes, @hassankhan, that was happening, tried on a clean server. Credentials were being taken from external profile.

Hello, I just started using this Cognito SDK and, first of all, thank you for providing it. Regarding security I was reading the documentation and the code wondering if store the tokens in local storage is really secure. Looking at the links provided by gitjeff05 and others about best practices to store tokens it seems a bit confusing to me since I saw that the local storage isn't the most appropriated place to keep them (some suggested using Cookies). Forgive my lack of knowledge, I started using the SDK just a few days ago . How would be the best way to handle this?

That has changed since then and you can pass whatever storage mechanism is most appropriate for your use case in the constructor objects for CognitoUser and CognitoUserPool.

I see. Thank you for the answer. Are there any examples showing this?

Check out the following pull request:

https://github.com/aws/amazon-cognito-identity-js/pull/363

I'll check, thank you.

From the forum link posted by @gitjeff05...

So userPoolId and clientId alone are not enough to do any malicious activity on your user pool. Using SSL should be good to cover the tokens in transit.

@itrestian and anyone else, am I right to assume that the Identity Pool ID being exposed publicly would be covered by the above statement as well. As in, if someone trawled your Javascript source code, no malicious activity could potentially result from that person gaining access to the User Pool ID, Client ID and Identity Pool ID?

I think I already know the answer, but when it comes to security it's always nice to hear it from other minds.

I also have concerns about exposing clientId and poolId. Say if someone takes my clientId and poolId and make a fake site that looks very similar to my site, and trick users to login with their email and password. User will be able to successfully log in, because the clientId and poolId is correct. Then after user log in, the fake site can run any program using the user's credential, like reset password, access database, s3, etc. Does cognito user pool has such mechanism that only allow requests from whitelisted domain? This will solve the above problem. @itrestian

As I understand it, you can avoid this situation by using the Hosted Cognito Login pages, since there you can specify allowed callback URLs. Not sure how to replicate the functionality within my own apps though.

@lina128 You could enable MFA on your user pool to mitigate the risks associated with stolen usernames/passwords. As far as whitelisting a domain, one strategy would be to use Gateway API -> Lambda proxy instead of the AWS SDK on the client. With Gateway API, you can enable CORS and restrict calls to a certain domain by setting the 'Access-Control-Allow-Origin' header. I believe you would then change your permissions policy to give your users permission to invoke the API, but not give them permissions to write to the db, s3, etc.

Cognito also has some other security features like triggers and the new Advanced Security feature that are worth checking out.

@gitjeff05 , thank you for the lengthy explanation. I did try triggers, problem is I cannot get header.origin from event. If header.origin can be added to the payload that is passed to lambda, then it will be perfect. I can still use client side auth, and with triggers I can make sure the request is sent from whitelisted domains. Will the team consider adding this feature?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

johnf picture johnf  路  3Comments

guyb1 picture guyb1  路  4Comments

m-schrepel picture m-schrepel  路  6Comments

ZwaarContrast picture ZwaarContrast  路  4Comments

kaihendry picture kaihendry  路  4Comments