Skip to content

BankID Proof

What is BankID Proof?

The ID token contains information about the authentication of an end-user, such as when the end-user was authenticated (auth_time), who the end-user is (e.g. bankid_altsub, nnin, name) and what authentication method was used (amr).

In short, the ID token shows that a user has been successfully authenticated by the BankID OIDC Authentication Server.

However, the ID token is not sufficient proof that a BankID High or BankID Substantial transaction has been performed by the end-user.

For merchants and banks that require a stronger, long-term proof of a BankID transaction, we offer "BankID Proof".

What is required to prove a BankID transaction?

Authentication with BankID involves that the end-user signs a randomly generated challenge. The result is a CMS (Cryptographic Message Syntax) signature which includes the end-user's certificate.

In order to prove that a BankID authentication has been performed, you must be able to provide:

  • The challenge signed by the end-user
  • The end-user's signature
  • The end-user's certificate
  • The OCSP (Online Certificate Status Protocol) response for the end-user's certificate

How to retrieve BankID Proof?

To retrieve the BankID Proof after a successful authentication you must provide the bankid_proof scope in the list of scopes to the authorize endpoint.

Access to this scope can be requested by BankID partners and banks by using our support desks.

The bankid_proof token is a JSON Web Signature (JWS) signed by the BankID OIDC Provider and included in the token response.

Example of BankID Proof JWS payload

{
  "endUserOcsp": "MIIHEAoBAK...",
  "endUserSignature": "MIAGCSqGSI...",
  "hashSigned": "xWyTcDzLiB9loBWIClbMnu7ganTPw6Q7gFTo80R+kgU=",
  "serverChallenge": {
    "hashClientNonce": "+vC+eDrHXsjxogwmjJ7M1Kahummb2+K8DHODAEK0ZkI=",
    "internalNonce": "EBgPFbDvXcsbXch2Ed3U4dvmBbQ="
  }
}

The BankID proof for authentication contains:

  • endUserSignature: The end-user's signature including the end-user's certificate
  • endUserOcsp: The OCSP response for the end-user's certificate
  • hashSigned: The challenge signed by the user. Provided for convenience, but should be extracted from the end-user's signature.
  • serverChallenge: Information used to generate the challenge signed by the end-user. The content and method of deriving hashSigned depends on authentication method and if you provided a nonce value in the original authentication request.

Include nonce in authentication request

It is strongly advised that all merchants that use BankID proof provides the nonce parameter in the original authentication request as it will be used in the challenge generation for BankID High, indirectly binding the ID token to the bankid_prooftoken.

Message digest verification

The following table shows how the message digest in the end user signature is calculated. This value should equal hashSigned, but the merchant must always retrieve this from the messageDigest signedAttribute in the SignerInfos of the end user signature.

Please see RFC5652: Signature Verification Process for details.

The following functions are used:

  • base64enc: Base64 encode
  • base64dec: Base64 decode
  • sha256: Generate hash value / message digest using the SHA-256 hash function.
  • idTokenNonce: Should be the same as the nonce parameter passed to the original authentication request
  • utf8GetBytes: Convert UTF-8 string to byte array

BankID High (BID) with nonce

Signature Verifiation calculation

The message digest in the end user signature should equal:

sha256(b64dec(internalNonce) + sha256(utf8GetBytes(idTokenNonce)))

If there is a mismatch, the following can be used to find the issue:

hashClientNonce == sha256(utf8GetBytes(idTokenNonce))
hashSigned == sha256(b64dec(internalNonce) + hashClientNonce)

Also check that hashSigned equals the message digest in the end user signature.

Server challenge payload

{
  "serverChallenge": {
    "hashClientNonce": "+vC+eDrHXsjxogwmjJ7M1Kahummb2+K8DHODAEK0ZkI=",
    "internalNonce": "EBgPFbDvXcsbXch2Ed3U4dvmBbQ="
  }
}

BankID High without nonce

Signature Verifiation calculation

The message digest in the end user signature should equal:

sha256(b64dec(internalNonce))

If there is a mismatch, the following can be used to find the issue:

hashSigned == sha256(b64dec(internalNonce))

Check that hashSigned equals the message digest in the end user signature.

Server challenge payload

{
  "serverChallenge": {
    "internalNonce": "EBgPFbDvXcsbXch2Ed3U4dvmBbQ="
  }
}

Certificate revocation check

You must check the revocation status of the end-user certificate using the end-user OCSP response.

Note: If your certificate has access to NNIN, the NNIN will always be included in the end-user's OCSP response with OID (object identifier) 2.16.578.1.16.3.2.

What about BankID Proof for signing scenarios?

Simple sign flow

If the bankid_proof scope is provided when starting a simple sign flow, the sign_result claim will be omitted as all relevant information will be provided in the bankid_proof token.

Example of BankID Proof JWS payload:

This example is from a simple sign with the text "This is a simple sign text æøå ÆØÅ"

{
  "merchantSignature": "MIAGCSqGSI...",
  "merchantOcsp": "MIIG3woBAK...",
  "endUserOcsp": "MIIHEAoBAK...",
  "hashOriginal": "iuGj0XD14fzQ0fnNBti7llGO2rFufjn9ZCzhkS1ns1o=",
  "endUserSignature": "MIAGCSqGSI...",
  "hashSigned": "kTkeKcvPAs1jImcFk4PRv6hecdDi1bJ3EcGYvi7/xLE="
}

The BankID proof payload contains:

  • endUserSignature: The end-user's signature including the end-user's certificate
  • endUserOcsp: The OCSP response for the end-user's certificate
  • merchantSignature: The merchant's signature including the merchant's certificate
  • merchantOcsp: The OCSP response for the merchant's certificate
  • hashOriginal: Hash over the original sign_txt requested by the merchant
  • hashSigned: The challenged signed by the user. Provided for convenience, but should be extracted from the end-user's signature. Note that hashSigned might be different from hashOriginal if the text contains characters that have different byte values in UTF-8 and ISO-8859-1 or mobile charsets (i.e. GSM).

Full sign flow

If the bankid_proof scope is provided when starting a full sign flow (i.e. SEID-SDO or PAdES), it will contain:

  • endUserSignature
  • endUserOcsp
  • hashSigned

for the first signed document.

This could potentially be used to bind a user authentication with a sign process, but the signature data should be retrieved from the SignDoc Resource Server response and not the bankid_proof token.