3. Token Exchange
Note that the testing environment for the FAPI 2.0 Authentication API is not yet ready. It will be ready in December 2025. If you are integrating now, please refer to Singpass Authentication API instead.
Token exchange refers to the process of making a POST request to the token endpoint to exchange the authorization code (obtained from the redirect URL in the previous step) with an ID token and access token.
The token endpoint is defined in the token_endpoint
field located in our authorization server's OpenID Configuration.
Request Body
You should send the request body in application/x-www-form-urlencoded
format. The DPoP header containing the DPoP JWT proof should also be included in your request.
The request body should have the following parameters:
client_id
The client ID of your registered client, provided by Singpass during app onboarding. It is the App ID found at the top of your app configuration page.
A 32-character case-sensitive alphanumeric string.
redirect_uri
The redirect_uri
which you had used earlier when making the Authorization request.
URL
grant_type
The grant being requested.
Must be the string authorization_code
, as mandated by OIDC specifications.
code
The authorization code issued by us, obtained via redirection back to your redirect_url
in the previous step.
A base64url-encoded string.
client_assertion_type
The type of client assertion.
Must be the string urn:ietf:params:oauth:client-assertion-type:jwt-bearer
, as mandated by OIDC specifications.
client_assertion
Your client assertion, which is used for authentication. Refer to our guide for instructions on how this should be generated.
A string containing the signed JWT.
code_verifier
The code verifier which you have generated when constructing your authorization request. This is used as part of PKCE.
String containing only alphanumeric characters, dashes, and underscores, between 43-128 characters long.
Response Body
Successful Response
If the request was successful. we will return a response in application/json
format which includes the following parameters:
access_token
For Login applications, this is a random string which should not be used. For Myinfo (v5) applications, this is an encoded JWT that can be used to obtain user information using the UserInfo endpoint. This access token has a lifetime of 30 minutes.
String
id_token
The encrypted ID token in JWT format, signed by us. More information on how to parse this ID token is available in the next page.
String
token_type
The type of token being requested.
This will always be DPoP
, as mandated by FAPI 2.0 specifications.
Error Response
If there was an error with the request, we will instead return a response body in application/json
format with the following parameters:
error
An error code identifying the type of error that has occurred.
This will be an enum value. The possible values are detailed below.
error_description
A human-readable text description of the error.
String. This is optional.
error_uri
URI of a web page that includes additional information about the error
URL. This is optional.
Possible error values
The table below lists the possible values of error
that we may return:
invalid_request
The request had missing or invalid parameters. You should ensure that all the parameters follow the specifications listed above. This error will also be returned if you did not send the DPoP
header in your request.
unsupported_grant_type
This means that you had passed a grant_type
value which is not the value authorization_code
. You should update your implementation to send grant_type
as authorization_code
.
invalid_grant
This means that the authorization code has expired. You should ensure that token exchange happens within 60 seconds of the authorization code being issued.
invalid_client
This can be caused by a few possible issues:
The
client_assertion
that you generated was invalid. Read our guide on client assertions and ensure that your implementation follows the guide. The method to generate the client assertion should be the same as the one used to generate the client assertion for the Pushed Authorization Request.The
redirect_uri
provided is different from the one which you have sent in the Pushed Authorization RequestThe
client_id
provided is invalid
invalid_dpop_proof
The DPoP
header which you have provided is invalid, expired, or malformed. Read our DPoP guide and ensure that your implementation follows the instructions in the guide.
server_error
The server encountered an unexpected error. You should check error_description
to understand what was the cause of the error.
This error can potentially be caused by your JWKS endpoint not being reachable. Read our guide on JWKS and ensure that you follow the requirements. In particular, your JWKS endpoint must be publicly accessible and should respond in a timely manner.
If the cause was not your JWKS endpoint, you may perform up to 3 retries using an exponential backoff strategy. If the request still fails, you should guide users to alternative authentication methods.
temporarily_unavailable
The server is temporarily unavailable to handle the request. You may perform up to 3 retries using an exponential backoff strategy. If the request still fails, you should guide users to alternative authentication methods, or to guide them to try again some time later.
Last updated
Was this helpful?