Cloud Unfold

unfolding the cloud trivia

API GatewayCognito

API Gateway Cognito Authorizer using Client Credentials – Part I

In this and part II of this article, we will run through the steps for configuring an API Gateway API with Cognito Authorizer with Client Credentials. In Part I, we will focus on creating a Cognito User Pool, setting App Clients, and finally generating an access token, which then can be used to make API requests.

What is Client Credentials?

If you are familiar with Client Credentials, you can skip to this part and continue with the configurations steps below.

Client Credentials is a really straightforward grant type. When you want the applications to talk to each other without you being involved in signing in, generating and sending auth token in the request, Client Credentials can be used. To be more precise, it is used to authorize machine to machine requests. For example, say you have two applications – A and B, and want App A to be accessible by B, only if the requests are authorized. You can configure the User pool in a way that generates a token (Access token), allows B to make requests using this token, and then A allows those requests. We will talk about this a bit more later in this article. For now, let’s get started with User pool configs.

1. Create a User pool 

User Pool creation can be kept pretty basic here, nothing fancy, so we create a User Pool with default settings:

  1. Open Cognito Console > Manage Userpools > Create a user pool
  2. Specify a name, and click on Review Defaults > Create Pool

2. Set up User pool domain

  • Domain Name creation is fairly simple. In User pool, go to App Integration > Domain Name
  • Here you can either use any string to be used as a User pool domain or you can use your custom domain name. For now, I will simply use a string to get a prefixed domain name like below.

  • Note: do not use the word “Cognito”, User pool does not like it. 🙂

3. Client Credentials Grant Type Configurations 

OAuth flow needs a Resource and/or an Authorization server for generating and/or validating token/code, however as Client Credentials grant type does not have an Authorization Server, we can create a Resource Server for our User pool. For more details on this, I would highly recommend watching this amazing talk.

If you already have a Resource server created, you can skip to the next step.

Create a resource server and add scopes

  • In your User pool, under App Integration, click on Resource Servers > Add another Resource Server
  • Give Name, Identifier, scopes, etc. and click Save Changes

4. Create an App Client

If you already have an App Client created with Client Secrets, you can use it, otherwise you can follow the below steps to create one.

  • In your User pool, under General Settings > App Clients > Add another App Client 
  • Specify App Client Name, and specify expiration times as your preference, for now we can leave them as default values
  • Make sure the Generate client secret is checked, this will be required for token generation
  • Leave rest of the things as default for now, you can change them later, and Create app client

5. Configure App Client for Client Credentials

We are almost done with the configs part, the only thing left before we jump onto creating tokens, is configuring our App client for Client Credentials Auth flow. 

  • In the User pool under App Integration > App Client Settings > navigate to an App Client we created above
  • In the configs, ensure that Enabled Identity Providers has Cognito User Pool checked
  • Specify your callback and signout urls, for now, we can set both of them to https://cloudunfold.com
  • Under OAuth 2.0 section, select Client credentials for Allowed OAuth Flows
  • As soon as you select the above option, all the Allowed OAuth Scopes will be disabled, and only Allowed Custom Scopes will be available
  • Select Allowed Custom Scopes and click Save changes

And, that concludes our configurations. Phew!! Let’s wrap the things up by simply creating a token for the above configs.

In client credentials, we only get an Access Token, that is the reason we needed to provide scopes. Similarly, as we noticed OAuth scopes are not available for client credentials, therefore we needed to create custom OAuth scopes which we got from our Resource server.

6. Generating an Access Token

Generating token now is just as simple as making a POST HTTP Request to our User pool domain at token endpoint i.e. /oauth2/token. This request needs an Authorization Header, which is nothing but a baseb4Encode string created with App Client id and Client Secret, custom scopes which we have got from our Resource server.

Create Authorization header value 

You can use any online tool like this one for creating a base64Encode string for a pair of Client Id and Client secret. Simply specify <app_client_id>:<client_secret> and click Encode.

For example, let client_id is 2qcccccccccccccccccccdi, and client secret is l3dfsdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxrs, then in you create base64Encoded string for this pair separated by colon (:) 

2qcccccccccccccccccccdi:l3dfsdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxrs

I prefer to use python as it’s pretty handy. Simply fire up the terminal and do the below:

>>> from base64 import b64encode
>>> b64encode(b'2qcccccccccccccccccccdi:l3dfsdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxrs')
b'MnFjY2NjY2NjY2NjY2NjY2NjY2NjZGk6bDNkZnNkZnh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4cnM='

Request Format

Now that we have everything we need for our request to generate a token, this will be your request format should be:

  • URL: {your domain name}/oauth2/token
  • Method: POST
  • Headers:
    • Authorization: Basic <base64Encoded string>
    • Content-Type: application/x-www-form-urlencoded
  • Body:
    • scope: {your custom scopes}
    • grant_type: client_crendentials

This is how it should look like in Postman:

Or if you prefer CURL then a sample curl request would looks like this:

$ curl --location --request POST 'https://cloudunfold.auth.{region}.amazoncognito.com/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic MnFjY2NjY2NjY2NjY2NjY2NjY2NjZGk6bDNkZnNkZnh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4cnM=' \
--data-urlencode 'scope=any-endpoint/something.read' \
--data-urlencode 'grant_type=client_credentials'

If everything is configured correctly so far, you can expect the response in this format:

{
    "access_token": "eyJraW----6WQWUtfH6js0g",
    "expires_in": 3600,
    "token_type": "Bearer"
}

And, if you parse the token using a tool like https://jwt.io, the payload for the token should look like this:

There you have a fully functional User pool with client credentials grant for your applications to be able to communicate with each other. In the next part, we will take a look at how we can use this setup as an authorizer for API Gateway API. Peace!

Was it helpful?

Just another lazy guy

LEAVE A RESPONSE

Your email address will not be published. Required fields are marked *

Related Posts