Lesson 1: The Authorization Code Flow (theory)
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:
With a code value when we use the Authorization Code flow.
Represents the identifier of the client previously registered in the Authorization Server.
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.
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.
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:
Has to be authorization_code to indicate we're using this flow.
The temporary code issued in a previous step.
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.