Guest Blog: Financial-grade API (FAPI) Explained by an Implementer
Introduction
Financial-grade API (FAPI) is a technical specification that Financial-grade API Working Group of OpenID Foundation has developed. It uses OAuth 2.0 and OpenID Connect (OIDC) as its base and defines additional technical requirements for the financial industry and other industries that require higher security.

The latest version is Implementer’s Draft 2 which was approved in October, 2018. Part 1 and Part 2 are freely viewable at the website of OpenID Foundation. Part 1 is a security profile for read-only APIs, and Part 2 is a security profile for read-and-write APIs.
- Financial-grade API – Part 1: Read-Only API Security Profile
- Financial-grade API – Part 2: Read and Write API Security Profile
The difference from the Implementer’s Draft 1 (which was approved in February and July, 2017) is not so small, so FAPI implementers have to check it.
It should be noted that the foreword of FAPI Implementer’s Draft 2 indicates that Client Authentication Backchannel Authentication (CIBA) is positioned as Part 3 of FAPI. For details about CIBA, please read the following article.
This article explains Financial-grade API security profile.
Certification Program
The certification program for FAPI officially started on April 1, 2019 (announce). Two vendors were granted certification on the start day.
Authlete, Inc., the company founded by the author of this article (me), is one of the two vendors. Please contact Authlete, Inc. (sales@authlete.com) if you are interested in a certified implementation of Financial-grade API OpenID Provider.
0. Prior Knowledge
0.1. Basic Specifications
The format of the FAPI specification is a terse list of technical requirements, so the document is not long. In exchange, a lot of prior knowledge is required to read it smoothly. Especially, you have to learn RFC 6749 and RFC 6750 (the core of OAuth 2.0) and OpenID Connect Core 1.0 (the core of OpenID Connect) by heart.
In addition, because specifications related to JWT (JWS, JWE, JWK, JWA and JWT) are prior knowledge to understand OIDC Core, they are of course prior knowledge to read the FAPI specification. Therefore, you need to understand them perfectly.
Furthermore, PKCE (RFC 7636) which was published in September, 2015 is now regarded as a part of the basic set of OAuth 2.0 specifications as well as RFC 6749 and RFC 6750.
The following is a list of specifications that you should read at least once before the FAPI specification.
- RFC 6749 — The OAuth 2.0 Authorization Framework
- RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage
- RFC 7515 — JSON Web Signature (JWS)
- RFC 7516 — JSON Web Encryption (JWE)
- RFC 7517 — JSON Web Key (JWK)
- RFC 7518 — JSON Web Algorithms (JWA)
- RFC 7519 — JSON Web Token (JWT)
- RFC 7523 — JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants
- RFC 7636 — Proof Key for Code Exchange by OAuth Public Clients
- OpenID Connect Core 1.0
- OpenID Connect Discovery 1.0
- OpenID Connect Dynamic Client Registration 1.0
- OAuth 2.0 Multiple Response Type Encoding Practices
- OAuth 2.0 Form Post Response Mode
Articles below may help understanding these specifications.
- The Simplest Guide To OAuth 2.0
- Diagrams And Movies Of All The OAuth 2.0 Flows
- Diagrams of All The OpenID Connect Flows
- Understanding ID Token
0.2. Mutual TLS
In general, “Mutual TLS” means that a client is also required to present its certificate in a TLS connection. However, in the context of FAPI, Mutual TLS means the following two which are defined in “OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens” (MTLS).
- OAuth client authentication using a client certificate
- Tokens bound to a client certificate
0.2.1. OAuth Client Authentication using a Client Certificate
When a confidential client (RFC 6749, 2. Client Types) accesses a token endpoint (RFC 6749, 3.2. Token Endpoint), client authentication (RFC 6749, 2.3. Client Authentication) is required. Client authentication is a process where a client application proves it has its confidential authentication information.
There are several ways for client authentication. The following are client authentication methods listed in OIDC Core, 9. Client Authentication (except none
).
client_secret_basic
— Basic Authentication using a pair of client ID and client secretclient_secret_post
— Embedding a pair of client ID and client secret in a request bodyclient_secret_jwt
— Passing a JWT signed by a key based on a client secret with a symmetric algorithmprivate_key_jwt
— Passing a JWT signed by a private key with an asymmetric algorithm
In client_secret_basic
and client_secret_post
, a client application directly shows the server its client secret to prove that it has the confidential information.
In client_secret_jwt
, a client application indirectly proves that it has the client secret by signing a JWT with the client secret and passing the JWT to the server. On the other hand, in private_key_jwt
, signing is performed with an asymmetric private key and the server verifies the signature with the public key corresponding to the private key.
Apart from the above, “2. Mutual TLS for OAuth Client Authentication” of MTLS introduces new client authentication methods below.
tls_client_auth
— Utilizing a PKI client certificate used in a TLS connectionself_signed_tls_client_auth
— Utilizing a self-signed client certificate used in a TLS connection
These two utilize the client certificate used in a TLS connection between the client and the token endpoint for client authentication.
In tls_client_auth
, the PKI client certificate used in a TLS connection established between a client and a server is used for client authentication. The server verifies the client certificate (this should be done even in a context irrelevant to OAuth) and then checks whether the Subject Distinguished Name or Subject Alternative Name matches the pre-registered one. For this process, client applications that want to use tls_client_auth
for client authentication must register Subject Distinguished Name or Subject Alternative Name into the server in advance. The specification newly defines the following client metadata for this purpose.
tls_client_auth_subject_dn
tls_client_auth_san_dns
tls_client_auth_san_uri
tls_client_auth_san_ip
tls_client_auth_san_email
In self_signed_tls_client_auth
, a self-signed client certificate is used instead of a PKI client certificate. To use this client authentication method, client applications have to register a self-signed client certificate into the server in advance.
The following table is the list of client authentication methods mentioned in FAPI.
0.2.2. Certificate-Bound Tokens
Once a traditional access token is leaked, an attacker can access APIs with the access token. Traditional access tokens are just like a train ticket which anyone can use once it is stolen.
An idea to mitigate this vulnerability is to check whether the API caller bringing an access token matches the legitimate holder of the access token when an API call is made. This is just like the boarding procedure for international flights where passengers are required to show not only a plane ticket but also their passport.
FAPI calls this idea “holder of key mechanism” and lists “Mutual TLS” and “Token Binding” as possible deployment options for the mechanism. In this context, “Mutual TLS” means the specification defined in “3. Mutual TLS Client Certificate-Bound Access Tokens” of MTLS.
Because Mutual TLS has several meanings as explained above and I actually experienced a problematic conversation like below,
Me: The API management solution of your company does not support Mutual TLS (as a holder of key mechanism).
The company: Not correct. Our solution supports Mutual TLS (because it can be configured to request a client certificate for TLS communication).
I’ve personally decided to call Mutual TLS as a holder of key mechanism “Certificate Binding”. This naming is not so bad (at least for me) because it sounds symmetrical to Token Binding and because actual implementations will eventually become just binding a certificate to an access token and won’t care whether the certificate has been extracted from a mutual TLS connection or has come from somewhere else.
In an implementation of Certificate Binding, when the token endpoint of an authorization server issues an access token, it calculates the hash value of the client certificate presented by the client application in the TLS connection and remembers the binding between the access token and the hash value (or embeds the hash value into the access token if the implementation of the access token is a self-container-type JWT). When the client application accesses an API of the target resource server, it uses the same client certificate that was previously used in the communication with the token endpoint. The implementation of the API extracts an access token and a client certificate from the request, calculates the hash value of the client certificate and checks the hash value matches the one that is associated with the access token. If they match, the API implementation accepts the request. If not, it rejects the request.
It is relatively easy to implement Certificate Binding because it can be implemented only if the client certificate is accessible. On the other hand, Token Binding is relatively hard because it is necessary to modify multiple layers such as TLS layer and HTTP layer. In addition, the future is uncertain as Chrome has removed the Token Binding feature although the community strongly tried to urge Chrome team to rethink it (“Intent to Remove: Token Binding”). However, anyway, related specifications were promoted to RFCs at the beginning of October, 2018.
- RFC 8471 — The Token Binding Protocol Version 1.0
- RFC 8472 — Transport Layer Security (TLS) Extension for Token Binding Protocol Negotiation
- RFC 8473 — Token Binding over HTTP
“OAuth 2.0 Token Binding” (its status is still “draft” as of April 2019) is a specification that defines rules to apply Token Binding to OAuth 2.0 tokens based on the specifications listed above.
0.3. JARM
JARM is a new specification which was approved at the same timing with FAPI Implementer’s Draft 2. JARM is referred to in FAPI Part 2.
The specification defines new values for the response_mode
request parameter as shown below.
query.jwt
fragment.jwt
form_post.jwt
jwt
If one of the above is specified, response parameters of an authorization response are packed into a JWT and the JWT is returned as the value of a single response
response parameter.
For example, a traditional authorization response in the authorization code flow looks like below. code
and state
response parameters are included separately.
HTTP/1.1 302 Found
Location: https://client.com/callback?code={CODE}&state={STATE}
On the other hand, if response_mode=query.jwt
is added to an authorization request, the authorization response will become like below.
HTTP/1.1 302 Found
Location: https://client.com/callback?response={JWT}
1. Part 1: Read-Only API Security Profile
As introduction of prior knowledge was done, let’s start the main part of this article. To begin with, “Part 1” which defines security profile for read-only APIs.
1.1. Part 1: Requirements for Authorization Server
“5.2.2. Authorization server” in “Part 1” lists requirements for authorization server. Let’s take a look one by one.
Part 1: 5.2.2. Authorization server, 1.
shall support confidential clients;
Part 1: 5.2.2. Authorization server, 2.
should support public clients;
The definition of confidential clients and public clients is described in “2.1. Client Types” of RFC 6749. I don’t explain the difference between the client types here as it is prior knowledge for those who read the FAPI specification. However, the relationship between client types and OAuth 2.0 flows is often misunderstood even by those who are familiar with OAuth 2.0. It is only the combination of a public client and client credentials flow that RFC 6749 explicitly prohibits. Other combinations are allowed. Without this understanding, you would misread the FAPI specification.
Just FYI. It is confidential clients only that are allowed to make backchannel authentication requests which are defined in CIBA.
Part 1: 5.2.2. Authorization server, 3.
shall provide a client secret that adheres to the requirements in section 16.19 of [OIDC] if a symmetric key is used;
OIDC Core states that a value calculated based on a client secret must be used as the shared key when a symmetric algorithm is used for signing and encryption. If the entropy of the client secret is lower than the one required by the algorithm, the strength of the algorithm is weakened. Therefore, “16.19. Symmetric Key Entropy” requires that client secrets have entropy strong enough for used algorithms. For example, when HS256
(HMAC using SHA-256) is used for signing algorithm of ID tokens, client secrets must have 256-bit entropy at minimum.
Part 1: 5.2.2. Authorization server, 4.
shall authenticate the confidential client at the token endpoint using one of the following methods:
1. Mutual TLS for OAuth Client Authentication as specified in section 2 of [MTLS];
2.
client_secret_jwt
orprivate_key_jwt
as specified in section 9 of [OIDC];
Note that client_secret_basic
and client_secret_post
defined in RFC 6749 are not allowed as client authentication methods at the token endpoint.
Part 1: 5.2.2. Authorization server, 5.
shall require a key of size 2048 bits or larger if RSA algorithms are used for the client authentication;
Part 1: 5.2.2. Authorization server, 6.
shall require a key of size 160 bits or larger if elliptic curve algorithms are used for the client authentication;
For example, when private_key_jwt
is used as client authentication method and RSA is used for signing the JWT, the key size must be 2048 or more. Likewise, when an elliptic curve algorithm is used, the key size must be 160 at minimum.
Part 1: 5.2.2. Authorization server, 7.
shall require [RFC7636] with
S256
as the code challenge method;
It is required to implement RFC 7636 (PKCE) which is a countermeasure for “authorization code interception attack”.
RFC 7636 adds code_challenge
and code_challenge_method
request parameters to the authorization request and code_verifier
to the token request. Because the default value used when code_challenge_method
is omitted is plain
, authorization requests that comply with FAPI must include code_challenge_method=S256
explicitly.
Part 1: 5.2.2. Authorization server, 8.
shall require redirect URIs to be pre-registered;
In RFC 6749, registration of redirect URIs is not required under some conditions. For FAPI, registration of redirect URIs is always required.
Part 1: 5.2.2. Authorization server, 9.
shall require the
redirect_uri
parameter in the authorization request;
In RFC 6749, the redirect_uri
request parameter of an authorization request can be omitted under some conditions. For FAPI, the request parameter must be always included. OIDC has the same requirement.
Part 1: 5.2.2. Authorization server, 10.
shall require the value of
redirect_uri
to exactly match one of the pre-registered redirect URIs;
When an authorization server checks whether the value of the redirect_uri
request parameter matches a pre-registered one, the rule described in “6. Normalization and Comparison” of RFC 3986 (Uniform Resource Identifier (URI): Generic Syntax) is applied unless the pre-registered one is an absolute URI. On the other hand, FAPI (and OIDC also) requires that simple string comparison be always used to check whether the redirect URIs match.
Part 1: 5.2.2. Authorization server, 11.
shall require user authentication at LoA 2 as defined in [X.1254] or more;
It is required that user authentication performed during authorization process satisfy LoA (Level of Assurance) 2 which is defined in X.1254 (Entity authentication assurance framework). The following is the definition of LoA 2 described in “6.2 Level of assurance 2 (LoA2)” of X.1254.
At LoA2, there is some confidence in the claimed or asserted identity of the entity. This LoA is used when moderate risk is associated with erroneous authentication. Single-factor authentication is acceptable. Successful authentication shall be dependent upon the entity proving, through a secure authentication protocol, that the entity has control of the credential. Controls should be in place to reduce the effectiveness of eavesdroppers and online guessing attacks. Controls shall be in place to protect against attacks on stored credentials.
For example, a service provider might operate a website that enables its customers to change their address of record. The transaction in which a beneficiary changes an address of record may be considered an LoA2 authentication transaction, as the transaction may involve a moderate risk of inconvenience. Since official notices regarding payment amounts, account status, and records of changes are usually sent to the beneficiary’s address of record, the transaction additionally entails moderate risk of unauthorized release of PII. As a result, the service provider should obtain at least some authentication assurance before allowing this transaction to take place.
Part 1: 5.2.2. Authorization server, 12.
shall require explicit consent by the user to authorize the requested scope if it has not been previously authorized;
Of course.
Part 1: 5.2.2. Authorization server, 13.
should verify that the authorization code (section 1.3.1 of [RFC6749]) has not been previously used;
Prohibiting reuse of authorization codes and ensuring that authorization codes have never been used previously are different things. If the verification were mandatory (if the specification used “shall” instead of “should”), and if the current implementation of an authorization server used randomly-generated strings as authorization codes and removed them from the database after they are used, the authorization codes would have to be kept in the database even after they are used just only for the verification. If strings that represent authorization codes are generated randomly enough, it is wasteful to keep authorization codes in the database even after their use. A certain famous engineer says “Most implementations prevent reuse of authorization codes by deleting corresponding database records and don’t check if they have been used previously, and such implementations are sufficient enough.”
Part 1: 5.2.2. Authorization server, 14.
shall return token responses that conform to section 4.1.4 of [RFC6749];
This is not a FAPI-specific requirement. Every authorization server implementation that claims it supports OAuth 2.0 must conform to section 4.1.4 of RFC 6749.
Part 1: 5.2.2. Authorization server, 15.
shall return the list of granted scopes with the issued access token;
In RFC 6749, the scope
response parameter is optional unless requested scopes and granted scopes are different (RFC 6749, 5.1. Successful Response). In FAPI, the scope
response parameter must be always included.
Part 1: 5.2.2. Authorization server, 16.
shall provide opaque non-guessable access tokens with a minimum of 128 bits of entropy where the probability of an attacker guessing the generated token is less than or equal to 2^(-160) as per [RFC6749] section 10.10;
Entropy of access tokens must be 128 bits or more. For example, as 128-bit data becomes 22 characters when encoded by base64url, if an access token generated by your authorization server consists of ASCII letters only and its length is less than 22, it indicates that the authorization server implementation does not satisfy the requirement of Part 1, 5.2.2., 16.
Part 1: 5.2.2. Authorization server, 17.
should clearly identify long-term grants to the user during authorization as in 16.18 of [OIDC]; and
For example, if a given permission lasts long, an explanation like “The client application is requesting a permission to access your bank account to refer to your transaction history” is not enough. The explanation should be followed by an additional note like “This permission will be valid for three months.”
Part 1: 5.2.2. Authorization server, 18.
should provide a mechanism for the end-user to revoke access tokens and refresh tokens granted to a client as in 16.18 of [OIDC].
It should be noted that, if the format of access tokens is self-contained-type (e.g. JWT), the access tokens cannot be revoked unless the system implements and operates a mechanism like CRL (Certificate Revocation List) or OCSP (Online Certificate Status Protocol) of PKI (Public Key Infrastructure). If the system does not provide such mechanism, it means that the system has decided to give up revocation of access tokens. In this case, the duration of access tokens must be short enough to mitigate damage of access token leakage. See “OAuth Access Token Implementation” for further discussion.
Part 1: 5.2.2. Authorization server, 19.
shall return an
invalid_client
error as defined in 5.2 of [RFC6749] when mis-matched client identifiers were provided through the client authentication methods that permits sending the client identifier in more than one way;
FAPI Part 1 requires MTLS (tls_client_auth
, self_signed_tls_client_auth
) or JWT (client_secret_jwt
, private_key_jwt
) for client authentication.
MTLS uses a client certificate but a certificate does not include the client identifier of the client which tries to authenticate itself with the certificate. Therefore, the client_id
request parameter needs to be given explicitly.
On the other hand, JWT-based client authentication methods present a JWT as the value of the client_assertion
request parameter and the JWT contains the client identifier as the value of the iss
claim. Therefore, the client_id
request parameter is not necessary. In addition, according to RFC 7523, 3. and OIDC Core, 9., the sub
claim also holds the client identifier when a JWT is used for client authentication.
In MTLS, it is only the client_id
request parameter that represents a client identifier. On the other hand, in JWT-based client authentication, both the iss
claim and the sub
claim hold a client identifier. The values of the claims must match. Also, if the client_id
request parameter is redundantly given although JWT-based client authentication is used, the value of the request parameter must match the client identifier, too.
Part 1: 5.2.2. Authorization server, 20.
shall require redirect URIs to use the
https
scheme;
This sentence added by FAPI Implementer’s Draft 2 is short but has a big impact. Because of this sentence, developers cannot use custom schemes in FAPI any more. To process redirection on client side only without preparing an external Web server, developers have to use the method described in “7.2. Claimed “https” Scheme URI Redirection” of BCP 212 (OAuth 2.0 for Native Apps).
Part 1: 5.2.2.1. Returning authenticated user’s identifier Authorization server
Further, if it is desired to provide the authenticated user’s identifier to the client in the token response, the authorization server:
Section 5.2.2.1. lists requirements that an authorization server must follow when the authenticated user’s identifier is requested. In other words, when an ID token is requested.
Part 1: 5.2.2.1. Returning authenticated user’s identifier Authorization server, 1.
shall support the authentication request as in Section 3.1.2.1 of [OIDC];
“3.1.2.1. Authentication Request” of OIDC Core is the definition of a request to an authorization endpoint in the context of OpenID Connect. RFC 6749 calls a request to an authorization endpoint “authorization request”. OIDC Core calls it “authentication request”. Aside from the names, considering that the specification of an authorization endpoint is the main part of OIDC Core, the FAPI’s requirement is almost equal to stating “shall support OIDC Core”.
Part 1: 5.2.2.1. Returning authenticated user’s identifier Authorization server, 2.
shall perform the authentication request verification as in Section 3.1.2.2 of [OIDC];
Part 1: 5.2.2.1. Returning authenticated user’s identifier Authorization server, 3.
shall authenticate the user as in Section 3.1.2.2 and 3.1.2.3 of [OIDC];
Part 1: 5.2.2.1. Returning authenticated user’s identifier Authorization server, 4.
shall provide the authentication response as in Section 3.1.2.4 and 3.1.2.5 of [OIDC] depending on the outcome of the authentication;
Part 1: 5.2.2.1. Returning authenticated user’s identifier Authorization server, 5.
shall perform the token request verification as in Section 3.1.3.2 of [OIDC]; and
Part 1: 5.2.2.1. Returning authenticated user’s identifier Authorization server, 6.
shall issue an ID Token in the token response when
openid
was included in the requestedscope
as in Section 3.1.3.3 of [OIDC] with itssub
value corresponding to the authenticated user and optionalacr
value in ID Token.
Summary of the requirements above is “shall follow OIDC Core specification.” Nothing special for FAPI.
1.2. Part 1: Requirements for Public Client
“5.2.3. Public client” of “Part 1” lists requirements for public clients. Let’s take a look one by one.
Part 1: 5.2.3. Public client, 1.
shall support [RFC7636] or the mechanisms defined in Financial-grade API — Part 2;
RFC 7636 is PKCE, but what are “the mechanisms defined in Financial-grade API — Part 2”? This description is ambiguous.
Part 1: 5.2.3. Public client, 2.
shall use
S256
as the code challenge method for the [RFC7636];
This means “an authorization request must include code_challenge_method=S256
.”
Part 1: 5.2.3. Public client, 3.
shall use separate and distinct redirect URI for each authorization server that it talks to;
Part 1: 5.2.3. Public client, 4.
shall store the redirect URI value in the resource owner’s user-agents (such as browser) session and compare it with the redirect URI that the authorization response was received at, where, if the URIs do not match, the client shall terminate the process with error;
Part 1: 5.2.3. Public client, 5.
shall adhere to the best practice stated by [BCP212]; and
These requirements are clear enough.
Part 1: 5.2.3. Public client, 6.
shall implement an effective CSRF protection.
In normal cases, CSRF protection is implemented on server side. What is CSRF protection as a requirement for public clients? This is CSRF protection for redirect URIs. The following is an excerpt from “10.12. Cross-Site Request Forgery” of RFC 6749.
The client MUST implement CSRF protection for its redirection URI. This is typically accomplished by requiring any request sent to the redirection URI endpoint to include a value that binds the request to the user-agent’s authenticated state (e.g., a hash of the session cookie used to authenticate the user-agent). The client SHOULD utilize the “state” request parameter to deliver this value to the authorization server when making an authorization request.
In addition to the requirements from “Public client, 1” to “Public client, 6”, “if it is desired to obtain a persistent identifier of the authenticated user”, that is, if an ID token is requested, an authorization request by a public client:
Part 1: 5.2.3. Public client, 7.
shall include
openid
in thescope
value; andPart 1: 5.2.3. Public client, 8.
shall include
nonce
parameter defined in Section 3.1.2.1 of [OIDC] in the authentication request.
On the other hand, “If openid
is not in the scope
value”, an authorization request by a public client:
Part 1: 5.2.3. Public client, 9.
shall include the
state
parameter defined in section 4.1.1 of [RFC6749].
1.3. Part 1: Requirements for Confidential Client
“5.2.4. Confidential client” of “Part 1” lists requirements for confidential clients. The requirements are positioned as additions to the requirements for public clients. Therefore, confidential clients must follow not only the requirements in 5.2.4. but also the requirements in 5.2.3.
Part 1: 5.2.4. Confidential client, 1.
shall support the following methods to authenticate against the token endpoint:
1. Mutual TLS for OAuth Client Authentication as specified in section 2 of [MTLS];
2.
client_secret_jwt
orprivate_key_jwt
as specified in section 9 of [OIDC];
Note that client authentication methods defined in RFC 6749 (client_secret_basic
and client_secret_post
) cannot be used.
Part 1: 5.2.4. Confidential client, 2.
shall use RSA keys with a minimum 2048 bits if using RSA cryptography;
Part 1: 5.2.4. Confidential client, 3.
shall use elliptic curve keys with a minimum of 160 bits if using Elliptic Curve cryptography; and
Part 1: 5.2.4. Confidential client, 4.
shall verify that its client secret has a minimum of 128 bits if using symmetric key cryptography.
These requirements apply when encrypted JWTs are used.
1.4. Part 1: Requirements for Read-Only API
“6.2.1. Protected resources provisions” of “Part 1” lists requirements for read-only protected resource endpoints.
Part 1: 6.2.1. Protected resource provisions, 1.
shall support the use of the HTTP GET method as in Section 4.3.1 of [RFC7231];
Part 1: 6.2.1. Protected resource provisions, 2.
shall accept access tokens in the HTTP header as in Section 2.1 of OAuth 2.0 Bearer Token Usage [RFC6750];
That is, protected resource endpoints must support HTTP GET
method and be able to accept an access token in the format of Authorization: Bearer {AccessToken}
.
Part 1: 6.2.1. Protected resource provisions, 3.
shall not accept access tokens in the query parameters stated in Section 2.3 of OAuth 2.0 Bearer Token Usage [RFC6750];
That is, protected resource endpoints must not accept a query parameter in the format of access_token={AccessToken}
.
Part 1: 6.2.1. Protected resource provisions, 4.
shall verify that the access token is neither expired nor revoked;
Part 1: 6.2.1. Protected resource provisions, 5.
shall verify that the scope associated with the access token authorizes the reading of the resource it is representing;
Part 1: 6.2.1. Protected resource provisions, 6.
shall identify the associated entity to the access token;
Part 1: 6.2.1. Protected resource provisions, 7.
shall only return the resource identified by the combination of the entity implicit in the access and the granted scope and otherwise return errors as in section 3.1 of [RFC6750];
These are general steps of access token verification that protected resource endpoints are expected to take.
“3.1. Error Codes” of RFC 6750 defines three error codes. They are invalid_request
, invalid_token
and insufficient_scope
. One point those who are not familiar with RFC 6750 may feel strange is that an error code is embedded not in the response body but in the WWW-Authenticate
HTTP header.
Part 1: 6.2.1. Protected resource provisions, 8.
shall encode the response in UTF-8 if applicable;
Part 1: 6.2.1. Protected resource provisions, 9.
shall send the
Content-type
HTTP headerContent-Type: application/json; charset=UTF-8
if applicable;
Protected resource endpoints in FAPI are expected to return their responses in JSON format.
Part 1: 6.2.1. Protected resource provisions, 10.
shall send the server date in HTTP
Date
header as in section 7.1.1.2 of [RFC7231];
The format of Date
header is defined in “7.1.1.1. Date/Time Formats” of RFC 7231. Below is an example.
Date: Sun, 06 Nov 1994 08:49:37 GMT
Part 1: 6.2.1. Protected resource provisions, 11.
shall set the response header
x-fapi-interaction-id
to the value received from the corresponding fapi client request header or to a [RFC4122] UUID value if the request header was not provided to track the interaction, e.g.,x-fapi-interaction-id: c770aef3-6784-41f7-8e0e-ff5f97bddb3a
; and
This is a requirement specific to FAPI. Responses from FAPI protected resource endpoints must include an x-fapi-interaction-id
header.
Part 1: 6.2.1. Protected resource provisions, 12.
shall log the value of
x-fapi-interaction-id
in the log entry.
This is also specific to FAPI. This requirement doesn’t have any impact on request and response formats, but this can make it easy to correlate server-side logs and client-side logs.
Part 1: 6.2.1. Protected resource provisions, 13.
should support the use of Cross Origin Resource Sharing (CORS) [CORS] and or other methods as appropriate to enable JavaScript clients to access the endpoint if it decides to provide access to JavaScript clients.
For example, if a protected resource endpoint wants to allow JavaScript clients to access it from anywhere, the endpoint should include an Access-Control-Allow-Origin: *
header in responses.
1.5. Part 1: Requirements for Clients to Access Read-Only API
“6.2.2. Client provisions” of “Part 1” lists requirements for clients to follow in accessing read-only protected resource endpoints.
Part 1: 6.2.2. Client provisions, 1.
shall send access tokens in the HTTP header as in Section 2.1 of OAuth 2.0 Bearer Token Usage [RFC6750]; and
That is, clients send an access token in the format of Authorization: Bearer {AccessToken}
.
Part 1: 6.2.2. Client provisions, 2.
(withdrawn);
Part 1: 6.2.2. Client provisions, 3.
may send the last time the customer logged into the client in the
x-fapi-auth-date
header where the value is supplied as a HTTP-date as in section 7.1.1.1 of [RFC7231], e.g.,x-fapi-auth-date: Tue, 11 Sep 2012 19:43:31 GMT;
andPart 1: 6.2.2. Client provisions, 4.
may send the customer’s IP address if this data is available in the
x-fapi-customer-ip-address
header, e.g.,x-fapi-customer-ip-address: 198.51.100.119
; andPart 1: 6.2.2. Client provisions, 5.
may send the
x-fapi-interaction-id
request header whose value is a [RFC4122] UUID to the server to help correlate log entries between client and server, e.g.,x-fapi-interaction-id: c770aef3-6784-41f7-8e0e-ff5f97bddb3a
.
These are FAPI-specific HTTP headers. It is up to clients whether to send the headers or not.
1.6. Part 1: Security Considerations
“7. Security considerations” of “Part 1” lists security considerations. Summary is as follows.
7.1. — Follow BCP 195. Use TLS 1.2 or newer. Follow RFC 6125.
7.2. — Part 1 doesn’t authenticate authorization request and response.
7.3. — Part 1 doesn’t assure message integrity of authorization request.
7.4.1. — Part 1 doesn’t discuss encryption of authorization request.
7.4.2. — Be careful not to leak information through logs.
7.4.3. — Be careful not to leak information through referrer. Make duration of access tokens short.
7.5. — Native applications also must use https
for the scheme of redirect URI.
7.6. — Both FAPI implementation and underlying OAuth/OIDC implementation must be complete and correct. See OpenID Certification.
“Part 2” provides solutions for security considerations listed in “Part 1”, for example, by making “request object” and “ID token as detached signature” (described later) mandatory. “Part 2” is recommended when higher security than “Part 1” is needed.
2. Part 2: Read and Write API Security Profile
Next, let’s read “Part 2” which is a security profile for read-and-write APIs.
2.1. Detached Signature
“5.1. Introduction” of “Part 2” states that it uses “ID token” as “detached signature”.
An ID token is signed by an authorization server, so even if an attacker tampered the content of the ID token, it could be detected. A client application that has received an ID token can confirm that the ID token has not been tampered by verifying the signature of the ID token.
If an authorization server embeds hash values of response parameters (such as code
and state
) into an ID token, a client application can confirm that the values of the response parameters have not been tampered by computing hash values of the response parameter values and comparing them to the hash values embedded in the ID token. In the context, the ID token is regarded as a detached signature.
For the code
response parameter that represents an authorization code, c_hash
has already been defined in OIDC Core as a claim that represents the hash value of code
. Likewise, at_hash
has been defined as a claim that represents the hash value of access_token
.
What is missing is a claim that represents the hash value of the state
response parameter. So, “5.1. Introduction” defines s_hash
for that purpose.
s_hash
State hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of thestate
value, where the hash algorithm used is the hash algorithm used in thealg
header parameter of the ID Token’s JOSE header. For instance, if thealg
isHS512
, hash the state value with SHA-512, then take the left-most 256 bits and base64url encode them. Thes_hash
value is a case sensitive string.
Because “Part 2” uses ID tokens as detached signatures, even if client applications don’t need ID tokens for the original usage, they have to send authorization requests that require an ID token. To be exact, they have to include id_token
in the response_type
request parameter. This is the reason that the second requirement in “5.2.2. Authorization Server” is saying “shall require the response_type
values code id_token
or code id_token token
”.
However, because of the section, “5.2.5. JWT Secured Authorization Response Mode”, which was newly added by Implementer’s Draft 2, ID tokens don’t have to be used as detached signatures when JARM is used. It is because the entire set of response parameters is packed into a JWT. This is mentioned later again.
2.2. Part 2: Requirements for Authorization Server
“5.2.2. Authorization server” of “Part 2” lists requirements for authorization server.
Part 2: 5.2.2. Authorization server, 1.
shall require the
request
orrequest_uri
parameter to be passed as a JWS signed JWT as in clause 6 of [OIDC];
The request
and request_uri
parameters are defined in “6. Passing Request Parameters as JWTs” of OIDC Core. To use these parameters, the first step is to pack request parameters into a JWT. This JWT is called “request object”. An authorization request (1) passes the request object as the value of the request
parameter directly or (2) puts the request object somewhere accessible from the authorization server and passes the URI pointing to the location as the value of the request_uri
parameter.
Signing a request object is not mandatory in OIDC Core, but signing is mandatory in FAPI Part 2. If request objects are signed, authorization servers can confirm that the request parameters have not been tampered by verifying signatures of the request objects.
To be honest, what surprised me most when I read the FAPI specification for the first time is this requirement. It’s because I knew from my experience it is very hard to implement the request object feature on authorization server side. As the feature is hard to implement and optional in OIDC, there are many authorization server implementations that claim they support OIDC but don’t support request object. Be careful not to choose an authorization server implementation that doesn’t support request object if you want to build a system that supports FAPI Part 2.
Part 2: 5.2.2. Authorization server, 2.
shall require the
response_type
valuescode id_token
orcode id_token token
;
To use ID token as detached signature, even if an ID token is not needed for the original usage, id_token
must be included in the response_type
request parameter.
But, as mentioned in the previous section, id_token
doesn’t have to be included in the response_type
request parameter when JARM is used. “When JARM is used” is, to be concrete, “when the response_mode
request parameter is included and its value is one of query.jwt
, fragment.jwt
, form_post.jwt
and jwt
.
Part 2: 5.2.2. Authorization server, 3.
shall return ID Token as a detached signature to the authorization response;
This requires that an authorization server issue an ID token, but because the previous requirement requires that id_token
be included in response_type
and so an ID token is issued as a general consequence, this requirement doesn’t have to exist. Like the above requirement, an ID token doesn’t have to be issued when JARM is used (unless the client wants an ID token for the original usage).
Part 2: 5.2.2. Authorization server, 4.
shall include state hash,
s_hash
, in the ID Token to protect thestate
value if the client supplied a value forstate
.s_hash
may be omitted from the ID Token returned from the Token Endpoint whens_hash
is present in the ID Token returned from the Authorization Endpoint;
When JARM is used, this requirement doesn’t have to be followed, either.
Part 2: 5.2.2. Authorization server, 5.
shall only issue authorization code, access token, and refresh token that are holder of key bound;
This requirement has a problem.
In the next requirement (Authorization server, 6), MTLS and Token Binding are listed as allowed options for HoK (Holder-of-Key) mechanism. This won’t cause any issue for access tokens and refresh tokens that are issued from a token endpoint. However, This brings up a problem for authorization codes that are issued from an authorization endpoint.
Suppose that MTLS is used as HoK. For this, network communication with an authorization endpoint has to be Mutual TLS. The program that communicates with an authorization endpoint is not a client application but a web browser. As a consequence, network communication between a web browser and an authorization endpoint has to be Mutual TLS. To achieve this, a client certificate needs to be installed into a web browser in advance and the web browser needs to be configured to use the client certificate for communication with the target authorization endpoint.
Part 2, 8.3.2. also states as follows:
When the FAPI client uses [MTLS] or [OAUTB], the authorization code is bound to the TLS channel, any phished client credentials and authorization codes submitted to the token endpoint cannot be used since the authorization code is bound to a particular TLS channel.
Because the specification explicitly states “since the authorization code is bound to a particular TLS channel”, I cannot help interpreting the requirement of Part 2, 5.2.2., 5 in this way.
I found a person who had reached the same interpretation in the group discussing “Consumer Data Right Information Security Profile”.
- ConsumerDataStandardsAustralia Issue 31: Authorisation endpoint should use MTLS
However, if we adopt this interpretation, we have to (1) install a client certificate into a web browser, (2) make the web browser use the client certificate in the mutual TLS connection to an authorization endpoint, and at the same time, (3) make the client application use the same client certificate in the mutual TLS connection to a token endpoint. The thread of “Issue 31” has reached a conclusion that it is impractical.
The tone of the argument in FAPI WG also seems like “it’s not our intention.”
- fapi Issue 202: authorization code and refresh token must be holder of key bound
It seems everyone thinks the requirement of Part 2, 5.2.2., 5. has a problem, so probably this requirement will be amended in future.
Part 2: 5.2.2. Authorization server, 6.
shall support [OAUTB] or [MTLS] as a holder of key mechanism;
Token Binding and MTLS can be applied to access tokens and refresh tokens. However, regarding authorization codes, there is the same concern as mentioned above. In “fapi Issue 202”, I suggested that the spec state like “PKCE shall be used as HoK mechanism for authorization codes while MTLS or OAUTB shall be used as HoK mechanism for access tokens and refresh tokens” to solve confusion, inconsistency and contradiction, but it is unclear where the discussion will go.
Part 2: 5.2.2. Authorization server, 7.
shall support user authentication at LoA 3 or greater as defined in [X.1254];
FAPI Part 2 requires LoA 3 or higher for user authentication while FAPI Part 1 requires LoA 2 or higher. The following is the definition of LoA 3 excerpted from “6.3 Level of assurance 3 (LoA3)” of X.1254.
At LoA3, there is high confidence in the claimed or asserted identity of the entity. This LoA is used where substantial risk is associated with erroneous authentication. This LoA shall employ multifactor authentication. Any secret information exchanged in authentication protocols shall be cryptographically protected in transit and at rest (although LoA3 does not require the use of a cryptographic-based challenge-response protocol). There are no requirements concerning the generation or storage of credentials; they may be stored or generated in general purpose computers or in special purpose hardware.
For example, a transaction in which a company submits certain confidential information electronically to a government agency may require an LoA3 authentication transaction. Improper disclosure could result in a substantial risk for financial loss. Other LoA3 transaction examples include online access to accounts that allow the entity to perform certain financial transactions, or use by a third party contractor of a remote system to access potentially sensitive client personal information.
Part 2: 5.2.2. Authorization server, 8.
shall support signed ID Tokens;
Because “2. ID Token” of OIDC Core says “ID Tokens MUST be signed”, it is ensured that every ID token is signed. Therefore, this requirement is not necessary.
Part 2: 5.2.2. Authorization server, 9.
should support signed and encrypted ID Token;
Encryption of ID tokens is mentioned in OIDC Core, too. Because this requirement uses “should” instead of “shall”, encryption support is not mandatory.
Part 2: 5.2.2. Authorization server, 10.
shall require that all parameters are present inside the signed request object passed in the
request
orrequest_uri
parameter;
Actually, OIDC Core does not require that request objects be signed. Because of this requirement, it becomes mandatory to sign request objects to comply with FAPI Part 2.
In addition, it should be noted that a request object must include all request parameters to comply with FAPI Part 2. In OIDC Core, request parameters can be put inside or outside a request object. It is also allowed to put the same request parameters both inside and outside.
Part 2: 5.2.2. Authorization server, 11.
may support the request object endpoint as described in section 7;
“7. Request object endpoint” of “Part 2” defines a new endpoint called “request object endpoint”. Request objects can be registered at the endpoint and the endpoint issues unique URIs which point to the registered request objects. Client applications can use the URIs as a value of the request_uri
request parameter.
Part 2: 5.2.2. Authorization server, 12.
shall require [RFC7636] with
S256
as the code challenge method for public clients only, if it supports public clients;
That is, public clients must include code_challenge_method=S256
in authorization requests.
Part 2: 5.2.2. Authorization server, 13.
shall require the request object to contain an
exp
claim; and
OIDC Core does not require that request objects include the exp
claim. In contrast, FAPI Part 2 requires exp
as a mandatory claim.
Part 2: 5.2.2. Authorization server, 14.
shall authenticate the confidential client at the token endpoint using one of the following methods (this overrides FAPI part 1 clause 5.2.2.4):
1. Mutual TLS for OAuth Client Authentication as specified in section 2 of [MTLS];
2.
private_key_jwt
as specified in section 9 of [OIDC];
It should be noted that client_secret_jwt
is not allowed in Part 2. This is different from Part 1.
2.3. Part 2: Requirements for Public Client
“5.2.3. Public client” of “Part 2” lists requirements for public clients. The requirements are positioned as additions to the requirements listed in “Part 1”.
Part 2: 5.2.3. Public client, 1.
shall support [OAUTB] or [MTLS] as a holder of key mechanism; Note: [MTLS] shall be used with instance-specific keys and (self-signed) certificates to bind access tokens to the particular instance of a public client. It is NOT used as client authentication mechanisms.
Before reading this sentence, it is necessary to understand the difference between using a client certificate for client authentication (MTLS, 2. Mutual TLS for OAuth Client Authentication) and using a client certificate for HoK (MTLS, 3. Mutual TLS Client Certificate-Bound Access Tokens).
Part 2: 5.2.3. Public client, 2.
shall include the
request
orrequest_uri
parameter as defined in Section 6 of [OIDC] in the authentication request;
As listed in the list of requirements for authorization server, either the request
parameter or the request_uri
parameter must be included. Note that OIDC Core says “If one of these parameters is used, the other MUST NOT be used in the same request.”
Part 2: 5.2.3. Public client, 3.
shall request user authentication at LoA 3 or greater by requesting the
acr
claim as an essential claim as defined in section 5.5.1.1 of [OIDC];
When a client wants to require claims as essential ones, the acr_values
request parameter cannot be used. Instead, a client must use the claims
request parameter, pass JSON as its value, and include {“essential":true}
inside the JSON. The following is an example of JSON that needs to be given as the value of the claims
request parameter in order to mark urn:mace:incommon:iap:silver
as an essential ACR.
BTW, this requirement is loosened in UK Open Banking which is based on FAPI Part 2. That is, clients don’t have to require ACRs as essential. Probably, it is not intentional. I guess that the snapshot of FAPI specification which was referred to when Open Banking Profile (OBP) was developed didn’t contain the sentence, “by requesting the acr
claim as an essential claim”.
The official Financial-grade API conformance test suite (fapi-conformance-suite) developed and maintained by FinTechLabs.io contains test cases for OBP. When FinTechLabs ran the OBP test cases using Authlete to test the test suite itself, they encountered an error. Because Authlete strictly follows FAPI specification, Authlete reported “acr
claim is not required as essential.” However, the expected behavior in the context of OBP is to ignore the FAPI requirement.
The right approach for the error was to amend OBP (to make OBP compliant with the latest FAPI specification). However, I was given explanation like “if the official conformance test suite did it, all the existing OBP implementations wouldn’t be able to pass the official tests. Changing the tests at this timing might cause delay in the officially-announced schedule of Open Banking.”
Therefore, I decided to tweak Authlete and added OPEN_BANKING option in addition to FAPI option.
If OPEN_BANKING is enabled, Authlete dare not to check if the acr
claim is required as essential even in the context of FAPI Part 2. The code snippet below is the actual implementation excerpted from Authlete’s source code.
As a result of this, Authlete is listed as a platform vendor that has passed “Open Banking Security Profile Conformance”.
Part 2: 5.2.3. Public client, 4.
shall require JWS signed ID Token be returned from endpoints;
Part 2: 5.2.3. Public client, 5.
shall verify that the
acr
claim in an ID Token indicates that user authentication was performed at LoA3 or greater;Part 2: 5.2.3. Public client, 6.
shall verify that the
amr
claim in an ID Token contains values appropriate for the LoA indicated by theacr
claim;Part 2: 5.2.3. Public client, 7.
shall verify that the authorization response was not tampered using ID Token as the detached signature
This requirement is not explicitly mentioned in “5.2.5. JWT Secured Authorization Response Mode”, but it can be logically deduced that this requirement doesn’t have to apply when JARM is used.
Part 2: 5.2.3. Public client, 8.
shall send all parameters inside the authorization request’s signed request object
Part 2: 5.2.3. Public client, 9.
shall additionally send duplicates of the parameters/values using the OAuth 2.0 request syntax where required by the OAuth specification
If request parameters are all put into a request object, either the request
parameter or the request_uri
parameter is enough. However, if parameters that are mandatory in OAuth 2.0 / OIDC Core (e.g. client_id
and response_type
) are omitted, the request is no longer compliant with OAuth 2.0 / OIDC Core. Therefore, parameters that are mandatory in OAuth 2.0 / OIDC Core must be put outside the request object duplicately even if they exist inside the request object.
In addition to the above requirements from 1. to 9., section 5.2.3. has a sentence at the end. The sentence says as follows:
To verify that the authorization response was not tampered using ID Token as the detached signature, the client shall verify that
s_hash
value is equal to the value calculated from thestate
value in the authorization response in addition to all the requirements in 3.3.2.12 of [OIDC].
No. 10 should be assigned to this sentence. I created “fapi Issue 210” to suggest it.
2.4. Part 2: Requirements for Confidential Client
“5.2.4. Confidential client” of “Part 2” lists requirements for confidential clients. In addition to the requirements listed in 5.2.3. except ones related to PKCE, confidential clients must follow the requirements below to become compliant with FAPI Part 2.
Part 2: 5.2.4. Confidential client, 1.
shall support [OAUTB] or [MTLS] as a holder of key mechanism (this overrides clause 5.2.3.1); Note: In case of confidential clients, [MTLS] can also be used as client authentication mechanism.
Part 2: 5.2.4. Confidential client, 2.
should require both JWS signed and JWE encrypted ID Tokens to be returned from endpoints to protect any sensitive personally identifiable information (PII) contained in the ID Token provided as a detached signature in the authorization response
The feature of ID token encryption has existed since OIDC Core. When the encryption algorithm for ID tokens is an asymmetric one, the authorization server must either (1) manage public keys of client applications directly in its database or (2) fetch JWK Set documents from the locations pointed to by clients’ jwks_uri
metadata and extract public keys from the documents.
For signing ID tokens, it is server-side keys only that an authorization server has to handle.
In contrast, if an authorization wants to support encryption of ID tokens, the authorization server has to handle client-side keys, too.
This is the reason that not a small number of authorization server implementations don’t support ID token encryption.
2.5. Part 2: JARM
“5.2.5. JWT Secured Authorization Response Mode” of “Part 2” is a section about JARM which has been newly added by Implementer’s Draft 2.
If JARM is used (if one of query.jwt
, fragment.jwt
, form_post.jwt
and jwt
is used as the value of the response_mode
request parameter), response parameters are packed into a JWT and the JWT is returned as the value of the response
response parameter. Because the JWT is signed by a key of the server, a client can confirm that the response has not been tampered by verifying the signature of the JWT.
In the first version of Implementer’s Draft, “ID token as detached signature” is the only method to detect response tampering. Implementer’s Draft 2 has added JARM as another method. Therefore, section 5.2.5. states as follows:
If [JARM] is used to secure the authorization responses, the clauses 2, 3, and 4 of section 5.2.2. do not apply. For example, clients may use [JARM] in conjunction with the response type
code
.
In addition to the clauses through 5.2.2.2 to 4., apparently some others also don’t have to apply when JARM is used. For example, the clause of 5.2.3. Public client, 7. which says “shall verify that the authorization response was not tampered using ID Token as the detached signature.” The specification will be amended so that it can be more consistent.
2.5.1. Client Metadata for JARM
Client applications have to set a value to the authorization_signed_response_alg
metadata in advance before using JARM. The metadata represents an algorithm for signature of response JWTs. If the value of the response_mode
request parameter is *.jwt
although the metadata is not set, the authorization request fails because the specification requires response JWTs be always signed.
To encrypt response JWTs, algorithms have to be set in advance to the authorization_encrypted_response_alg
metadata and the authorization_encrypted_response_enc
metadata. To use an asymmetric algorithm, configuration about client’s public key is necessary, too.
The screenshot below is client-side settings for JARM in Authlete’s web console that is provided for client management.
2.5.2. Server Metadata for JARM
Discovery information of authorization servers that support JARM includes one or more of query.jwt
, fragment.jwt
, form_post.jwt
and jwt
in the list of supported response modes (response_modes_supported
). Also, discovery information includes the following metadata related to algorithms used for response JWTs.
authorization_signing_alg_values_supported
— supported algorithms for signing
authorization_encryption_alg_values_supported
— supported algorithms for key encryption
authorization_encryption_enc_values_supported
— supported algorithms for payload encryption
Discovery information of authorization servers that support JARM completely will include data as shown below.
2.6. Part 2: Request Object Endpoint
When a request object is used in an authorization request, it is passed by value using the request
request parameter (OIDC Core, 6.1) or passed by reference using the request_uri
request parameter (OIDC Core, 6.2).
To use request_uri
, a client application developer prepares a server and puts request objects there. There is an idea to make an authorization server itself host such request objects.
“7. Request object endpoint” of “Part 2” defines a new endpoint called “request object endpoint”. It is an endpoint at which client application developers register request objects. After accepting registration of a request object, the endpoint stores it somewhere in the authorization server, issues a URI that can identify the request object, and returns a JSON that contains the URI.
The following are examples of a request and a response listed in “7.2. Request” and “7.3. Successful response”. Pay attention to the request_uri
claim in the response.
Discovery information of authorization servers that support Request Object Endpoint includes metadata named request_object_endpoint
.
2.7. Part 2: Security Considerations
“8. Security considerations” of “Part 2” lists security considerations. Summary is as follows.
8.1 — This specification references security considerations in section 10 of RFC 6749 and RFC 6819.
8.2 — Protected resource endpoints shall accept only certificate-bound or token-bound access tokens.
8.3.1 — Clients should use a different redirect URI per authorization server.
8.3.2 — Authorization codes and client secrets are passed to attackers if developers are deceived into using a fake token endpoint.
Section 8.3.2 includes the following sentence.
When the FAPI client uses [MTLS] or [OAUTB], the authorization code is bound to the TLS channel, any phished client credentials and authorization codes submitted to the token endpoint cannot be used since the authorization code is bound to a particular TLS channel.
As discussed for Part2–5.2.2–5, this sentence has a problem and will be amended in future.
8.3.3 — Hybrid flow can be used as a countermeasure for IdP mix-up attack.
8.3.4 — Requests objects containing confidential information are passed to attackers if developers are deceived into using a fake request object endpoint.
8.3.5 — Because access tokens are bound to TLS channels in FAPI Part 2, attackers cannot use stolen access tokens.
8.4.1 — RFC 6749 doesn’t assure message integrity of authorization request and response.
8.4.2 — Using request objects prevents authorization request parameter injection attack.
8.4.3 — Using hybrid flow prevents authorization response parameter injection attack.
2.8. Part 2: TLS Considerations
“8.5. TLS considerations” of “Part 2” permits only the following cipher suites for TLS communication.
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
But, from a viewpoint of interoperability of web browsers, additional cipher suites allowed in the latest BCP 195 are permitted for authorization endpoints.
Well, because I couldn’t find any good reasons to exclude the following cipher suites,
5. TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
6.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
I created Issue 216 (TLS_ECDHE_ECDSA cipher suites) to suggest adding them to the list of permitted cipher suites.
2.9. Part 2: JWS Algorithm Considerations
Signing algorithms of JWS are listed in “3.1. “alg” (Algorithm) Header Parameter Values for JWS” of RFC 7518 (JSON Web Algorithms). Among the 13 algorithms, “8.6. JWS algorithm considerations” of “Part 2” permits PS256
and ES256
only. The section explicitly states that RSASSA-PKCS1-v1_5 (e.g. RS256
) should not be used and none
must not be used.
JWT is used at the following places in an authorization server implementation.
Personally, I think there is room for discussion as to whether the JWT algorithm restriction applies to UserInfo response. However, apparently, client_assertion
, ID token, request object and authorization response are affected by the restriction.
Regarding backchannel authentication request, we have to watch discussion about “CIBA FAPI profile” in MODRNA Working Group.
3. FAPI implementation
This chapter picks up some topics related to FAPI implementation.
3.1. Read-Only or Read-and-Write?
For authorization requests and token requests to get an access token to access read-only APIs and for the APIs themselves hosted on resource servers, FAPI Part 1: Read-Only API Security Profile applies.
Likewise, for authorization requests and token requests to get an access token to access read-and-write APIs and for the APIs themselves hosted on resource servers, FAPI Part 2: Read and Write API Security Profile applies.
APIs hosted on resource servers know whether they themselves are read-only APIs or read-and-write APIs. Therefore, it is apparent for the API implementations which security profile they should follow.
On the other hand, how does the authorization endpoint of an authorization server judge whether an incoming request is for read-only APIs or for read-and-write APIs, or for APIs irrelevant to FAPI?
Actually, FAPI specification mentions nothing about how to judge.
A simple solution would be “Regard all authorization requests as ones for read-and-write APIs.” Actually, UK Open Banking has adopted this approach. A hard-coded implementation like this may be acceptable if the system development is a one-time work.
However, this approach is not appropriate for a generic authorization server implementation. It’s because a hard-coded implementation hinders flexibility of system design too much. Therefore, in a generic implementation, it is better to judge dynamically at runtime whether an authorization request is for FAPI read-only or for FAPI read-and-write (or for normal OAuth 2.0 / OIDC).
If so, how to judge dynamically? The conclusion everyone will eventually reach after thinking will be just one. It is judged by checking the requested scopes.
(Note: Another possible way would be to utilize the resource
request parameter defined in “Resource Indicators for OAuth 2.0”, but I’m not sure whether the specification can gain strong support from the community.)
For example, (1) prepare scopes named read
and write
, (2) adopt a rule which requires the read
scope for read-only APIs and the write
scope for read-and-write APIs, and (3) implement APIs so. If APIs are implemented in this way, the implementation of an authorization endpoint can change its behavior dynamically by (a) applying FAPI Part 2 requirements when the scope
request parameter includes the write
scope, (b) applying FAPI Part 1 requirements when the scope
request parameter does not include the write
scope but includes the read
scope, and (c) applying normal OAuth 2.0 and OIDC requirements when the scope
request parameter includes neither the read
scope nor the write
scope.
How to implement the scope-based switch? For example, regard scopes whose name starts with read
as scopes for read-only APIs? However, this approach imposes heavy restrictions on scope names. So, what is the approach Authlete has adopted?
First, Authlete implemented a generic mechanism to set arbitrary attributes to each scope. On the mechanism, Authlete treats the attribute name fapi
in a special way. An attribute having name fapi
and value r
represents Read-Only. Likewise, an attribute having name fapi
and value rw
represents Read-and-Write.
The web console for FAPI-aware Authlete (version 2.0+) provides UI for scope attributes. The screenshot below defines a scope named read
with an attribute of fapi=r
.
/api/auth/authorization
, an Authlete API that parses an authorization request, checks scopes listed in the scope
request parameter in the authorization request and regards the request as a request for FAPI Read-and-Write APIs if the scope list includes a scope that has an attribute of fapi=rw
. If the scope list does not include any scope having an attribute of fapi=rw
but includes a scope having an attribute of fapi=r
, the authorization request is regarded as a request for FAPI Read-Only APIs. In other cases, the authorization request is treated as a normal OAuth 2.0 / OIDC request.
3.2. Mutual TLS
“Mutual TLS” has three meanings as listed below (as already explained previously).
- TLS communication using a client certificate
- Client authentication using a client certificate
- Certificate binding
The first part is handled by API management solutions. On the other hand, the second and the third parts don’t necessarily have to be handled by API management layer. Rather, a better system architecture would build them as systems independent from each other.
Because of its unique architecture, Authlete doesn’t take on any task in API management layer. That is, Authlete does nothing for the first part. On the other hand, Authlete supports the second and the third parts. Thanks to this, with Authlete, systems can support MTLS (OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens) required by FAPI on any API management solution that developers want to use. Actually, it has already been confirmed that MTLS can be supported on Azure API Management and Apigee with Authlete. I’ve not tried AWS API Gateway yet, but any API management solution can support MTLS by using Authlete as long as it provides a mechanism which enables developers to access the client certificate used in TLS communication.
I’m afraid it would take time for existing API management solutions to implement MTLS directly. Above all, it is not a good system design to support the functionality directly in API management layer. At the time of this writing, if you use an API management solution provided by one of giant cloud vendors, Authlete is the best answer to support Financial-grade API.
The video below is a session in “Financial APIs Workshop” that took place in Tokyo on July 24, 2018. In the video, Justin Richer, one of the most famous software engineers in the community and the author of “OAuth 2 in Action”, is explaining Authlete’s MTLS implementation.
The presentation material used in the session is available here on SlideShare.
3.3. Access Token Duration
This is not related to FAPI, but I explain this feature here because I’m often consulted about the feature in the context of Bank API by customers who want to make duration of access tokens for remittance shorter than that of access tokens for other purposes.
The functionality can be achieved by making access token duration shorter when an authorization request contains a scope for remittance. For example, if an API for remittance requires a scope named remit
, the authorization server would shorten access token duration when an authorization request contains the scope.
Authlete supports the functionality by treating a scope attribute named access_token.duration
in a special way.
Authlete checks all scope attributes of requested scopes, picks up the smallest value among values of access_token.duration
attributes, and uses it as the duration of an access token being issued. If none of the requested scopes has an access_token.duration
attribute, Authlete uses the default value of access token duration set per authorization server instance. If the default value is smaller than the smallest value of access_token.duration
attributes, the default value is used.
For example, definition of remit
scope setting 300 seconds to access token duration is as follows.
Likewise, duration of refresh tokens can be set by utilizing refresh_token.duration
attributes.
3.4. Access Token with Transaction Information
This feature is not related to FAPI, either, but I explain it here as I’m often consulted about it in the context of Bank API by customers who want to associate detailed transaction information with an access token. I hear that some regulations in Europe require an access token be issued per transaction under some conditions.
This functionality cannot be achieved by “scope attribute” explained in “3.3. Access Token Duration”. Handling data per access token is required instead of data per scope.
Since old days, Authlete has provided a mechanism to set arbitrary key-value pairs to an access token. This feature can be utilized to associate transaction information with an access token. Technical details about this feature are explained in “Extra Properties”.
However, note that it is not a smart way to associate detailed information such as amount of money with an access token directly. Instead, a recommended way is to (1) store detailed transaction information into another database and (2) associate the unique identifier of the database record with an access token.
Finally
Thank you for reading this long post till the end.
I’ll give a talk titled “Financial-grade API (FAPI) and CIBA” in DeveloperWeek New York 2019 on June 20. Authlete, Inc. will have a booth at the event. Please come to the event and visit our booth.
Again, please contact Authlete, Inc. (sales@authlete.com) if you are interested in the world’s first certified implementation of Financial-grade API OpenID Provider.
About the Author
Takahiko Kawasaki is co-founder and representative director of OpenID Foundation member, Authlete, Inc.