We are planning to use AWS WebIdentityFederation for a single page application.
I have created OIDC provider, which is an external ADFS and created a WebIdentityFederation assumed role. I am able to generate id_token through ADFS. In this id_token, I have added Role claim, which is AD Groups (I can change to AWS Role ARNs if needed) and then generate temporary STS tokens from AWS STS API.
However, it looks like, AWS WebIdentityFederation role doesn't validate any role claim inside id_token, like AWS does for SAML federation. This creates a authorization question, if an user have valid id_token, they can assume any WebIdentityFederation role.
For example: If I have two WebIdentityFederation roles READONLY and ADMIN, then an user with a valid id_token can assume READONLY and ADMIN both, even if in id_token user has READONLY role.
Is there any way to validate role or any other custom claims present in id_token? Can it be done through Trust Policy conditions?
Related
Executing import amplify auth for Cognito User Pool and Identity Pool and passing on the Web Client as well as the Native client fails with the below Error. Is there something that is missing please let me know. TIA
Cannot import Identity Pool without roles.
Error: Cannot import Identity Pool without roles.
at IdentityPoolService.getIdentityPoolRoles (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/amplify-provider-awscloudformation/src/aws-utils/IdentityPoolService.ts:88:13)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at importServiceWalkthrough (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/#aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/import/index.ts:322:74)
at Object.importResource (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/#aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/import/index.ts:45:42)
at Object.executeAmplifyCommand (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/#aws-amplify/amplify-category-auth/src/index.js:421:3)
at executePluginModuleCommand (/usr/local/lib/node_modules/#aws-amplify/cli/src/execution-manager.ts:178:3)
at executeCommand (/usr/local/lib/node_modules/#aws-amplify/cli/src/execution-manager.ts:30:5)
at Object.run (/usr/local/lib/node_modules/#aws-amplify/cli/src/index.ts:205:5)
Ran into this issue as well.
The Amplify Auth import docs mention the following:
Your Identity Pool needs:
an Authenticated Role with a trust relationship to your Identity Pool
an optional Unauthenticated Role if you want to use any guest user access for your Amplify categories. (Example: Guest access for your S3 buckets or REST API endpoints)
However, I:
Using an identity pool with an "authenticated" role with proper trust relationship intact (role, policy, identity pool role attachment).
Made sure the IAM role I was using to deploy this change had proper permissions to list and read identity pools & roles.
Still no help.
I then enabled "Allow unauthenticated identities" (although I did not want this) and things worked smoothly. This is because this setting will automatically generate two authenticated and unauthenticated roles and attach them for you.
However, as I did not want unauthenticated identity access, I disabled that again. Based off that setting working, I wondered if that Unauthenticated Role was truly optional, well it turns out it's not. At least not in the latest Amplify system. Someone must have changed this behaviour without updating the docs.
Solution:
Your Identity Pool needs:
an Authenticated Role with a trust relationship to your Identity Pool
an Unauthenticated Role with a trust relationship to your Identity Pool
To check if your identity pool is set up properly run this function in the AWS CLI:
aws cognito-identity get-identity-pool-roles --identity-pool-id "your identity pool id here"
You should get something like this:
{
"IdentityPoolId": "your identity pool id here",
"Roles": {
"authenticated": "your authenticated role ARN here"
"unauthenticated": "your authenticated role ARN here"
}
}
I have set up aws cognito and would like to use their federated identities to authenticate users against my own database but on getting a token after calling the get_open_id_token_for_developer_identity() and then calling the get_credentials_for_identity() the response is identityID , AccessKey , clientSecret and session token but this accesskey and client secret do not match the security credentials for my root user or even the IAM users and when used in postman with the AWS SIGNATURE authorization it throws an unauthorized error . I am getting the credentials after calling the get_credentials_for_identity() using identity id and in login{"cognito-identity.amazonaws.com":<token_from_get_open_id>} but the response which includes accesskey and client secret does not let me hit the api now secured using cognito
this accesskey and client secret do not match the security credentials for my root user or even the IAM users
These are new and temporary credentials not linked to your root or other IAM users in your account. From docs:
You can use Amazon Cognito to deliver temporary, limited-privilege credentials to your application, so that your users can access AWS resources.
This is explained more here:
When a user logs in to your app, Amazon Cognito generates temporary AWS credentials for the user. These temporary credentials are associated with a specific IAM role. The IAM role lets you define a set of permissions to access your AWS resources.
According to the offical AWS documentation, IAM Roles can also be attached to IAM Users, and not only services.
What would be a valid use case to assign an IAM Role to an IAM User?
Aren't all the cases covered by directly granting (allow/deny) IAM Policies to the users?
TBH my initial impression was thar IAM Roles served the purpose of authorization for the AWS services (so that they can interact with other services), since the latter cannot be addressed in the User context
As you clearly understood, AWS Roles serves the purpose of authentication (with IAM policies for authorization) for AWS services. In contrast, AWS IAM users directly maps towards human user who obtains credentials to login to the AWS Management Console.
However, when granting access to an User outside the AWS Account (e.g; Cross Account Access, AD Authentication Federation) it will require an IAM Role to Assume the permission.
Referring to the documentation you shared, its not a direct IAM User who is getting permission, rather an Active Directory user (External) assuming an IAM Role (Not direct IAM User) to get access to the AWS Resources.
It is an IAM best practice is to assign Roles to AWS users from other AWS accounts in order to delegate permissions. This is to avoid sharing credentials between AWS accounts.
I also wanted to point out, your initial impression about Roles as authorization is not correct. The only IAM resource that is considered authorization are IAM Policies.
This can be seen in the AWS documentation on Understanding IAM and in the following AWS training video: Authentication and Authorization with AWS Identity and Access Management (login required)
The other three basic IAM resources: Users, Groups and Roles are considered part of Authentication.
Im building a serverless application using the following AWS technologies:
AWS Cognito
AWS Lambda
AWS API gateway
AWS IAM
All requests from the client (programmed in Angular2) go through API gateway.
I have created a IAM role for signed in users: Cognito_MyApp_Auth.
I use a Cognito User Pool Authorizer to make sure all calls to my API are from valid signed-in users.
Question: How can I grant the Lambda function the same permission as the signed in user?
Use case: A signed in user may only create, edit or delete in his own S3 bucket, so granting Lambda full permission to S3 is not an option.
Cognito_MyApp_Auth does not set different permissions from user to user. It only defines the permissions for any signed user. So you should allow access to all buckets in this role's policy. (However, I'd limit this access to buckets starting with a specific prefix.)
Fortunately, when Lambda is invoked via Cognito SDK, using Cognito provided credentials, context object passed to handler carries Cognito identity used to invoke the Lambda.
For Node.js you can see how to get this information:
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html#nodejs-prog-model-context-example
if (typeof context.identity !== 'undefined') {
console.log('Cognito
identity ID =', context.identity.cognitoIdentityId);
}
Once you have the identity id, you can set up your own logic to limit the user's access to her own bucket.
This was the case when you call the Lambda directly from the application using Cognito SDK. If you use API Gateway, there is a good post from an AWS employee: https://forums.aws.amazon.com/thread.jspa?messageID=717379
There is no direct way to grant the Lambda function the same permissions as the signed in user; however, you should be able to implement your use case using Cognito identity pools and policy using the cognito-identity context variable.
For this approach, you won't use Cognito user pools nor the Cognito user pool authorizer. Instead, you use a Cognito identity pool for federated identity. Set the authorization on you API methods as AWS_IAM. Don't use Lambda as the integration, but instead use the AWS proxy to integrate directly to S3. Set the integration request to use the caller's identity.
To cal the API you'll need to use Cognito to get temporary credentials and then sign your API request with them.
With this approach, the S3 call is made with Cognito identity context, so you can attach policy which uses cognito-identity variables to the IAM role associated with authenticated users in your Cognito identity pool.
For example:
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
]
"Resource": [
"arn:aws:s3:::BUCKET_FOR_USER_${cognito-identity.amazonaws.com:sub}/*"
]
}
See this post for a similar use case.
Documentation for IAM state that the Resource-property for AttachUserPolicy and DetacherUserPolicy should be set to the user principal the managed policy will be attached to. While the documentation for iot:AttachPrincipalPolicy and iot:DetachPrincipalPolicy are not as detailed, the error message
AccessDeniedException: User: arn:aws:sts::ACCOUNT_ID:assumed-role/ROLE/CognitoIdentityCredentials is not authorized to perform: iot:AttachPrincipalPolicy on resource: COGNITO_ID
leads me to believe it expects an ARN for Cognito identity or identity pool. However, specifying ARNs shown in Cognito documentation result in the same error. Cognito identity ARNs also fail validation in the policy generator.
What resource should I specify so that iot:AttachPrincipalPolicy and iot:DetachPrincipalPolicy are permitted to attach/detach IoT policies on a Cognito identity?
Using Cognito identities with AWS IoT has two slightly different paths. Cognito identity pools support identities which are either unauthenticated (any agent can get credentials) or authenticated (users tied to a provider like Cognito User Pools, Facebook, OpenID, etc). AWS IoT supports both cases when using Cognito to get credentials.
When using the unauthenticated case, you must attach a policy to the cognito_unauth_role that gets created with your Cognito identity pool. The Identity Access & Management (IAM) console is where you attach a policy to this role. To get started, try attaching the managed policy "AWSIoTDataAccess". Then, your unauthenticated Cognito IDs can get credentials (access key, secret key, session token) which are passed to AWS IoT to establish a connection.
When using the authenticated case, you must attach a policy to the cognito_auth_role that gets created with your Cognito identity pool AND the Cognito ID which is created for each authenticated entity. The AWS IoT API AttachPrincipalPolicy is what you use to attach an AWS IoT policy to the Cognito ID. The format of that API call in the CLI would be like: aws iot attach-principal-policy --policy-name myPolicy --principal us-east-1:abcd1234-5678-1234-abcd1234efgh. The principal in this case is the Cognito ID of the authenticated entity. Only with both policies in place will the credentials returned by Cognito work to make connections to AWS IoT.