Implementing OAuth 2.0 with AWS API Gateway, Lambda, DynamoDB, and KMS — Part 1

Bilal Ashfaq
8 min readAug 5, 2023

--

In this series, we will see how we can secure our API Gateway endpoints by implementing OAuth 2.0 client credentials flow using various AWS services such as API Gateway, Lambda, DynamoDB, and Key Management Service (KMS). In this part of the series, we will first understand the concepts of OAuth 2.0, client credentials, and JWT, and then finally, we will have a look at the AWS architecture to understand how we will be implementing OAuth 2.0 client credentials flow. So let’s get started!

OAuth 2.0 (Client Credentials Flow):

OAuth 2.0 is an authorization protocol that allows a third-party website or application (referred to as a client) to access a user’s protected resources without providing the user’s credentials. The client will just provide something called an “Access Token” and would be able to access the protected resources.

Following are the different roles involved in OAuth 2.0:

Client: the system or application that wants access to a user’s protected resources

Resource Owner: the user or application that owns the resources

Authorization Server: the server that authenticates the client and provides an Access Token to access the protected resources

Resource Server: the server where the protected resources are located

OAuth 2.0 has different grant types which are steps that the client has to perform to get the access token. Each grant type has its own specific use cases. Client Credentials is one of the grant types which is designed for machine-to-machine communication and in this grant type, the client authenticates itself without any user involvement. In this flow, either the client itself is the resource owner or it has been authorized by the authorization server to access the protected resources. An example use case of Client Credentials flow is when a backend service wants to periodically access an API to get certain data or perform an operation using a scheduled task.

To understand this flow better let’s take an analogy:

Let’s assume that a guy named Jon is going out of town for some time and his friend Alex wants to stay at his home for a couple of days. So, Jon hands over his home keys to his neighbor and tells him “If a person with the name “Alex” comes and proves that he is Alex, give him the key to only my room, for a couple of days”. And the neighbor agrees!

Now, Alex comes and says to the neighbor, “Hey I am Alex, and here is my ID, can you please give me the key to Jon’s room?” Since Jon had already informed the neighbor, he gives the key (to Jon’s room) to Alex for a couple of days.

In this analogy, Jon is the resource owner, Alex is the client, neighbor is the authorization server, Jon’s room is the protected resource, and the house (we can say) is the resource server. Note that, the neighbor didn’t need to call Jon to ask his permission before handing over the key to Alex. There was just an initial arrangement between Jon and the neighbor and that’s it!

Now, we will map this analogy to the Client Credentials flow but first, let’s answer a few questions:

The first question is, what details does the client has to provide to get the Access Token? In the Analogy, the name of Alex and his ID card were used to get the token (key). In OAuth 2.0 terminology, they are called Client Id and Client Secret, and they are just like usernames and passwords but for applications. Also, note that they are not the Resource Owner’s credentials, they are the client’s own credentials. These credentials are acquired by the client from the Authorization server.

So, in order to access the protected resource, the client would provide the client id and client secret to the authorization server, the authorization server would authenticate the client and return an access token, then the client would provide the access token to the resource server to get the protected resource.

Now the next question is, what actions can the client take on the protected resource given that it has the access token? Can it only view the resource or also change it? For how long would the token be valid?

In the Analogy, the token or the key could only be used to access Jon’s room and not the other rooms, and that too for a couple of days only. This means while generating the access token, the authorization server also needs the information on what sort of access the client needs. For this, the client will provide something called “Scope” to inform the authorization server that it needs these permissions as part of the access token. Also, the authorization server will add an expiry to the token so that it cannot be used forever. Let’s also define the term Scope.

Scope: is a list of permissions that are required by the client e.g. read, update, etc. These permissions determine what actions the client can perform or what resources it can access.

Now our final flow looks something like this:

  1. The client provides the client id, client secret, and scope to the authorization server
  2. The authorization server authenticates the client and also verifies that the requested scopes can be granted to the client
  3. The authorization server returns the Access Token to the client
  4. The client requests access to the protected resource from the Resource Server providing the Access Token
  5. Resource Server validates the Access Token and grants access

The following image depicts this flow:

OAuth 2.0 Client Credentials Flow

Now that we know what OAuth 2.0 is and what client credentials flow means, let’s also discuss JWT.

JSON Web Token (JWT):

JWT is a way of securely transmitting data between two parties as JSON objects. Since OAuth 2.0 does not specify a format for Access Token, JWT is mostly used because it is very compact. JWTs are trusted between the sharing parties because they are digitally signed using a secret (e.g. HMAC algorithm) or public/private key pair (e.g. RSA algorithm).

JWTs consist of the following three parts:

Header: that typically contains attributes typ (type of the token i.e. JWT) and alg (which is the algorithm used for signing)

Payload: that consists of claims or pieces of information that you want to send. Claims can be any information like email, userId, etc. and there is a set of recommended claims such as iss (issuer of the token), exp (expiration time of the token), and iat (the time when the token was issued), etc.

Signature: that ensures that the token was not changed along the way. It is created using the header and the payload. Both these parts are base64URL encoded and combined with a dot ‘.’. Then, the resulting string is given to signing algorithms (like RSA) to create the signature.

Finally, all these three base64URL encoded parts are combined with dots to create the token. Have a look at the image below to understand it better:

JSON Web Token

Now, at this point, two things should be clear:

  1. As JWTs are signed, the receiver knows that the message was not tampered with, because it can check the signature and verify that it matches the header and payload part of the token
  2. If a private/public key pair is used to sign the token, the receiver knows that the sender is who he says he is, because only he can have the private key

Now that we are clear on all the concepts, let’s discuss the architecture i.e. how we will be implementing this,

Architecture:

During the implementation, we would assume that the clients have already acquired their credentials (client id and client secret) from the authorization server, and in order for the authorization server to authenticate the clients, we would have the credentials and allowed scopes saved in a DynamoDB table.

Also, we will have two API Gateways working as the Authorization and Resource servers. Our Authorization server API Gateway will invoke a Lambda that would authenticate the client and would validate that the requested scopes are permitted. Finally, if everything checks, it will create an Access Token signed using AWS KMS. Then, the access token will be returned to the client.

The following image shows the working of our authorization server:

Authorization Server — Architecture

Now, after getting the access token, the client will request the resource from our resource server API Gateway providing the access token. There would be a Lambda Authorizer attached to our API Gateway endpoint that will validate the token (it is not expired, the signature is valid, etc). Then, Lambda Authorizer will return a policy to API Gateway, which either allows or denies access to the resource. Finally, based on the policy, the client would get access to the resource or would be denied access.

The flowing image depicts the working of our resource server:

Resource Server — Architecture

Conclusion:

In this article, we discussed OAuth 2.0 and we specifically focused on Client Credentials flow. We discussed the different roles involved in OAuth 2.0 and terminologies. We also discussed JWT and the AWS architecture we will create in this series and how it would work. To Summarize it all:

  • OAuth 2.0 is an authorization protocol that allows applications or websites to access a user’s protected resources without needing the user’s credentials
  • Client Credentials is one of the grant types of OAuth 2.0 which is used in machine-to-machine communications, and in this grant type, the client authenticates itself with the authorization server by providing the client id and client secret
  • JWT is a way of securely transmitting data between two parties as JSON objects
  • In our implementation, we will use API Gateways to act as Authorization and Resource Servers
  • Client information including the permitted scopes will be stored in a DynamoDB table
  • AWS KMS will be used to sign the tokens
  • The resource server will use a Lambda Authorizer to validate the tokens

In the next part, we will implement our authorization server, so please keep reading!

References:

  1. What is OAuth 2.0?
  2. OAuth 2.0 Authorization Framework
  3. Client Credentials Flow
  4. Introduction to JSON Web Tokens
  5. Explaining JSON Web Token (JWT) To a 10 Year Old Kid

--

--

Bilal Ashfaq

Software Engineer . Cloud Enthusiast . Passionate about building scalable software solutions and enhancing user experiences.