Is it safe to use ID tokens with Cognito authorizers?

Yan Cui

I help clients go faster for less using serverless technologies.

This article is brought to you by

I never fully recovered my workspace setup when I upgraded my laptop two years ago, and I still miss things today. If only I had known about Gitpod back then…

Learn more

A common narrative is that one should always use access tokens to call your APIs, while ID tokens are strictly for identifying users.

Some of it has come from this article by Auth0 [1], which makes a strong statement about using ID tokens:

However, things are usually more nuanced. In some cases, using ID tokens instead of access tokens is both acceptable and pragmatic. Cognito User Pools might be one of these cases.

Cost of using access tokens in Cognito

The common practice amongst Cognito users is to use ID tokens.

Before January 2024, you couldn’t customize access tokens to include the OAuth scopes. So, using access tokens for authorization just wasn’t an option.

But now, Cognito lets you customize access tokens through the Pre-Token Generation trigger, like this [2]. With this, you can implement authorization in API Gateway using access tokens and OAuth scopes.

However, this requires Cognito’s advanced security features [3], which are charged much higher – starting at $0.050 per MAU and do not have a free tier. You must also pay the standard MAU cost for Cognito User Pools, which starts at $0.0055 per MAU and has a generous free tier of 50,000 MAU.

This significantly raises the cost of using Cognito User Pools. Here is how much it’d cost you per month with Advanced Security Features (using access tokens) vs. without (using ID tokens).

This might be fine for B2B use cases where you tend to have few high-value users. But it’s practically a death penalty for many B2C businesses, many of whom have thousands of free users.

“Why not use something else instead?”

For this many MAUs, you’d pay even more with vendors such as Auth0 and Okta. Most of whom require you to sign an enterprise contract before you can reach this scale.

Cognito’s greatest strengths are cost efficiency and its integration with other AWS services, such as API Gateway and AppSync. If access tokens are significantly more costly, one must ask,

“Is it worth it?”

Are access tokens more secure? If so, are they THAT much more secure and worth the extra cost?

ID tokens vs. Access tokens

Whenever I show an example of using Cognito with ID tokens, someone would tell me, “You should use access tokens instead!”. But, I have yet to hear a compelling argument for why ID tokens are less secure.

Let’s quickly debunk the common arguments.

“ID tokens are not designed for authorization”

Yes, access tokens were intended for APIs and ID tokens for authentication purposes. However, this division is not always necessary or practical.

After all, there is more than one way to implement authorization.

You can implement the authorization logic in the identity provider and embed the authorization decision in access tokens (in the form of OAuth scopes).

However, you can also implement the authorization logic directly in the API. In my last post [4], I demonstrated how you can do this with a Lambda authorizer and Cognito groups. We will also explore other ways to implement authorization with API Gateway in the coming weeks.

It’s two routes to the same result – being able to control who can do what in your system.

“ID tokens have more information”

This is true. ID tokens contain information about the user, such as their name and email.

But what can attackers do with this information if they managed to steal your ID tokens? Nothing. Most likely.

As an attacker, I have easier ways to acquire names and emails than to steal ID tokens from a system.

“ID tokens give you access to the API”

So does access tokens.

“Access token can only be created by a trusted source”

So are ID tokens.

“Access tokens have limited lifetime”

So can ID tokens. You can configure the validity period for both access and ID tokens in Cognito (and with other vendors). It’s a matter of making sensible architectural decisions.

“You can bind access tokens to specific senders to avoid abuse”

Yes, the Auth0 article mentioned this.

The linked article [5] (which is a good read, btw!) discusses two techniques:

  • Mutual TLS authentication (MTLS)
  • Demonstrating Proof-of-Possession (DPoP)

for binding a token to a specific sender.

However, nothing about these techniques is specific to access tokens. They will work equally well for ID tokens.

Summary

Until someone can prove otherwise, I believe it’s perfectly safe to use ID tokens with Cognito authorizers.

ID tokens are not inherently less secure than access tokens. Furthermore, all the techniques that make access tokens more secure also apply to ID tokens.

So, there are no security downsides to using ID tokens with Cognito.

On the other hand, there are significant costs to using access tokens.

I’m not saying that you shouldn’t use access tokens! In fact, I will show you how to use access tokens to implement authorization in API Gateway in the next post.

But you should know the trade-offs and not blindly pick a more costly approach based on hearsay.

Links

[1] “ID Token and Access Token: What’s the Difference?” by Auth0

[2] How to customize access tokens in Amazon Cognito user pools

[3] Cognito User Pool advanced security features

[4] Fine-grained access control in API Gateway with Cognito groups & Lambda authorizer

[5] Identity, Unlocked… Explained | Episode 1

Related posts

Whenever you’re ready, here are 3 ways I can help you:

  1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
  2. I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
  3. Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.