Table of Contents
This document is a tutorial to describe basic usage of Authlete APIs in order to implement OAuth 2.0 authorization server that supports authorization code grant flow.
In this tutorial, we assume the following components. Note that only Authlete’s consoles and APIs are up and running, while an authorization server and a resource server don’t actually exist.
Instead you will use curl command to simulate how these servers make API requests to Authlete on receiving authorization requests, token requests and token introspection requests from clients.
FODNs for each component are as follows. The authorization server and the client don’t exist as stated above, but their FQDNs are at least needed to explain the OAuth flow.
Component | FQDN |
---|---|
Authlete API | api.authlete.com |
Authlete Service Owner Console | so.authlete.com |
Authlete Developer Console | cd.authlete.com |
Authorization Server | as.example.com |
Client | client.example.org |
Resource Server | N/A |
Consult instructions “Sign-up to Authlete and Creating a Service“ to create a new Authlete API service and register a client to the service.
In this tutorial, we assume the following properties are generated or specified.
Item | Value |
---|---|
Client ID | Auto-generetad e.g. 12818600553323 |
Client Secret | Auto-generated e.g. -olDIKD9BihRfB8O1JxobUEKBZ7PIV5Z6oaqxAshmoUtUZgB-wjmmxTYDiDV6vM_Mgl267PeNrRftq8cWplvmg |
Client Type | CONFIDENTIAL |
Redirect URIs | https://client.example.org/cb/example.com |
Client Authentication Method | CLIENT_SECRET_BASIC |
Let’s try authorization code grant flow using this environment, in the next section.
Here is a sequence diagram in this tutorial. Message numbers in the diagram might help you understand the following steps.
The client makes an authorization request to the authorization server via user agent (message #2, #3). In this tutorial, let’s suppose the following values are specified as paramters in the request.
Item | Value |
---|---|
client_id | 12818600553323 |
response_type | code |
redirect_uri | https://client.example.org/cb/example.com |
The authorization server is to receive the following content (folded for readability) as HTTP GET query string from the user agent.
redirect_uri=https://client.example.org/cb/example.com
&response_type=code
&client_id=12818600553323
The authorization server is supposed to evaluate these parameters by itself. Typical evaluation rules are shown below. After that, the authorization server is going to process authorization code grant flow since the value of response_type
is code
.
12818600553323
has been registered to the authorization serverhttps://client.example.org/cb/example.com
matches with one of URIs registered to the clientresponse_type
, scope
are applicable for the client, i.e. permitted for the client to specify in its requestAuthlete’s /auth/authorization
API does the evaluation process on the authorization server’s behalf.
Let’s make a request to this API by acting as the authorization server.
For Linux/Mac, execute curl command as follows (message #4).
Make sure to replace API Key
, API Secret
, Client ID
by your own values generated in the previous step.
curl -s -X POST https://api.authlete.com/api/auth/authorization \
-u '<API Key e.g. 10738933707579>:<API Secret e.g. Xg6jVpJCvsaXvy2ks8R5WzjdMYlvQqOym3slDX0wNhQ>' \
-H 'Content-Type: application/json' \
-d '{ "parameters": "redirect_uri=https://client.example.org/cb/example.com&response_type=code&client_id=<Client ID e.g. 12818600553323>" }'
If you are using Windows 10's bundled curl.exe command via PowerShell, make sure the command is curl.exe
instead of curl
, escape "
characters and use `
to break lines. (message #4).
Make sure to replace API Key
, API Secret
, Client ID
by your own values generated in the previous step.
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization `
-u '<API Key e.g. 10723797812772>:<API Secret e.g. ekYoYTI84qZcpe6bXGzDwduQ1fGBYxJT8K8Tnwd7poc>' `
-H 'Content-Type: application/json' `
-d '{\"parameters\" : \"redirect_uri=https://client.example.org/cb/example.com&response_type=code&client_id=<Client ID e.g. 12800697055611>\"}'
If the request is appropriate, Authlete makes the following response (omitted for brevity) (message #5).
{
"resultMessage" : "[A004001] Authlete has successfully issued a ticket to the service (API Key = 10738933707579) for the authorization request from the client (ID = 12818600553323). [response_type=code, openid=false]",
"type" : "authorizationResponse",
"resultCode" : "A004001",
"client" : { [...] },
"ticket" : "cA0xUty6I64PnFTjer2g-iM5KIfGpssUHqkfDoMr0xk",
"action" : "INTERACTION",
[...]
"service" : {
[...]
"supportedClaims" : [
[...]
],
"supportedScopes" : [
[...]
],
}
}
Pay attention to three key/value pairs in the response; resultMessage
, action
and ticket
.
{
[...]
"ticket" : "cA0xUty6I64PnFTjer2g-iM5KIfGpssUHqkfDoMr0xk",
"action" : "INTERACTION",
"resultMessage" : "[A004001] Authlete has successfully issued a ticket to the service (API Key = 10738933707579) for the authorization request from the client (ID = 12818600553323). [response_type=code, openid=false]",
resultMessage
provides human-readable result of the request processing. (See also Interpreting Authlete’s result codes)action
indicates what the authorization server should do next.ticket
is required for the authorization server to make a request to another API in the next step.Authlete also provides service and client information in the response. The authorization server utilizes them to ask the resource owner if he or she authorizes access for the client to the service.
Actual interaction between the resource owner and the authorization server is out of scope in this tutorial. In most cases, authorization server would authenticate user with some credentials (e.g. ID/password), determine roles and privileges for the user, and ask the user if he or she authorizes access (message #6, #7).
Let’s assume the auhtorization server reaches the following state after completion of the previous process:
subject
parameter, is testuser01
.The authorization server makes a request to Authlete’s /auth/authorization/issue
for issurance of an authorization code. It specifies values of subject
and ticket
that were a part of the response from /auth/authorization
API, as request parameters.
Execute curl command as follows (message #8). Make sure to replace API Key
, API Secret
, Ticket
by your own values generated in the previous steps.
curl -s -X POST https://api.authlete.com/api/auth/authorization/issue \
-u '<API Key e.g. 10723797812772>:<API Secret e.g. ekYoYTI84qZcpe6bXGzDwduQ1fGBYxJT8K8Tnwd7poc>' \
-H 'Content-Type: application/json' \
-d '{ "ticket": "<Ticket e.g. bi2Kxe2WW5mK_GZ_fDFOpK1bnY6xTy40Ap_8nxf-7AU>", "subject": "testuser01" }'
Execute curl.exe as follows (message #8). Make sure to replace API Key
, API Secret
, Ticket
by your own values generated in the previous steps.
curl.exe -s -X POST https://api.authlete.com/api/auth/authorization/issue `
-u '<API Key e.g. 10723797812772>:<API Secret e.g. ekYoYTI84qZcpe6bXGzDwduQ1fGBYxJT8K8Tnwd7poc>' `
-H 'Content-Type: application/json' `
-d '{ \"ticket\": \"<Ticket e.g. bi2Kxe2WW5mK_GZ_fDFOpK1bnY6xTy40Ap_8nxf-7AU>\", \"subject\": \"testuser01\" }'
If the request is appropriate, Authlete makes the following response (message #9).
{
"responseContent" : "https://client.example.org/cb/example.com?code=3GIJORjvgaEdu2u4KHyaQdGxfHDFsiViwGyZUxeBVrM",
"authorizationCode" : "3GIJORjvgaEdu2u4KHyaQdGxfHDFsiViwGyZUxeBVrM",
"action" : "LOCATION",
"accessTokenDuration" : 0,
"resultMessage" : "[A040001] The authorization request was processed successfully.",
"type" : "authorizationIssueResponse",
"resultCode" : "A040001",
"accessTokenExpiresAt" : 0
}
Pay attention to three key/value pairs in the response; resultMessage
, action
and responseContent
.
resultMessage
provides human-readable result of the request processing. (See also Interpreting Authlete’s result codes)action
indicates what the authorization server should do next. The value in this response is LOCATION
, which means the authorization server should make a redirection response back to the user agent.responseContent
is supposed to be content of the response from the authorization server.The authorization server is expected to make the following response (folded for readability) to the user agent (message #10).
HTTP/1.1 302 Found
Location: https://client.example.org/cb/example.com
?code=3GIJORjvgaEdu2u4KHyaQdGxfHDFsiViwGyZUxeBVrM
It would be another case where the authorization server determines that it won’t issue tokens to the client due to the result of the previous authentication and confirmation. In that situation the authorization server has to tell the client that the authorization flow is terminated.
Authlete’s /auth/authorization/fail
API supports the termination process in terms of messages to be sent to the client, and transfer method for the response.
To summarize, an authentication server usually makes a request to either /auth/authorization/issue
or /auth/authorization/fail
API depending on result of user authentication and consent.
Here we assume that the user agent receives the redirection response form the authorization server. It would send the following request (folded for readability) to the client (message #11).
GET /cb/example.com?code=3GIJORjvgaEdu2u4KHyaQdGxfHDFsiViwGyZUxeBVrM HTTP/1.1
Host: client.example.org
The client would extract the value of the code
parameter, craft a token request with the value and send it to the authorization server as follows (folded for readability). https://as.example.com/token
is the token endpoint URI in this tutorial (message #12).
POST /token HTTP/1.1
Host: as.example.com
Authorization: Basic base64(12818600553323:-olDIKD9BihRfB8O1JxobUEKBZ7PIV5Z6oaqxAshmoUtUZgB-wjmmxTYDiDV6vM_Mgl267PeNrRftq8cWplvmg)
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=3GIJORjvgaEdu2u4KHyaQdGxfHDFsiViwGyZUxeBVrM
&redirect_uri=https://client.example.org/cb/example.com
The authorization server is supposed to evaluate parameters in the request, make a token response back to the client.
In this tutorial, let’s use Authlete’s /auth/token
API to evaluate the request and create the response.
Execute curl command as follows (message #13). Make sure to replace API Key
, API Secret
, Client ID
, Client Secret
and Code
by your own values generated in the previous steps.
curl -s -X POST https://api.authlete.com/api/auth/token \
-u '<API Key e.g. 10723797812772>:<API Secret e.g. ekYoYTI84qZcpe6bXGzDwduQ1fGBYxJT8K8Tnwd7poc>' \
-H 'Content-Type: application/json' \
-d '{ "clientId": "<Client ID e.g. 12800697055611>", "clientSecret": "<Client Secret e.g. dcDHEXr_tXNi7QdIMXLSXpXAy_j7Cr4C4LT2xAukQcW_09E2Ag1jTBdwpQrG-HBxflPF4Bz_Nb9Zd_ySAxOs6A>", "parameters": "grant_type=authorization_code&code=<Code e.g. GrYz5vtk6VaF0jxfnDrB2yvmk4deIrnMkrGT07JdM5U>&redirect_uri=https://client.example.org/cb/example.com" }'
Execute curl.exe as follows (message #13).Make sure to replace API Key
, API Secret
, Client ID
, Client Secret
and Code
by your own values generated in the previous steps.
curl.exe -s -X POST https://api.authlete.com/api/auth/token `
-u '<API Key e.g. 10723797812772>:<API Secret e.g. ekYoYTI84qZcpe6bXGzDwduQ1fGBYxJT8K8Tnwd7poc>' `
-H 'Content-Type: application/json' `
-d '{ \"clientId\": \"<Client ID e.g. 12800697055611>\", \"clientSecret\": \"<Client Secret e.g. dcDHEXr_tXNi7QdIMXLSXpXAy_j7Cr4C4LT2xAukQcW_09E2Ag1jTBdwpQrG-HBxflPF4Bz_Nb9Zd_ySAxOs6A>\", \"parameters\": \"grant_type=authorization_code&code=<Code e.g. GrYz5vtk6VaF0jxfnDrB2yvmk4deIrnMkrGT07JdM5U>&redirect_uri=https://client.example.org/cb/example.com\" }'
If the request is appropriate, Authlete makes the following response (message #14).
{
"accessTokenExpiresAt" : 1558627889220,
"refreshTokenDuration" : 864000,
"clientId" : 12818600553323,
"accessToken" : "-g5ZJDAfpTQAqR9mdnAfhv0zuCe3SUrKJ2_859zI1Ow",
"refreshToken" : "4PwVTovcwMgnNJbsH-BzeQj5a8nelOi0iEIswex-ueE",
"accessTokenDuration" : 86400,
"clientIdAliasUsed" : false,
"refreshTokenExpiresAt" : 1559405489220,
"grantType" : "AUTHORIZATION_CODE",
"subject" : "testuser01",
"action" : "OK",
"responseContent" : "{\"access_token\":\"-g5ZJDAfpTQAqR9mdnAfhv0zuCe3SUrKJ2_859zI1Ow\",\"refresh_token\":\"4PwVTovcwMgnNJbsH-BzeQj5a8nelOi0iEIswex-ueE\",\"scope\":null,\"token_type\":\"Bearer\",\"expires_in\":86400}",
"resultCode" : "A050001",
"type" : "tokenResponse",
"resultMessage" : "[A050001] The token request (grant_type=authorization_code) was processed successfully."
}
Pay attention to three key/value pairs in the response; resultMessage
, action
and responseContent
.
resultMessage
provides human-readable result of the request processing. (See also Interpreting Authlete’s result codes)action
indicates what the authorization server should do next. The value in this response is OK
, which means the authorization server should make a token response back to the client.responseContent
is supposed to be content of the response from the authorization server.The authorization server is expected to make the following response to the client (message #15).
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token":"-g5ZJDAfpTQAqR9mdnAfhv0zuCe3SUrKJ2_859zI1Ow",
"refresh_token":"4PwVTovcwMgnNJbsH-BzeQj5a8nelOi0iEIswex-ueE",
"scope":null,
"token_type":"Bearer",
"expires_in":86400
}
Finally, the authorization server successfully created the tokens and provided them to the client. By leveraging Authlete APIs, the authorization server doesn’t need to implement complicated logic to evaluate paramters in authorization / token request, and make appropriate responses for those requests with the correct method.
In most cases, the client would make a request with the access token to the resource server providing APIs (message #16).
The resource server is supposed to evaluate the validity of the token, retrieve information on the user and the client related to the token and determine how to respond to the API request.
Authlete provides /auth/introspection
API for such purpose. It checks the validity of the token and provide the information above.
Make sure to replace <API Key>
, <API Secret>
and <Token>
by your own values generated in the previous step.
Execute curl command as follows (message #13). Make sure to replace API Key
, API Secret
and Token
by your own values generated in the previous steps.
curl -s -X POST https://api.authlete.com/api/auth/introspection \
-u '<API Key e.g. 10723797812772>:<API Secret e.g. ekYoYTI84qZcpe6bXGzDwduQ1fGBYxJT8K8Tnwd7poc>' \
-H 'Content-Type: application/json' \
-d '{ "token": "<Token e.g. 7FfwOnGjVHwxXhs2Wr67XV1-ZhQaoy3ctKcGkLyKxuY>" }'
Execute curl.exe as follows (message #13). Make sure to replace API Key
, API Secret
and Token
by your own values generated in the previous steps.
curl.exe -s -X POST https://api.authlete.com/api/auth/introspection `
-u '<API Key e.g. 10723797812772>:<API Secret e.g. ekYoYTI84qZcpe6bXGzDwduQ1fGBYxJT8K8Tnwd7poc>' `
-H 'Content-Type: application/json' `
-d '{ \"token\": \"<Token e.g. 7FfwOnGjVHwxXhs2Wr67XV1-ZhQaoy3ctKcGkLyKxuY>\" }'
If the request is appropriate, Authlete makes the following response (message #18).
{
"resultMessage" : "[A056001] The access token is valid.",
"refreshable" : true,
"clientIdAliasUsed" : false,
"existent" : true,
"resultCode" : "A056001",
"expiresAt" : 1558627889000,
"responseContent" : "Bearer error=\"invalid_request\"",
"clientId" : 12818600553323,
"action" : "OK",
"usable" : true,
"sufficient" : true,
"subject" : "testuser01",
"type" : "introspectionResponse"
}
The resource server would be able to find bunch of information such as
expiration period of the token (expiresAt
), identifier of the user
who approved the access (subject
), identifier of the client
(clientId
). Then it is supposed to determine how to respond to the
API request (message #19).
In this tutorial, we were able to confirm how to use Authlete APIs to implement authorization code grant flow into authorization server.
Let’s dig deeper on Authlete by playing with the following features.
/auth/authorization/fail
API (See Generating error response with “fail” API)