Last time we covered the OAuth 2.0 Authorization Framework and dove into the Authorization Grant called Client Credentials. Let’s move to the next Authorization Grant known as Resource Owner Password Credentials (ROPC) or Password Grant Type.
Quick refresh of OAuth 2.0
OAuth 2.0 is about access delegation between parties using a token that defines that access. The token is used in place of establishing a username and password between the various parties as those can be more easily compromised and are harder to maintain. OAuth 2.0 RFC-6749 jumps into that breakdown early as to why there are challenges with that approach. To help users understand the framework, the RFC defines roles for the parties and grant types as a means of categorizing the authentication interaction. Each grant type has one or more suggested use case.
Here are the roles again:
- Resource Owner: The entity who is granting access to a protected resource.
- Resource Server: The thing that is protected and takes access tokens. In our case, the REST API.
- Client: The application you do not want to give your password to but needs to access the Resource Server. We will talk more later about how we are about to contradict this.
- Authorization Server: The server that issues an access token once you have authenticated successfully as the Resource Owner.
Here is the list of grant types starting from highly trusted to least trusted in a manner of speaking:
- Client Credentials
- Resource Owner Password Credentials (ROPC or Password Grant Type)
- Authorization Code
Trust in this context is based on how well the Client can confidentially maintain its credentials.
Resource Owner Password Credentials or Password Grant Type
Resource Owner Password Credentials Grant Type is a mouthful. You will more commonly hear people talk about it as ROPC or Password Grant Type. For the purposes of this blog, I will refer to it as ROPC. ROPC is recommended for trusted relationships between the Client and Resource Owner where the Client can be trusted to acquire your username and password. The Client passes your username and password to the Authorization Server along with its own credentials for validation and token generation by the Authorization Server. You may see this grant type used with trusted native applications (like a desktop or mobile application created by the service owner or trusted party) to access your company intranet or portal to update or review HR data or other helpful company resources for authenticated users.
Here are the high-level steps involved:
- Resource Owner provides username and password to the Client.
- Client requests an access token from the Authorization Server passing along its own registered credentials along with the Resource Owner’s username and password.
- Authorization Server authenticates the Client and validates the Resource Owner’s username and password. Pending all is valid, the Authorization Server sends an access token with an optional refresh token back to the Client.
- Client discards the Resource Owner’s username and password and sends an API request along with the access token to the Resource Server.
- (OPTIONAL) If a refresh token is issued along with the access token, the Client can use the refresh token to get a new access and refresh token from the Authorization Server without re-validating the Resource Owner’s username and password.
UML Sequence diagram of ROPC Grant Flow with the Ferguson API Gateway
The Ferguson API Gateway can integrate with a third-party Authorization Server to facilitate ROPC grant type authorization needs. In this case, the API Gateway creates a façade layer over the Authorization Server and the backend service. Below is a UML sequence diagram that shows how a Client exchanges relevant credentials with the API Gateway and how the latter handles the rest of the Authorization and token generation process. Please note that how the Resource Owner and the Client exchange username and password is beyond the scope of this blog.
In the OAuth 2.0 Client Credentials Overview, you saw how Ferguson exchanges credentials (Key & Secret) for fetching an access token and used the preferred method of HTTP Basic authentication along with a Content-Type of “application/x-www-form-urlencoded” for the request body. We will continue to use that business practice in the sequence explanation below.
- Resource Owner initiates the request by providing the Client with its username and password required for the Authorization Server. Again, how this exchange occurs is beyond the scope of this blog but just know that it happens somehow.
- Client makes an API call to the specified ROPC OAuth2 token endpoint using its credentials from the developer portal in the form of a Basic authentication header that’s base64 encoded with padding.
- (Borrowing from the previous Client Credentials Grant Type example) Use the Key & Secret and base64 encode them:
base64 encode with padding (<KEY> + “:” + <SECRET>)
Which becomes: RnFDSE5TYmxJUzlBZ2Y3SkxwbjJLR0JMT1ZMQndKVWk6cngyS3BxQWpwVDhOQjd5dA==
- Take the base64 encoded value and use it as a Basic Authorization HTTP request header, set the Content-Type and add a form parameter of grant_type=password. In addition, the Client must pass on the username and password from the Resource Owner. Therefore, set username=abc123 and password=xyz456.
c. A curl request could look like this:
3.Once the API call hits the API Gateway, it decodes the Basic Authorization header and makes sure the Client’s creds are valid and enabled.
4. If the credentials are still valid, the API Gateway formulates a new secured request to include the Resource Owner’s username and password to send to the Authorization Server. It is important to note in this scenario, the API Gateway is not storing or doing any validation against the Resource Owner’s username and password. They are passed forward as requirements for the Authorization Server.
5. The Authorization Server validates that the Resource Owner’s creds are still valid and enabled.
6.Pending successful authentication, the Authorization Server will notify the API Gateway.
7.The API Gateway mints an access token and (optional) refresh token.
8. All the validations have occurred, and the API Gateway issues a successful JSON payload back to the Client to include an access token, token type, access token expires in value, and the optional refresh token along with its own expires in value. All of this is done via key/value pair format within the JSON payload. For example:
9. Should the Client be issued a refresh token and it chooses to use that to refresh an access token, the Client can make a new API call using the refresh token prior to its expiration.
a. The required parameters for the Client to call the API Gateway are slightly different this time. There is no relying on the Resource Owner’s username and password. Instead, the focus is on the refresh token received during the initial token request. We still need to authenticate with the API Gateway but that is it.
b. We will use the same Basic Authentication and Content-Type headers but modify the form parameters to refer to grant_type=refresh_token and set the refresh_token to the actual refresh token received earlier.
c. A curl request could look like this:
10.The API Gateway decodes the Basic Authorization header, ensures the Client’s creds and refresh token are authenticated and valid. Pending no issues with the token’s metadata and the refresh token is not expired, it mints an access token and (optional) refresh token.
11. After all the validations are confirmed, the API Gateway will issue a new successful JSON payload to include the new access token and (optional) refresh token. The Client must discard previous tokens and use the newest token(s) moving forward.
Please note: If any credentials are not valid at the API Gateway or Authorization Server, a 401 Unauthorized response would be returned to the Client by the API Gateway.
I have an access token – now what?
The Client should still use the valid access token to make the REST API call to the protected resource. How it does so is dependent on the access token type. If Ferguson’s “HelloWorld” REST API used ROPC (it does not) and Bearer token type, you could use that access token to call it. In the request, you would present the token as a “Bearer” token within the Authorization header. See this section for the steps (scroll towards bottom of page): Using your access token to make a “HelloWorld” REST API call.
If you had a different access token type (like mac or SAML), you would follow a different format. So always pay attention to the token type as each presents itself differently. And yes, this is beyond the scope of this blog.
ROPC should only be used in highly trusted relationships like service applications since the Resource Owner is sharing their username and password with the Client and relying on the Client to keep them confidential. Certainly, there are use cases for this grant type and it is simple to implement but understand the security implications and limitations. The Client should do everything it can to keep the username and password confidential from third parties while it has them. Fortunately, that is a short period of time since they are only needed for the initial access token request. Once that is complete, the Client can use the OAuth 2.0 refresh token authorization process for subsequent resource requests.
Stay tuned for discussions on other OAuth 2.0 grant types!