I am using the AWS Javascript API and trying to get the assigned cognito id:
AWS.config.credentials.get(function(err) {
if (!err) {
console.log("Cognito Identity Id: " + AWS.config.credentials.identityId);
}
});
Why does this result in a 400 error with the message below?
{"__type":"InvalidIdentityPoolConfigurationException","message":"Invalid identity pool configuration. Check assigned IAM roles for this pool."}
I have IAM roles configured for authenticated and non-authenticated users.
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"mobileanalytics:PutEvents",
"cognito-sync:*"
],
"Effect": "Allow",
"Resource": [
"*"
]
}]
}
The most common reason for this error is your roles aren't set up to trust your identity pool. You should confirm that the identity pool id listed in your trust relationships matches the identity pool you are using.
More info on trust relationships in Amazon Cognito can be found in our developer guide.
After some digging I realized that you must add the RoleArn and AccountId to your credentials.
Even though most of the documentation out there mention this as being enough:
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:xxxxx-a87e-46ed-9519-xxxxxxx',
});
This was not enough.
I had to do this:
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:xxxxx-a87e-46ed-9519-xxxxx',
RoleArn: 'arn:aws:iam::xxxxx:role/Cognito_xxxxUsersUnauth_Role',
AccountId: 'xxxxxxxxx', // your AWS account ID
});
You must mention the ARN of your Role for your identity pool.
The only doc that mention it right is this one.
The wrong ones:
http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-configuring.html
https://mobile.awsblog.com/post/TxBVEDL5Z8JKAC/Use-Amazon-Cognito-in-your-website-for-simple-AWS-authentication
https://blogs.aws.amazon.com/javascript/post/TxTUNTVES4AL15/Authentication-in-the-Browser-with-Amazon-Cognito-and-Public-Identity-Providers
Maybe I'm missing something but this is certainly confusing.
Check the "Trust Relationship" section of the role that is assigned to your Identity Pool, authentication users.
Make sure you have policies defining access to your Cognito pool.
The easiest way to get the requirement policy statements is,
Edit the pool
Create new role for identity pool
In IAM edit this role to copy the policy statements
Add these Trust Relationships to your required existing role
Another - probably less common - reason: Make sure that you are actually using an identity pool and if not, remove the identity pool id from your aws-exports.js.
I was getting this error after adding federated sign ins to my user pool (not identity pool). For reasons unknown my config included an aws_cognito_identity_pool_id. Removing this id solved the error for me.
I checked the Trust Relationship of my roles configured for "Authenticated role" and "Unauthenticated role" for my identity pool more than once, but still the error occured.
After reviewing my whole identity pool configuration I recognized that in
Authentication providers
Cognito
Authenticated role selection
I have chosen "Choose role from token" and my wrong configured role was the one I attached to the cognito group for my users.
So updating the Trust Relationship for this role fixed the problem.
Hope this helps someone :)
In my case, I am using SAML identity provider. The action in the IAM role policy should be: "Action": "sts:AssumeRoleWithSAML". But this is the root cause of the exception. I have to manually change it to "Action": "sts:AssumeRoleWithWebIdentity". It turns out any role created by the Cognito identity pool will use "Action": "sts:AssumeRoleWithWebIdentity". It won't check your identity provider type. I believe this is a bug.
I encountered this error and my problem turned out to be that my user was assuming an unauthenticated role because I was returning AWSTask(result:nil) from the logins() function in my custom CognitoDeveloperIdentityProvider.
I had the same error when trying to retrieve files from S3 through my Identity pool users.
Solution: You can create a role in IAM for "Web Identity". Then provide your identity pool ID and add the permissions that you want the role to have, e.g. S3FullAccess. Then navigate back to Amazon Cognito Identity pools and assign the role you just created to the unauthrole or authrole. The users in the Identity pool should now be able to access the S3 resources
Another -way less probably scenario- is that either the provider or identityPoolId you are using is invalid. I spent hours debugging a missing ENV in my code.
Had this issue, after several hours of checking our what the problem could be, found out that the Trust Policy is actually missing this line sts:TagSession in the Action List so eventually the Authenticated Trust Policy is as defined below:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": [
"sts:AssumeRoleWithWebIdentity",
**"sts:TagSession"** //this does the trick for me
],
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "{IDENTITY_POOL_ID}"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
Related
I have users in a Cognito user pool, some of whom are in an Administrators group. These administrators need to be allowed to read/write to a specific S3 bucket, and other users must not.
To achieve this, I assigned a role to the Administrators group which looked like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bucket-name/*"
]
}
]
}
Then in my Angular app, I sign in and use Amplify's Storage class to do the following:
Storage.put("test.txt", "hello")
.then(result => ...)
.catch(err => ...);
The Amplify.configure in this case is:
const amplifyConfig = {
Auth: {
region: "eu-west-2",
userPoolId: xxx,
userPoolWebClientId: yyy,
mandatorySignIn: false,
},
Storage: {
AWSS3: {
bucket: 'my-bucket-name',
region: "eu-west-2"
}
}
};
Amplify.configure(amplifyConfig);
The problem here was that, internally, no credentials were provided to the Storage.put call, and the task fails as follows:
[DEBUG] 31:08.487 Credentials - Failed to load credentials
ZoneAwarePromise {__zone_symbol__state: false, __zone_symbol__value: NotAuthorizedException:
Unauthenticated access is not supported for this identity pool.
Reading around, this seemed to be because you don't get credentials at all unless you have a federated identity pool. So I created an identity pool attached to my user pool + app client, with all the defaults, and added its ID to my Amplify.configure config.
This still doesn't work, but this time I do get credentials - and they are for the IAM role specified in the identity pool's Authenticated Role.
So now if I add the above S3 permissions to that role, all my code works, but there's a massive security hole in that now all users (not just admins) can read/write the admin's bucket. Ah.
So, how can I get credentials for the role specified in the admin user group's settings if and only if I'm an admin?
Or alternatively, can this be solved by some clever setting in the federated identity whereby it assigns the correct roles there based on the user's group?
The solution lies in the federated identity pool's settings.
By default the identity pool will provide the IAM role that it's configured with. In other words, one of either the "unauthenticated role" or the "authenticated role" that it's set up with.
But it can be told instead to provide a role specified by the authentication provider. That's what will solve the problem here.
In the AWS console, in Cognito, open the relevant identity pool.
Click "Edit identity pool" (top right)
Expand "Authentication Providers"
Under Authenticated Role Selection, choose "Choose role from token".
That will allow Cognito to specify its own roles, and you will find that the users get the privileges of their group.
We have configured Cognito and Kibana to use the Cognito pools for authentication, but when I open Kibana endpoint - it just let me in, without asking for login / password. We used this doc, but IAM part isn't quite clear.
In ES cluster I see:
Amazon Cognito for authentication: Enabled
Cognito User Pool: my-user-pool
Cognito Identity Pool: my-id-pool
IAM Role Name: the_role_name
the_role_name has standard AWS-managed AmazonESCognitoAccess attached.
I'm a bit confused that at VPC we have
IAM Role: AWSServiceRoleForAmazonElasticsearchService
The identity pool has Enable access to unauthenticated identities disabled.
So, how to enable the authentication properly?
There were missing permissinos in elasticsearch "access policy", was needed like that:
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::1111111111:role/acl-Cognito-Auth-Role-my"
},
"Action": "es:ESHttp*",
"Resource": "arn:aws:es:eu-west-1:1111111111:domain/es-name/*"
}
My setup:
- Mobile Hub
- Cognito User Pool
- Api Gateway
- DynamoDB
What I got working so far:
The User can sign up/in with the Cognito User Pool and get an Id and AccessToken.
The IdToken is used with the Api Gateway Cognito Authorizer to access the Api Gateway.
The Mapping of the user sub into the integration message to DynamoDb works.
"userId": {
"S": "$context.authorizer.claims.sub"
}
Restricting the access to non user rows in a DynamoDb Table does not work.
The DynamoDb tables were created using Mobile Hubs Protected Table feature, which creates the following policy:
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"${cognito-identity.amazonaws.com:sub}"
]
}
}
But thats not working, because this expression returns the Identity User Id and NOT the User Pool Sub. At first I'm not using Identity Pools and second I want to use the User Sub here.
I found out
${cognito-idp.<REGION>.amazonaws.com/<POOL-ID>:sub} should do the trick, but thats not working too.
If I hardcode the Condition to use the Sub of my test user, everything works as expected, so the Policy itself is okay, it's only the expression to get the sub of the current user is not working correctly.
Is it possible to debug the IAM Policys to see what the values of the expressions are at runtime?
Any Ideas, hints, suggestions?
Thanks in advance.
I got the answer now from an AWS Dev. You are only able to use the
${cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXX:sub}
variable if you configure the Cognito User Pool as an open ID Connect provider directly against IAM.
But there is a big problem, because you need to update the SSL Thumbprint of the service endpoint if the certificate changes in the Open ID Connector configuration. But you are not able to tell when the aws certificate has changed.
I finally figured this out by using aws:PrincipalTags
Pre-req is making sure that the IAM role that the Cognito User assumes has sts:TagSession assume role policy permission. This allows principal tags to be passed after successful login to Cognito.
On the Cognito Identity Pool, open Authentication Providers and find the Cognito provider. Make sure that Attributes for access control uses the default mappings which maps username to sub, or you have a custom rule set that passes the sub property to a PrincipalTag.
Finally you can use the tag passed in the filter of the role to only allow access to resources by that sub.
{
"Action": [
"dynamodb:UpdateItem",
"dynamodb:Query",
"dynamodb:PutItem",
"dynamodb:GetItem"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${aws:PrincipalTag/username}"
}
},
"Effect": "Allow",
"Resource": "arn:aws:dynamodb:*:*:table/MyTableName",
"Sid": ""
}
With the recent release of API Gateway Cognito Custom Authorizers, I'm attempting to use Cognito, API Gateway and S3 together for authenticated access control without Lambdas.
Authorizing with API Gateway works as it should (with Trust Relationships for the API Gateway execution role set correctly) but I can't seem to get the resource policy to capture the Cognito User ID Sub variable for fine grain access control to S3 resources based on User ID.
Here's the current flow I'm trying to accomplish:
Authenticate with Cognito and get valid token
Send token to API Gateway to gain access to S3 bucket (through AWS Service integration type)
Fine grain access to only User ID's directory
Return S3 object (based on API endpoint)
Here's my current resource policy for the API Gateway execution role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cognito-idp:*",
"cognito-sync:*",
"cognito-identity:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:Get*",
],
"Resource": [
"arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
Everything works as it should but this IAM variable (in the policy attached to the API Gateway execution role) doesn't seem to be right.
I came across this StackOverflow article and tried using both formats us-east-1:xxxx-xxxx-xxxx-xxxx and xxxx-xxxx-xxxx-xxxx but both didn't seem to work. I'm using the sub attribute found in the Cognito User Pool User info. If I hard code the folder in S3 to the Cognito User ID Sub it works just fine.
How do I get the Cognito variable to work in the API Gateway's execution role policy?
Here are a couple other articles I found related to the question on the AWS forums:
Cognito IAM variables not working for assumed-role policies
What cognito information can we use as IAM Variables?
That's not the sub that the variable expects. There is no way to use cognito user pool attributes in policy. The sub that you want is the cognito identity id which is the id of the user in the cognito Identity (federated identity pool). You can get this ID by using the get id method. I would suggest you store this ID as a custom attribute variable in your cognito user pool so you don't have to keep making the call.
You can read more about this identity id here.
We're currently using G Suite as an IDP for our AWS SAML access that assumes a role within a handful account to give our G Suite users access to certain AWS resources. Each account has a similarly named role that the G Suite user can assume to give them access to certain resources in that account which is all working as expected.
I'm looking into whether I can configure that assumed role to give more fine-grained access to certain users for certain resources, without having to assign completely different roles to different users within G Suite itself.
For example, if the role assumed within the account is called "assumed_gsuite_ro" and doesn't give access to IAM, you get errors in the IAM console as such:
User: arn:aws:sts::0012345678900:assumed-role/assumed_gsuite_ro/matt#domain.com is not authorized to perform: iam:GetAccountSummary on resource: *
So I'd like to add something as such to the assumed_gsuite_ro role policy to give just my federated user access to that in IAM:
...
{
"Sid": "IAMTest",
"Effect": "Allow",
"Action": [
"iam:GetAccountSummary",
"iam:ListAccountAliases"
],
"Resource": "*",
"Condition": {
"ArnEquals": {
"aws:SourceArn": "arn:aws:sts::0012345678900:assumed-role/assumed_gsuite_ro/matt#domain.com"
}
}
}
...
However, this doesn't work as apparently the SourceArn doesn't match. Is there a value of the condition I can use that will allow me to target the specific federated user that AWS seems to know about? I was thinking something like aws:userid or aws:username might work, but I'm not sure what the values of those would be in this case.
Having delved a bit deeper and found this page in the AWS documentation which describes how the values of aws:userid is made up in a SAML/federated context, I've determined the following works:
"Condition": {
"StringLike": {
"aws:userid": "AROAROLEID:matt#domain.com"
}
}
Where AROAROLEID is the value of the "role ID" for the name of the role you're assuming (assumed_gsuite_ro in my example) which according to this page you can only get from a get-role call to the AWS CLI (it's the value of RoleId).