Skip to main content
This page is for Authlete 2.x. For current (3.0) documentation, see this page.

Preface

This document describes overview of security provisions defined in Financial-grade API Security Profile 1.0 - Part 2: Advanced (hereinafter called “FAPI”) and configuration instructions of Authlete through steps for building a FAPI compliant authorization server. It is strongly advised that you have basic knowledge of OpenID Connect and Authlete by doing the following tutorial.

Components

In this tutorial, we assume the following components. Note that only Authlete’s consoles and APIs are up and running, while an authorization server (OIDC identity provider) 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 (OIDC relying party).
NoteIn this tutorial, OIDC identity provider and relying party are described as authorization server and client respectively for convenience.
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.

Interaction between API client and API server using FAPI

In this document, you will configure Authlete to enable the following token granting process and API access flows in a FAPI-compliant manner.

1. Authorization request

A FAPI-compliant client has to employ a request object to craft an authorization request to a FAPI-compliant authorization server. The request object is passed to the server by either value (using request parameter) or reference (request_uri parameter). In this document, the client will be using the former one. In addition to the request object, you have to comply with other security provisions of FAPI, such as response_type parameter. In this document, the client will be using response_type=code id_token. Other settings, including claims, are to be explained later.

2. Authorization response

In this document, the server will be making a response include the code as a fragment since response_type=code id_token is specified in the previous step. (Note: FAPI security provisions do not allow an authorization server to include an authorization code as a query string in an authorization response.)

3. Token request

An authorization server has to employ public key methods to authenticate clients on receiving a token request. In this document, the server will be using mutual TLS authentication.

4. Token response

An authorization server has to bind an access token with a client certificate obtained from mutual TLS communication at token endpoint of the server, and make a token response to the client.

5. API request

An client and a resource server have to establish a mutual TLS communication. The resource server will be verifying the binding between the client certificate and the access token in an API request and then making a response if the binding is valid.

Initial setup

Adding a new Authlete service with a client

Adding a new Authlete service and enabling FAPI support

Log into Authlete’s Service Owner Console https://so.authlete.com/ and click “Create Service” button. You will see the service creation page. Enter Service Name and Token Issuer Identifier as follows, and click “Create” button. Press “OK” in a dialog for confirmation. The new service has been created. Automatically generated values of “API Key” and “API Secret” will be used as “Login ID” and “Password” to log in to Developer Console, as well as credential for your authorization server to make requests to Authlete APIs. Let’s enable FAPI support of the service. Click “Edit” button in the bottom of the page to make settings editable and go to Authorization tab. There should be FAPI with a checkbox, which is unchecked, on Supported Service Profiles. Check the box and click “Update” button in the bottom of the page. Press “OK” in a dialog for confirmation. Click “Edit” button to make settings editable again, and go to Token tab. There should be Supported Scopes and some predefined scopes such as address and openid. Click “Create Scope” button on the right side so that you can see a dialog to define a scope. Add a new scope with the following parameters.

Adding a new client and basic settings

Open the link to Authlete’s Developer Console for the service (https://cd.authlete.com/<API Key> e.g. https://cd.authlete.com/174381609020) and log in to the console with your API Key and API Secret as Login ID and Password respectively. Click “Create App” button on the right side and enter/choose the following values (Client Name and Client Type) in Basic tab. Then click Authorization tab next to the Basic, click Create Redirect URI button in Redirect URIs section, and enter the following value for a New Redirect URI. Click “Create” button in the bottom of the page. Press “OK” in a dialog for confirmation. Now you’ve done registration of the client to the service. Automatically generated values of “Client ID” will be used as client_id for the client to make requests to the authorization server. “Client Secret” is generated as well, but it is never used in this tutorial. Also make sure other values are set as expected.

Testing the initial configuration

Let’s check how Authlete works with the initial configuration. We will use POST /auth/authorization API for that purpose.

Authorization request for non-FAPI scope

Let’s assume that the auhtorization server receives an authorization request (scope=openid) that doesn’t include any scopes subject to FAPI. The server will make a request to POST /auth/authorization API. Here’s a curl version of the request.
Make sure to replace API Key, API Secret, Client ID by your own values generated in the previous step.
Make sure to replace API Key, API Secret, Client ID by your own values generated in the previous step.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.
Authlete makes the following response (folded for readability).
According to the value of resultMessage, Authlete accepted the authorization request when its scopes are not FAPI-related. So what happens if the request includes FAPI scopes? Let’s try it in the next section.

Authorization request for FAPI scope (Part 1)

Let’s assume the authorization server receives an authorization request (scope=openid payment) that does include a scope (payment) subject to FAPI. The server will make a request to POST /auth/authorization API. Here’s a curl version of the request.
Authlete makes the following error response (folded for readability).
According to the value of resultMessage, response_type=code is not allowed. This is due to security provisions of FAPI. 5.2. Advanced security provisions / 5.2.2. Authorization server states as follows.
  • shall require
    1. the response_type value code id_token, or
    2. the response_type value code in conjunction with the response_mode value jwt;
Thus you have to use either response_type=code id_token, or response_type=code with response_mode=jwt in a FAPI-compliant environment. In other words, response_type=code without the response_mode=jwt parameter is prohibited i.e. an authorization server must not accept them.

Authorization request for FAPI scope (Part 2)

So, how about an authorization request that includes response_type=code id_token instead of response_type=code? Let’s make a request to POST /auth/authorization API as follows.
Again Authlete makes another error response.
According to the value of resultMessage, a request object is required to proceed. This is due to security provisions of FAPI. The same section, 5.2. Advanced security provisions / 5.2.2. Authorization server states as follows.
  • shall only use the parameters included in the signed request object passed via the request or request_uri parameter;
An authorization server has to mandate clients to pass a request object by value (request) or by reference (request_uri). So let’s craft an authorization request with a request object in the next section to make the request FAPI-compliant.

Making a FAPI-compliant authorization request

In this section, we will create an authorization request using a a request object.

Request object settings

Configuring a signing key used for a request object

We have to prepare a key for a client to sign to a request object. In this document, we will use mkjwk to create an ES256 key pair, and two types of key sets; One includes a private key and other one doesn’t. Parameters for mkjwk are as follows. Here are examples of a generated key set and a derived set without a private key.
  • es256_keyset.txt (including a row of a private key "d")
  • es256_keyset_pub.txt (excluding a row of a private key "d" from es256_keyset.txt)

Additional client settings

In order for Authlete service to verify a signature of a request object coming from a client, you have to register its public key to the client’s settings and specify a signing algorithm that the client uses. Log into Developer Console for the service (https://cd.authlete.com/<API Key> e.g. https://cd.authlete.com/174381609020) and configure the client’s settings as follows.
  • JWK Set tab
  • Authorization tab
Now we have finished preparation to have Authlete verify a signature of a request object.

Creating a request object

Let’s act as a client generating a request object and crafting an authorization request with the object. Here is a sample payload in this document. Enter the correct values of client_id, nbf and exp. payload.txt
The following example shows how to generate values of nbf and exp:
  1. nbf claim: get the current Unix time using some method (for example, date +%s) and add it to the payload as the value of nbf. If you get 1613373232 as the result of date +%s, add this line to payload.txt:
  2. exp claim: specify a new value which is the sum of the value of nbf and 3600. If "nbf":1613373232 is used, the new value is 1613373232 + 3600 = 1613376832 and the line of the exp claim in payload.txt should be:
The client will be creating a signed JWT with the private key generated in the previous section. In this document, we use mkjose for example. Enter/choose values for each item and click “Generate” so that you can find the signed JWT in Output section. Another example using step CLI is as follows.
In this document, the following result was made. This will be used as a value of request parameter in an authorizaiton request.

Testing the configuration

Let’s assume that the auhtorization server receives an authorization request, including a request object, from a client. The server will make a request to POST /auth/authorization API. Here’s a curl version of the request.
Authlete will make a response (folded for readability) like this.
According to the value of resultMessage, Authlete accepted the authorization request. The response includes ticket as expected. An authorization server is to store the value of ticket into the user’s login session, and attempt to authenticate the user and obtain consent. Once completed, the server will make a request to Authlete’s POST /auth/authorization/issue API to generate an authorization response. In this document, the authorization request shown in the previous section included response_type=code id_token. So Authlete is expected to generate an authorization response that includes an authorization code code and an ID token id_token in fragment. Let’s assume the auhtorization server authenticates the user, obtains consent and determines that the user’s unique identifier (subject) is testuser01. The server will be making a request to Authlete’s POST /auth/authorization/issue API with the ticket and the subject. Here’s a curl version of the request.
Authlete makes the following response (folded for readability).
According to the value of resultMessage, Authlete doesn’t allow HS256 (Authlete’s default settings) as a signing algorithm for ID token. This is due to security provisions of FAPI. 8.6. Algorithm considerations states as follows.
  • shall use PS256 or ES256 algorithms;
Thus a client and an authorization server have to employ either ES256 or PS256 as JWS algorithm. In this document, we will be configuring Authlete to use ES256 for ID token signing algorithm.

Making a FAPI-compliant authorization response

Changing ID token signing algorithm

Adding a signing key for ID token

Now we are going to generate an ES256 key set and register it to Authlete as a signing key for ID token. We will be also updating the client settings to specify ES256 as a signing algorithm for the client. See the following article in Authlete Knowledge Base for instructions.
NoteThe key set being generated in this section is for an authorization server to sign ID tokens, while the other key set generated and registered in the previous section “Configuring a signing key of a request object” is to verify a signature in a request object from a client to an authorization server. Please make sure those two key sets are different.
Parameters for mkjwk are as follows. Register the generated “Keypair set” to the service by logging into Authlete’s Service Owner Console https://so.authlete.com/, adding the keypair set to “JWK Set Content” section in JWK Set tab, and enter a value of kid of the keypair set, 1 in this example, to “ID Token Signature Key ID” section in the same page. Then log into Developer Console for the service (https://cd.authlete.com/<API Key> e.g. https://cd.authlete.com/174381609020), click a link to the client, click “Edit” button in the bottom of the page to make settings editable, and go to ID Token tab. There should be ID Token Signature Algorithm section. Choose ES256 from dropdown list and click “Update” button. Those configuration will have Authlete select ES256 as a signing algorithm for issuing ID token for this client and use the registered ES256 key.

Testing the configuration (ES256 for ID token)

Let’s check if Authlete works as expected. Make the same request again to POST /auth/authorization API to get a ticket at first.
You should be able to obtain a response (folded for readability) including ticket.
Make a request with the value of the ticket and an arbitrary value of subject (testuser01 in this example) to POST /auth/authorization/issue API.
Authlete makes the following response (folded for readability).
According to the value of resultMessage, Authlete successfully processed the request. There are an issued ID token and an authorization code in idToken and authorizationCode respectively, and HTTP response content in responseContent. The content includes these token and code as fragment and is intended to be sent from an authorizartion server to a client as an authorization response. Once the client received the response from the authorization server it will verify the ID token. If the verification is done successfully, it will extract c_hash from the ID token and use it to verify the authorization code. If the second verification is also done successfully, the client will make a token request with the code to the authorzation server. The authorization server will make a request including the token request, to Authlete’s POST /auth/token API to have the API generate a token response which should include an access token. Here’s a curl version of the request to POST /auth/token API.
Authlete makes the following error response (folded for readability).
According to the value of resultMessage, the client authentication method of none, which is the default value of Authlete, is not allowed for confidential clients. This is due to security provisions of FAPI. 5.2 Read and write API security provisions / 5.2.2. Authorization server states as follows.
  • shall authenticate the confidential client using one of the following methods (this overrides FAPI Security Profile 1.0 - Part 1: Baseline clause 5.2.2-4):
    1. tls_client_auth or self_signed_tls_client_auth as specified in section 2 of MTLS, or
    2. private_key_jwt as specified in section 9 of OIDC;
Thus you have to use either Mutual TLS for OAuth Client Authentication defined in RFC 8705 or private_key_jwt defined in OpenID Connect Core 1.0. That is, other methods such as none, client_secret_basic that is popular one for confidential clients, are prohibited i.e. an authorization server must not employ them to authenticate clients. In this document, we will be having Authlete use the former one and PKI Mutual-TLS Method (tls_client_auth) defined in the method.

Making a FAPI-compliant token request

TLS client authentication configuration

Let’s configure both the service and the client settings to enable TLS client authentication.

Service settings for TLS client authentication configuration

Log into Authlete’s Service Owner Console https://so.authlete.com/, click “Edit” button in the bottom of the page to make settings editable, and go to Authorization tab. There should be Token Endpoint section. Check the box at Supported Client Authentication Methods and click “Update” button in the bottom of the page. Press “OK” in a dialog for confirmation.

Client settings for TLS client authentication configuration

Log into Developer Console for the service (https://cd.authlete.com/<API Key> e.g. https://cd.authlete.com/174381609020) and configure the client’s settings at “Token Endpoint” section in Authorization tab as follows. WIth those settings above, Authlete will support mutual TLS authentication for client authentication and apply the method to process token requests from the client. Subject DN CN=client.example.org, ... is used as the identifier of the client.

Generating a self-signed certificate

You have to prepare a digital certificate for the client to be authenticated by the authorization server. The subject DN of the certificate must be the same as one that has been specified in the previous section, CN=client.example.org, ... in this document. The following example illustrates that generating a self-signed certificate by using OpenSSL.
  • Generating a private key
  • Generating a CSR
    • Using CN=client.example.org, O=Client, L=Chiyoda-ku, ST=Tokyo, C=JP as Subject DN
  • Generating a certificate
The following one is a certificate generated in this example. server.crt
The certificate gets transformed into one line as follows, so that it can be used in requests with curl command.

Testing the configuration (Mutual TLS)

Let’s check if Authlete works as expected. Run the same procedure again.
  1. Make a request to POST /auth/authorization API and obtain a value of ticket from a response
  2. Make a request to POST /auth/authorization/issue API and obtain a value of authorizationCode from a response
  3. Make a request with the following modification to POST /auth/token API
  • Add clientCertificate parameter with the client certificate as its value
  • Remove clientSecret parameter (it is no longer required as mutual TLS authentication is effective)
Here’s a curl version of the request to POST /auth/token API.
Authlete makes the following response with caution (folded for readability).
According to the value of resultMessage, Authlete didn’t perform “Holder of Key” method, which is mandatory to comply with the security provisions of FAPI, while an access token has been issued. Thus the issued access token is not bound with the TLS client certificate of the client.

Making a FAPI-compliant token response

Holder of Key configuration

Service settings for access token configuration

Log into Authlete’s Service Owner Console https://so.authlete.com/, click “Edit” button in the bottom of the page to make settings editable, and go to Token tab. There should be Access Token section. Choose the following option for TLS Client Certificate Bound Access Tokens.

Client settings for access token configuration

Log into Developer Console for the service (https://cd.authlete.com/<API Key> e.g. https://cd.authlete.com/174381609020), click a link to the client, click “Edit” button in the bottom of the page to make settings editable, and go to Basic tab. Choose the following option for TLS Client Certificate Bound Access Tokens. Congraturations! Finally you have finished configuration of Authlete to support a FAPI-compliant authorization server.

A complete example walk through

Once the configuration is done you are able to check if Authlete works as expected. Make requests, which are the same as the ones in the previous section, to POST /auth/authorization API, POST /auth/authorization/issue API and POST /auth/token API. In addition to these three requests, make another request to /auth/introspection API to see if the access token used for API requests to a resource server is bound with the TLS client certificate of the client.

Authorization request

  • Response (folded for readability)

Authorization response

  • Response (folded for readability)

Token request and token response

  • Response (folded for readability)

API request

After the procedure above, we have got an access token whose value is SUtEVc3Tj3D3xOdysQtssQxe9egAhI4fimexNVMjRyU in this example. Let’s assume that the resource server receives an API request, including the value as the access token, from the client. The token in the request would be in Authorization: Bearer header. The resource server is to verify the token and obtain related information with it, by making a request to /auth/introspection API. The resource server will also include the client certificate, which should be able to obtained from mutual TLS communication for the API request, into the request to Authlete.
  • Response (folded for readability)
The resource server is now able to find that the access token from the client has been verified and get the associated information with the token such as subject and scopes.

Conclusion

In this tutorial, we reviewed security provisions defined in Financial-grade API Security Profile 1.0 - Part 2: Advanced and configuration instructions of Authlete through steps for building a FAPI compliant authorization server.