I'm concerned that the AWS Cognito User Pools Javascript API doesn't seem to care which website requests are coming from (all you need to use the API are the User Pool ID and Client ID, which would be readily available in my javascript source).
Am I right to be concerned that another site could hijack my user pool, potentially tricking users into signing up to it?
If this is a valid concern, is there any way to prevent this? The pre-authentication Lambda payload doesn't seem to include any request origin data, so I guess that isn't the way to do it.
If it isn't something I need to be concerned about, why is that?
Choose (or create) a method on your API. Choose Method Request. Under Settings, choose the pencil icon next to Authorization. Choose one of the available Amazon Cognito user pool authorizers from the drop-down list.
A user pool is a user directory in Amazon Cognito. With a user pool, your users can sign in to your web or mobile app through Amazon Cognito. Your users can also sign in through social identity providers like Google, Facebook, Amazon, or Apple, and through SAML identity providers.
cognitoIdentityId as the user Id. This is the Id that a user is assigned through the Identity Pool. However, you cannot use this Id to look up information for this user from the User Pool. This is because to access your Lambda function, your user needs to: Authenticate through your User Pool.
So, I have contemplated this in great length and decided this:
Yes it's ok to have those digits on your front end.
Of course - for many reasons as follows.
Question:
Am I right to be concerned that another site could hijack my user pool, potentially tricking users into signing up to it?
Response:
If I were to take your
UserPoolID
andClientID
- could I "hijack" to your application?
Answer:
Not exactly...maybe kinda sorta but why...
The level of "tenancy" or "permission" you give to a client is entirely up to you and your IAM Roles. Lets say we don't consider my second and more relavant reason, yet - (origin checks).
If I steal your access keys and misuse your app/brand/whatever, I am simply driving clients to your site. I cannot gain access to your client list, data, logs, records, etc. IF you set your authenticated user permissions to not allow that. Locking down your "Admin Level" permissions to client lists, pool info, data, etc.
Example (added to your Statement
section):
{
"Effect": "Deny",
"Action": [
"cognito-identity:CreateIdentityPool",
"cognito-identity:DeleteIdentityPool",
"cognito-identity:DeleteIdentities",
"cognito-identity:DescribeIdentity",
"cognito-identity:DescribeIdentityPool",
"cognito-identity:GetIdentityPoolRoles",
"cognito-identity:ListIdentities",
"cognito-identity:ListIdentityPools",
"cognito-identity:LookupDeveloperIdentity",
"cognito-identity:MergeDeveloperIdentities",
"cognito-identity:SetIdentityPoolRoles",
"cognito-identity:UnlinkDeveloperIdentity",
"cognito-identity:UpdateIdentityPool"
],
"Resource": [
"arn:aws:cognito-identity:us-east-1:ACCOUNT_DIGITS:identitypool/us-east-1:PoolID_NUMBERS"
]
}
Or simply the opposite:
{
"Effect": "Allow",
"Action": [
"cognito-identity:GetOpenIdTokenForDeveloperIdentity"
],
"Resource": "arn:aws:cognito-identity:us-east-1:ACCOUNT_DIGITS:identitypool/us-east-1:NUMBERS-NUMBERS-PoolID"
}
Only need the "cognito-identity:GetOpenIdTokenForDeveloperIdentity"
part.
Locking down your "User Level" permissions to stuff
Example:
{
"Effect": "Allow",
"Action": [ "s3:PutObject", "s3:GetObject" ],
"Resource": [
"arn:aws:s3:::[bucket]/[folder]/${cognito-identity.amazonaws.com:sub}/*"
]
}
As an obvious rule of thumb - only give users permission to what they need. Lock down all the crap you can possibly lock down and use the policy simulator. Conclusion to reason one:
You can lock down all the things that would expose your client base and make it pointless for someone to 'hyjack' your site. Counter argument:
Ya, but what IF
Here is a doc that might help for IAM stuff And some more
Question:
The pre-authentication Lambda payload doesn't seem to include any request origin data, so I guess that isn't the way to do it.
Response:
Hmm.
Answer:
Yes it does include request origin data - IF one sets it up.
Question:
I'm concerned that the AWS Cognito User Pools Javascript API doesn't seem to care which website requests are coming from
Answer:
For this - you're correct. If you are using static served files with user pools triggers - there is little done to check origin.
So - if you really want to - you can set all this up using API Gateway to Lambda. This will remove direct interaction with User Pools from the client side and put it on the back end.
Preface:
Sets to setup:
const
AWS = require( 'aws-sdk' ),
UserPool = new AWS.CognitoIdentityServiceProvider();
exports.handler = ( event, context, callback ) => {
console.log( event );
const params = {
AuthFlow: 'CUSTOM_AUTH',
ClientId: 'numbers',
AuthParameters: {
USERNAME: event.email,
PASSWORD: event.password
}
};
UserPool.initiateAuth( params, ( err, data ) => {
callback( err, data );
} );
};
In the above - yes you can do:
UserPool.initiateAuth( params, callback );
Instead of:
UserPool.initiateAuth( params, ( err, data ) => {
callback( err, data );
} );
But this throws weird errors - there is an issue open on GitHub about it already.
Integration Request
Body Mapping Templates
application/json
This is Apache Template Velocity Language
- different from the JSONScheme
language used by the other mapping template things:
#set($allParams = $input.params())
{
"body-json" : $input.json('$'),
"params" : {
#foreach($type in $allParams.keySet())
#set($params = $allParams.get($type))
"$type" : {
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
},
"stage-variables" : {
#foreach($key in $stageVariables.keySet())
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
#if($foreach.hasNext),#end
#end
},
"context" : {
"account-id" : "$context.identity.accountId",
"api-id" : "$context.apiId",
"api-key" : "$context.identity.apiKey",
"authorizer-principal-id" : "$context.authorizer.principalId",
"caller" : "$context.identity.caller",
"cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
"cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
"cognito-identity-id" : "$context.identity.cognitoIdentityId",
"cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
"http-method" : "$context.httpMethod",
"stage" : "$context.stage",
"source-ip" : "$context.identity.sourceIp",
"user" : "$context.identity.user",
"user-agent" : "$context.identity.userAgent",
"user-arn" : "$context.identity.userArn",
"request-id" : "$context.requestId",
"resource-id" : "$context.resourceId",
"resource-path" : "$context.resourcePath"
}
}
With this, you can get the source-ip
, cognito information, etc.
This method is a secure method for locking down origin. You can either check origin by doing an if
check in Lambda, or a IAM condition - blocking all requests from other origins.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With