Open ID Connect and using Cognito to assume a role

Viewed 224

I want to create an API that requires an IAM role to access the data in the end-user's S3 buckets. I currently use the following flow:

  1. User logs on to the website and gets an ID token and access token (via OIDC).
  2. User invokes a call to my API and presents its ID token.
  3. My API fetches temporary credentials from Cognito Identity Pool using the presented ID token.
  4. Calls to S3 can be made using the temporary credentials.

Although this works, there is a flaw in this flow. The website got an ID token during the Open ID Connect login, but ID tokens shouldn't be used to pass to an API (that's what access tokens are for). I would rather pass an access token instead, but I can't get the AWS credentials using an access token.

What is the appropriate solution here? I checked if I could get an ID token from an access token. I have several options:

  1. Just pass the ID-token to the API, because we want to pass our identity (IAM role) so the API can impersonate. This makes it reasonable to pass an ID token instead of an access token.
  2. The API should obtain an ID-token based on the access-token. Although I can fetch all identity claims from the OIDC userinfo endpoint, this isn't an ID token, so I can't use it to fetch the AWS credentials using Cognito's identity pool.
  3. Completely ditch Cognito Identity Pool and grant the API role STS policies, so it can assume the role that is linked to the user. I rather not have high-privilege roles in my services.

All three solutions are not ideal. But what's the best scenario? Or did I forget something?

1 Answers

There are actually 2 types of resource being used here:

GENERAL v PROVIDER RESOURCES

  • Cognito acts as a general Authorization Server to get tokens for use in your apps and to access data in your APIs

  • Cognito can also act as as an Idemtity Provider with which the user authenticates, but this is not the only option

The second point is clearer if you imagine the Cognito flow being updated to sign the user in via Google, after which there are two types of token and the user's Google documents can be accessed with the Google token.

EMBEDDED TOKEN PATTERN

See this Curity article for techniques on separating this type of concern. Although you are not using embedded tokens, it is worth understanding that apps sometimes need to think in terms of accessing different resources with different tokens.

YOUR SCENARIO

The important consideration is to base general API authorization to your own resources on the access token - as you suggest. This will keep your main API logic standards based and portable. Aim to keep this separate from vendor specific behaviour.

For API operations that need to access S3 or other AWS resources, you may have to do things according to the provider. ID tokens provide proof of the authentication event to UI clients, yet AWS sometimes use them like access tokens. Personally I would not follow this approach for my own resources. Instead I would send the ID token to specific API operations in an additional header such as x-idp-token, in addition to the access token.

Related