Lesson 1: The Authorization Code Flow (theory)

1. Goal

In this lesson we’re going to analyze a very popular OAuth2 Grant Type Flow, the Authorization Code Flow.


2. Lesson Notes

We'll focus only on understanding how the flow is executed, with no code involved at this point. Therefore, there is no need to checkout anything from our code repository.


2.1. The Authorization Code Flow Actors

Let’s begin with the high-level actors that will interact in the flow:

The Resource Owner will be the end-user of our application. Its role is to explicitly grant access to the Client for its protected resources.

Now, there are many types of clients, but, for the purpose of our discussion here, we’re going to consider a traditional MVC application with a server-side component as well as a client-side component executed by a user-agent - the browser in our case.

The Authorization Code flow involves redirections and interactions with the user as we'll see next.


2.2. The Authorization Code Flow Steps

Step 1: The Authorization Endpoint

The flow starts when the Client requests authorization to access a protected resource. The user-agent will be redirected to the Authorization Endpoint of the Authorization Server.

The OAuth2 specification indicates that the following parameters can be included in the request:

response_type

With a code value when we use the Authorization Code flow.

client_id

Represents the identifier of the client previously registered in the Authorization Server.

redirect_uri

A URI pointing to an endpoint in the Client application capable of handling the Authorization response.

It is usually required to register a whitelist of valid Redirect URIs. As per the specification, this param is required only if the Client registers multiple Redirection Endpoints, but in practice, many Authorization Servers require it anyway.

scope

Indicates which 'permissions' will be granted with the Access Token, for example, read and write access.

The supported values are defined by the Authorization Server.

Multiple values can be specified in the request by separating them with whitespaces.

state

This is used for security purposes, to prevent Cross-Site Request Forgery (CSRF) attacks.

For example, the request to this endpoint might look like this:

Note there are no client credentials involved in the request; their confidentiality can’t be guaranteed on the client-side.


Step 2: Authenticating the Resource Owner

The Authorization Server authenticates the Resource Owner and asks to grant or deny the permissions that the Client requested.


Step 3: The Redirection URI

This interesting step is what makes this flow different and more secure than the other OAuth flows.

The Access Token is not issued yet at this point, because, as we said, this is all passing through the user agent - the browser - on the client-side, and there is no guarantee that things are handled securely in this domain.

Instead, the Authorization Server returns an intermediary code, the Authorization Code (hence the name of the flow).

Basically, the browser is redirected back to the redirect URI in the Client application. Remember, we supplied that URI at the very beginning of the flow.

The call includes the Authorization Code as a query parameter. This is a code generated by the Authorization Server, usually short-lived for security reasons and that should be used only once.

Let's see how this URI might look like:

Naturally, the state param has to match the one provided in the Authorization request, and the Client should perform this validation.

If the Resource Owner denied access, then the response includes error information instead of the code parameter:

  • error: the error code (access_denied, invalid_request, unauthorized_client,...)
  • error_description: with additional information to help understand the error that occurred
  • error_uri: pointing to a web page with information about the error


Step 4: The Access Token Endpoint

The Client app now needs to exchange the Authorization Code for an Access Token. This is done by sending a POST request to the Authorization Server's Token Endpoint with some specific parameters:

grant_type

Has to be authorization_code to indicate we're using this flow.

code

The temporary code issued in a previous step.

redirect_uri

The RFC indicates this is required only if it was sent in the Authorization request in the first place. Has to match exactly with the one sent previously.

Additionally, the Client has to authenticate with the Authorization Server, usually by providing the Client Id and a Client Secret. These can be sent using HTTP Basic Authentication or in the body of the request:

Note that, unlike the previous steps where everything was passing through the user-agent, here the request is made from the Client application on the server-side directly to the Authorization Server.

That’s why it can be considered safe to handle the Client credentials at this stage and include these in the request together with the Authorization Code.


Step 5: The Access Token Response

If the request is valid and authorized, the Authorization Server finally issues an Access Token. The token and its validity period is retrieved in this response, among other relevant fields:

Step 6: Access the Protected Resource

Now finally the Client can request secured resources using the Access Token.

The Authorization Server includes information on how to use the Token within the Access Token response.

For instance, if the token_type value of the response is Bearer, then the Token is utilized by simply including it in a request header.


2.3. Refresh Token Support

It’s also worth mentioning that in the Authorization Code flow, the usage of Refresh Tokens is a mechanism to deal with the short-lived Access Tokens.

But we’ll analyze this topic in a future lesson.


2.4. OAuth 2.1 Notes

OAuth 2.0 didn’t impose strict restrictions on how the registered/whitelisted Redirect URI is used to check the redirect_uri query parameters provided in the Authorization Code flow matches.

Because of this, some Authorization Servers allow the use of patterns instead of complete URLs, and this implies security vulnerabilities.

Therefore, OAuth 2.1 explicitly establishes that the Client must register an absolute URI, and that this should match exactly with the one provided in the Authorization request.

Furthermore, since the original purpose of sending the Redirect URI in the Token request was to prevent an Authorization Code injection attack, and that is averted differently in the new version (using PKCE parameters), this parameter is not used in the Token Endpoint anymore (it can still be used if the Authorization Server wants to be compliant with both OAuth versions, though).


3. Resources

- IETF OAuth 2.0 Authorization Framework Specifications

- Front-End App with Spring Security OAuth – Authorization Code Flow

M2 - The Authorization Code Flow - transcript.pdf
Complete and Continue