Changelog

The list of changes from the existing Authentication API

Overview

The FAPI 2.0 Security Profile builds on top of the existing OIDC specifications. Singpass is already OIDC-compliant, which means that you will not need to update your entire existing integration - you will only need to update some parts of the integration.

The following diagram provides an overview of the parts of the Singpass flow that we are changing. The changed parts are highlighted in red. For ease of comparison, the same diagram, but for the existing flow (i.e. without changes), can be found at https://docs.developer.singpass.gov.sg/docs/technical-specifications/singpass-authentication-api/overview-of-singpass-flow.

You may also view an interactive version of this diagram in this page.

Pushed Authorization Requests

Relevant steps in sequence diagram: steps 4-7

Previously, you would have performed the authorization request by redirecting users to an authorization URL containing all the authorization request parameters (such as redirect_uri, client_id, scopes ) in its query parameters.

We will now instead require pushed authorization requests (as specified in RFC 9126) to be performed during the authentication flow. This was done for improved security, as using pushed authorization requests will prevent tampering of the authorization request parameters in the authorization URL.

You may also read this blog post to understand more about pushed authorization requests.

Switching to pushed authorization requests requires you to make two changes:

  1. Before redirecting the user to the authorization URL, you must first make a POST request to the pushed_authorization_request_endpoint (which is published in the authorization server metadata) with a request body containing all the authorization request parameters. This is represented by steps 4-5 in the sequence diagram.

  2. When you redirect the user to the authorization URL, the query parameters of the URL should only contain request_uri (returned from the pushed authorization request) and your client_id .

New Parameters for Authorization Requests

Relevant step in sequence diagram: step 4

We now support some new parameters for authorization requests. These parameters are:

  • acr_values

  • transaction_category

  • auth_context_message

These new parameters, which you will pass in the pushed authorization request, will provide you greater control over what your users will experience during the authentication process. Full details of these parameters can be found in this page.

Demonstrating Proof-of-Possession (DPoP)

Relevant steps in sequence diagram: steps 5, 17, and 22

A DPoP proof (as specified in RFC 9449) is now required for the following requests:

  • The pushed authorization request

  • The token request

  • The userinfo request

This was introduced in order to ensure that both the authorization code and the access token (issued on steps 10-13 and 19 respectively in the sequence diagram) can only be used by you and not by any other party.

You may read more about DPoP in this article.

ID Token Encryption and Format

Relevant steps in sequence diagram: steps 20-21

The ID token will now always be encrypted using JSON Web Encryption (JWE), regardless of the client profile of your app. Previously, the ID token was only encrypted if you had requested for NRIC to be returned in the ID token. Note that this will now require you to add an encryption key into your JWKS, if you do not already have one.

Additionally, the format of the claims returned in the ID token is also different. A summary of the changes are:

  • The sub claim will now only contain the UUID of the user. Previously, it contained key-value pairs containing different values depending on your app's client profile and the type of user, but we have now simplified the claim to just always be the UUID.

  • If you require NRIC (for SC/PR), FIN (for pass holders) or the foreign ID (for SFA users) to be returned in the ID token, you may request for the new sub_account scope. If the scope is requested, then this information will be returned in the new sub_account claim in the ID token.

Here are some examples to illustrate the difference:

ID token differences

Note: for brevity, the examples here do not contain the whole ID token - they only contain the parts that have changed.

Note also that sub_account in the new ID token will only be returned if requested as part of the scopes in the authorisation request.

User type
Old ID token
New ID token

Singapore Citizen / PR

{
  "sub": "s=S8829314B,u=1c0cee38-3a8f-4f8a-83bc-7a0e4c59d6a9"
}
{
  "sub": "1c0cee38-3a8f-4f8a-83bc-7a0e4c59d6a9",
  "sub_account": {
    "account_type": "SC/PR",
    "uinfin": "S8829314B"
  }
}

FIN holders

{
  "sub": "s=G4542206U,u=1c0cee38-3a8f-4f8a-83bc-7a0e4c59d6a9"
}
{
  "sub": "1c0cee38-3a8f-4f8a-83bc-7a0e4c59d6a9",
  "sub_account": {
    // note: there are several different possible account types for FIN holders - FIN-EP is just one of them
    "account_type": "FIN-EP",
    "uinfin": "G4542206U"
  }
}

Singapore Foreign Account

{
  "sub": "s=Y7613265T,fid=G730Z-H5P96,coi=DE,u=e2af740e-25b4-4b19-b527-494670952cb0"
}
{
  "sub": "e2af740e-25b4-4b19-b527-494670952cb0",
  "sub_account": {
    "account_type": "SFA",
    "foreign_id": "G730Z-H5P96",
    "foreign_id_coi": "DE"
  }
}

For full details on the new format, you may refer to ID token specs.

Userinfo Response Format

Relevant step in sequence diagram: step 26

The userinfo response will have a slightly different format. The format of the data itself remains unchanged - the only difference is that the data is now nested inside a person_info field.

The userinfo response will remain encrypted using JWE - no changes will be made on how it is encrypted.

Here's an example to illustrate the difference:

Userinfo payload difference
Old response
New response
{
  "uinfin": {
    "lastupdated": "2024-09-26",
    "source": "1",
    "classification": "C",
    "value": "S9000001B"
  },
  "name": {
    "lastupdated": "2024-09-26",
    "source": "1",
    "classification": "C",
    "value": "SOH HAO FENG"
  },
  "iss": "https://stg-id.singpass.gov.sg",
  "sub": "s=S9000001B,u=d45d8f21-6178-4713-b962-8635ed2a945a",
  "aud": "tWT3rfImn9hCezlLr0M1nRUvQ40fCNL4",
  "iat": 1746678089
}
{
  "person_info": {
    "uinfin": {
      "lastupdated": "2024-09-26",
      "source": "1",
      "classification": "C",
      "value": "S9000001B"
    },
    "name": {
      "lastupdated": "2024-09-26",
      "source": "1",
      "classification": "C",
      "value": "SOH HAO FENG"
    },
    "iss": "https://stg-id.singpass.gov.sg",
    "sub": "s=S9000001B,u=d45d8f21-6178-4713-b962-8635ed2a945a",
    "aud": "tWT3rfImn9hCezlLr0M1nRUvQ40fCNL4",
    "iat": 1746678089
  }
}

Enforcement of Proof of Key Code Exchange (PKCE)

We will be enforcing PKCE (specified in RFC 7636) for all integrations with the new authentication API. This is a requirement for FAPI 2.0 compliance, and will help to protect you against misuse of the authorization code.

Removal Of Support For Custom Scheme URLs

Previously, custom scheme URLs (i.e. URLs that do not use the https:// scheme) were allowed to be registered as redirect URLs and app launch URLs. This was done to support redirection to mobile apps.

We will be dropping support for the usage of such URLs with the new specifications. If you are currently using custom scheme URLs for mobile app redirection, you are required to instead use App-claimed https URLs (Universal Links for iOS, and App Links for Android) for this purpose instead. This is being done to ensure that redirects from Singpass cannot be intercepted by malicious applications.

Authentication Error Responses

Currently, we do not always redirect back to your redirect URL when an error occurs. This will change with the new authentication API. Where possible, we will now be redirecting back to your redirect URL with an Authentication Error Response, which is specified in section 3.1.2.6 of the OpenID specifications.

With this change, you will get more information about what are the errors that users face while authenticating with Singpass, and can handle the error flows appropriately. However, this also means that you must ensure that you have proper error handling in place for these errors.

The full list of possible error responses will be provided in the final version of this specification.

Last updated

Was this helpful?