Sign with Singpass
Singpass Developer DocsAsk a Question
  • START HERE
    • Overview of Sign
    • How do our Digital Signatures work?
    • Frequently Asked Questions
  • FOR USERS
    • How to sign
    • Verifying Sign with Singpass Signatures
      • Loading Singpass Root Signing Certificate
  • FOR RELYING PARTIES
    • Use Cases
    • Getting Started
      • How to Onboard our API
      • Digital Signing Partners
        • Docusign
        • Tungsten Automation
        • OneSpan
        • Tessaract Technologies Pte Ltd
        • Netrust Pte Ltd
        • Modus Consulting
        • Redoc.co by Real Estate Doc Pte Ltd.
        • CrimsonLogic
        • Zoho Sign
        • Securemetric Technology Pte. Ltd.
        • Rently Pte. Ltd.
    • API Documentation
      • Document Signing V3
        • Initiate Sign Request
        • Redirect From Sign with Singpass
        • Accept Success Signing Webhook
        • Get Signing Result
        • JWKS Specification
        • Sign Portal
      • Document Signing V1
      • Transaction Signing
        • Embedding Singpass JS
        • Init Transaction Signing
        • Exchange Transaction Signature
    • UX Guidelines
      • User Journey Illustration
    • Support
Powered by GitBook
On this page
  • Following up after redirection
  • Method Parameters
  • Returns
  • Structure of txnInfo JWT
  • .cancelTxnSigningSession()

Was this helpful?

  1. FOR RELYING PARTIES
  2. API Documentation
  3. Transaction Signing

Init Transaction Signing

RPs should invoke this function to start a transaction signing session with Singpass. This is the only function that needs to be invoked by the RP for every transaction signing session.

initTxnSigning(DOMElementID, clientParams, transactionParamsSupplier, onError, additionalOptions)

Behind the scenes, Singpass JS will coordinate the required backend API calls to create a new session and renders the UI screens accordingly as users progress through the signing process.

Firstly, Singpass JS will perform pre-flight checks to validate the function method parameters and ensure that the end-user’s browser/user-agent is supported by Singpass JS.

Next, Singpass JS will call the /txn-signing-sessions endpoint that is exposed on the Singpass backend to initiate the transaction signing flow.

Upon successful invocation of this function and the session initiation by Singpass, a QR code will be generated and displayed for the user to scan with the Singpass app (SPM) and proceed with the transaction.

At the same time, Singpass JS will call the /status endpoint, which is a long-polling connection to the Singpass backend. This endpoint reacts to user actions in the SPM app, i.e. "user scanned" and "user authorised".

Wrap the invocation of initTxnSigning in a try-catch block, in case of any unforeseen errors. RPs can choose to default to an alternate authorisation mechanism in such error cases.

Following up after redirection

Once the user has successfully scanned and authorised the transaction using SPM, Singpass JS will redirect the end-user’s browser/user-agent to the RP’s registered redirect_uri along with the code and state parameters.

Once redirected, the RP’s backend should invoke the /txn-signatures endpoint to retrieve the user’s transaction hash signature and complete the transaction signing flow.

Sample redirect location upon successful transaction signing

https://partner.txnsign.gov.sg/redirect?code=v2-BYE9fSQpDXCM0tlcI0yHwkwiff3bNy09n%2F703h4rmZI%3D&state=ewoidXNlciI6ImEiLAoic2Vzc2lvbiI6IjEyMyIsCiJyYW5kb20iOiJ4eXoiCn0=

Method Parameters

DOMElementID string

Represents the unique ID of the Document Object Model (DOM) Element where Singpass JS will render the transaction signing UI elements (QR code, text, images) on.

The DOM element should be empty; Singpass JS will clear it before rendering any UI assets.

See UI dimensions for the minimum size required of this element.

clientParams object: { clientId, redirectUri }

  • clientId string

    The client identifier that was assigned by Singpass during RP registration.

  • redirectUri string

    The URL that Singpass JS will eventually redirect the user to after the user completes the signing process using SPM. This value will be validated against the RP’s redirect_uri that was specified during RP registration.


transactionParamsSupplier function: () ⇒ object: {state, nonce, txnInfo}

This function will be invoked by Singpass to retrieve the necessary session parameters from the RP’s backend everytime a new sign session is to be initialised.

Singpass JS may invoke this function multiple times (eg. when the user clicks on the Singpass-rendered retry button to re-initialise another session due to an unforeseen error or session expiry). RPs should ensure that a new set of values (txnInfo, state, nonce) is returned on each invocation as these values are expected to be session-based.

RPs should ensure that they perform automated retries on any network calls made during this function invocation because Singpass JS will not retry on any failures arising from this function invocation.

This function can either be an async function OR a standard function that returns a Promise object that resolves to an object containing the following structure:

  • state string

    A session-based, unique, and non-guessable value that RP’s backend should generate per transaction signing session.

    As part of threat modelling, Singpass JS requests for the state parameter to mitigate replay attacks against the RP’s redirect uri. This parameter serves the same purpose as the OAuth 2.0’s state parameter.

    It should have a maximum of 255 characters and must match regexp pattern of [A-Za-z0-9/_\-=.].

  • nonce string

    A session-based, unique, and non-guessable value that the RP’s backend should generate per transaction signing session.

    As part of threat modelling, Singpass JS requests for the nonce parameter to mitigate MITM attacks against the /txn-signatures endpoint. This parameter serves the same purpose as the OIDC 1.0’s nonce parameter.

    It should have a maximum of 255 characters. We recommend that you use a hex-encoded random number such as java.security.SecureRandom or UUIDv4.

  • txnInfo string

    A signed JWT that contains the transaction information that the user would sign on using SPM. The structure of the JWT and how it will be validated by Singpass is detailed in the Structure of txnInfo JWT section.

Sample transactionParamsSupplier Implementation

const initiateSessionOnBackend = async () => {
  // Replace the below with an `await`ed call to initiate a session on your backend
  // which will generate state+nonce+txnInfo values.
  // Keep in mind to put in place automated retries, because Singpass will not retry on
  // any errors coming from this function invocation.

  //e.g
  return { state: "dummySessionState", nonce: "dummySessionNonce", txnInfo: "dummyTxnInfo" };
}

const transactionParamsSupplier = async () => {
  const backendSession = await initiateSessionOnBackend();
  return {
    state: backendSession.state,
    nonce: backendSession.nonce,
    txnInfo: backendSession.txnInfo
  };
};

onError function: (errorId, message) ⇒ {}

A callback function that will be invoked by Singpass JS upon certain error events.

On error events, you can expect the appropriate error screens to be rendered on the provided DOMElementID parameter.

The function must accept the following parameters:

  • errorId string

    An Singpass-generated unique identifier for the error/request. If present, it can be used for debugging the error in Singpass.

  • message string

    A short description of the error that occurred. Possible values:

    Error Code
    Description

    invalid_request

    General client side errors, eg. an API call returned a 400 bad request error

    status_subscription_fail

    The status subscription API call that Singpass JS makes has failed

    sign_session_expired

    The current signing session has expired

    service_unavailable

    Transaction signing service is toggled off at Singpass

    txn_signing_fail

    Catch all for unhandled/unknown errors

    txn_signing_cancelled

    The current signing session is cancelled

Sample onError implementation

const onError = (errorId, message) => {
  // Can be any custom implementation to handle the error

  // eg.
  console.log(`onError. errorId:${errorId} message:${message}`);
};

additionalOptions object

Optional configuration to customise additional behaviour:

  • renderDownloadLink string (Optional)

    Whether to render a link to download the Singpass app. Defaults to false if not specified. The link appears below the QR area. Clicking the link opens the Singpass app webpage in a new tab/window.

These additional UI elements will change the height of the rendered UI. See UI dimensions for the expected heights of the UI for the different modes.

  • appLaunchUrl boolean (Optional)

    Intended for mobile apps which embed this javascript and render a QR code. This adds the possibility for the user to be redirected back to the provided App Link after they successfully authorize themselves on the Singpass Mobile App. The value passed here should be the App Link registered with Apple’s App Store and/or Google’s Play Store.

    • Please note that opting into this would mean the relying party is required to be able to initialize auth, i.e generate the QR code, both with and without the appLaunchUrl. This is to ensure the Singpass App only triggers App Links when desired.

Authenticating From
appLaunchUrl Param

Relying Party website

Do not include

Relying Party website on a mobile browser

Do not include

Relying Party mobile app

Can Include

  • Sample additionalOptions implementation:

{
  renderDownloadLink: boolean,
  appLaunchUrl: string
}

Returns

initTxnSigning returns a string that may be one of the following values:

  • SUCCESSFUL

    Pre-flight checks were successful, and you can expect a QR code to be rendered. In case of unforeseen errors (eg. API errors during initialisation), a generic error screen will be rendered with the corresponding erroneous HTTP code, and the onError callback will be invoked.

  • FAILED

    Pre-flight checks failed due to missing or malformed input parameters. If a valid DOMElementID is provided, a generic error screen will be rendered suggesting the user to opt for alternative authorization mechanisms. The onError callback will NOT be invoked.

  • NO_OP

    Input method parameters are valid but pre-flight checks have determined that Singpass JS will not run on the end-user’s browser/user-agent. If a valid DOMElementID is provided, an error screen will be rendered indicating the unsupported browser/user-agent. The onError callback will NOT be invoked.

Sample HTML invoking .initTxnSigning()

<html>
<script src="https://stg-id.singpass.gov.sg/static/ndi_txn_sign.js"></script>
<script>
  async function init() {
    const transactionParamsSupplier = async () => {
      const backendSession = await initiateSessionOnBackend();
      return {
        state: backendSession.state,
        nonce: backendSession.nonce,
        txnInfo: backendSession.txnInfo
      };
    };

    const onError = (errorId, message) => {
      console.log(`onError. errorId:${errorId} message:${message}`);
    };

    const initTxnSigningResponse = window.NDI.initTxnSigning(
      'singpass-qr',
      {
        clientId: 'T5sM5a53Yaw3URyDEv2y9129CbElCN2F',
        redirectUri: 'https://partner.gov.sg/redirect'
      },
      transactionParamsSupplier,
      onError,
      {
        renderDownloadLink: true,
        appLaunchUrl:'https://partner.gov.sg' // Replace with your iOS/Android App Link
      }
    );

    console.log('initTxnSigning: ', initTxnSigningResponse);
}
</script>
<body onload="init()">
<div id="singpass-qr"></div>
</body>
</html>

Structure of txnInfo JWT

The txnInfo returned by the RP-provided transactionParamsSupplier function described above should wrap the required transaction information.

This is a standard signed JWT in compact serialization format.

Sample Signed JWT

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im1vY2stY2xpZW50LWVzMjU2LTEifQ.eyJleHAiOjE2MTQ2NTk1MDAsImlzcyI6IlQ1c001YTUzWWF3M1VSeURFdjJ5OTEyOUNiRWxDTjJGIiwiYXVkIjoiaHR0cHM6Ly9zdGctaWQuc2luZ3Bhc3MuZ292LnNnL3R4bi1zaWduaW5nLXNlc3Npb25zIiwidHhuX2lkIjoidHJhbnNhY3Rpb25faWRlbnRpZmllciIsInR4bl9pbnN0cnVjdGlvbnMiOiJ1cGRhdGUgYmFuayBhY2NvdW50IGZyb20geHh4IHRvIHl5eSIsInR4bl9oYXNoIjoiYTRlNTlhNDBmODM2MjA0NDVlODk1ODcxZTU5Njg5NTcwZWQ2YjY0OTdkMzE1OTYxYTlkNDNmNDRkNDE4NzU4YiIsImlhdCI6MTYxNDY1OTM5Nywic3ViIjoiMWMwY2VlMzgtM2E4Zi00ZjhhLTgzYmMtN2EwZTRjNTlkNmE5In0.JTR09Ou6xBqo1nH19rTzrXyz4aW01_1JeMd6dcEFBJOAFAaVol3erfHvH6hDzA6m5RgfBfO-El6zQODY7o9uig
Parameters
Description

iat - A Unix timestamp in seconds indicating the date and time when the JWT was issued. Must be at most 2 minutes from the current time. exp - A Unix timestamp in seconds indicating the date and time when the JWT will expire. Must not be greater than two minutes from iat. sub - (optional) The user’s Singpass ID (in UUIDv4 format) if available. txn_id - The unique ID of the transaction generated by the RP. txn_instructions - Human-readable instructions that the user can read and consent on. Any sensitive information must be masked. txn_hash - Hashed value of the combined txn_id and txn_instructions claims in the format: <txn_id>:<txn_instructions>. Must be SHA256 hashed and hex-encoded.

Signature

JWT Validation

Singpass backend will validate the signature of the signed JWT using the RP’s JWKS endpoint that was provided during registration.

Singpass caches the keys found in the RP’s JWKS endpoint for one hour. When the RP’s signing keypair needs to be rotated, new keypairs must use a different key id (kid) value to ensure that consumers (e.g. Singpass) of the keys do not use a stale version of the public key in their caches.

.cancelTxnSigningSession()

This function does not require any method parameters, and it also does not return anything.

Upon invocation, all ongoing API calls (if any) made by .initTxnSession() will be aborted. A screen indicating that the transaction has been cancelled is rendered, and there will be no UI changes thereafter.

If a valid onError callback is provided, then it will be invoked with the following parameters: onError(errorId: '', message: 'txn_signing_cancelled')

We recommend invoking this function when a transaction has been cancelled by the user (eg. when the transaction modal is closed) to ensure that the transaction is aborted properly. It is safe to invoke this method regardless of the session’s state (ie. whether the session is active or in an erroneous state).

PreviousEmbedding Singpass JSNextExchange Transaction Signature

Last updated 4 months ago

Was this helpful?

Header - standard JWS Headers. Refer to .

type - Must be "JWT" alg - Must be an ECDSA-based algorithm. See complete list . kid - The key id indicating the key used to sign the JWT

Payload - standard registered claims alongside custom claims highlighted in bold. Refer to .

Standard

https://tools.ietf.org/html/rfc7515#section-4
here
https://tools.ietf.org/html/rfc7519#section-4.1
JWT signature