Criipto
  1. eIDs
  2. Swedish BankID

JWT/Token example

{
"identityscheme": "sebankid",
Overall eID used to authenticate
"nameidentifier": "1373c272b61a4cb588b29c44883fe62f",
Legacy format of 'sub'
"sub": "{1373c272-b61a-4cb5-88b2-9c44883fe62f}",
Persistent pseudonym. Uniquely identifies an eID user (per Criipto Verify tenant)
"ssn": "196802020575",
Social security number
"name": "Terne Paulsen",
"given_name": "Terne",
"family_name": "Paulsen",
"ipaddress": "77.241.128.160",
"country": "SE"
}

Optional claims for native BankID signature verification

If your use case requires verifying the signature (which is not required, but possible), you have an option to request the evidence data as returned by the underlying e-ID provider. This can be done by adding scope=openid evidence (or login_hint=scope:evidence) to your authorize request.

With this configuration, the issued JWT will contain two additional claims: evidence and ocspResponse:

{
"identityscheme": "sebankid",
Overall eID used to authenticate
"nameidentifier": "1373c272b61a4cb588b29c44883fe62f",
Legacy format of 'sub'
"sub": "{1373c272-b61a-4cb5-88b2-9c44883fe62f}",
Persistent pseudonym. Uniquely identifies an eID user (per Criipto Verify tenant)
"ssn": "196802020575",
Social security number
"name": "Terne Paulsen",
"given_name": "Terne",
"family_name": "Paulsen",
"ipaddress": "77.241.128.160",
"country": "SE",
"evidence": "PD94bWwgdmVyc2lvbj0i...5hdHVyZT4=",
"ocspResponse": "MIIHdgoBAKCCB28wggdrBgk...uSbCquVT1J"
}

The full content of evidence and ocspResponse is omitted for brevity.

Avoiding excessively large JWT payload

When included in the payload, evidence and ocspResponse claims will significantly increase the size of the JWT token, potentially causing it to exceed the size limitations of an HTTP header. The bloated JWTs would thus become unusable as Bearer tokens for accessing APIs.

To address this concern, consider changing the response type in your authorization request to response_type=code id_token.

In this case, a more compact ID Token with only essential claims will be issued from the Token endpoint. The client can subsequently fetch all data about the user from the Userinfo endpoint.

With code id_token response type, the ID Token from the token endpoint will always be the same (and have nothing but a sub that is user-specific). In contrast, when using the response_type=code, the full ID Token is returned immediately in exchange for code.

Test users

Swedish BankID test users are created at the demo web site.

For more information on how to configure your device for test and setup test users: Get a test BankID

Note that, as is also described on the website, using test BankID users does require a reconfiguration of the BankID application. This means it cannot be used for real BankID. So if you are Swedish and already have BankID on your phone, you may want to use a spare phone for testing.

BankID Phone Authentication

BankID in telephone calls facilitates user authentication during a phone call.

Overview

The Phone authentication flow is designed for scenarios where a user is talking with your customer service agent over the phone, and you need to verify that the caller is who they say they are. This is commonly used when a customer contacts their bank or when a call center agent needs to verify the caller's identity.

The process looks as follows:

  1. SSN Input: The customer service agent enters the user's personal identification number (SSN) in their system, or the user is prompted to input their SSN via an automated PBX system.
  2. Authentication request: The customer service agent (if applicable) indicates whether the call was initiated by the user or the company they represent, then initiates authentication request.
  3. Security check: The Swedish BankID app displays a phone icon and the company’s name, prompting the user with a Yes/No security check question.
  4. User Response: If the user selects Yes, they can proceed by identifying themselves with a security code or biometrics. If the user selects No, they can cancel the identification process.

CIBA security check

The example above demonstrates what it looks like when the customer is calling the service. A different security check is shown when the service is calling the customer.

The underlying CIBA flow

Criipto Verify facilitates Swedish BankID phone authentication via the CIBA flow.

Implementing BankID Phone Authentication

The CIBA flow is only available to traditional server-based web applications (confidential clients) and requires client validation for authentication requests. We'll use private key JWTs for authenticaiton in the example below. An alternative (less secure) approach is to use client_secret for authentication.

  1. Make an HTTP POST request to the /ciba/bc-authorize endpoint:
# Replace `$client_assertion` with your JWT assertion
# Replace `YOUR_DOMAIN.criipto.id` with your Criipto domain
# Replace `SSN` with a valid Swedish BankID SSN
# Replace `BINDING_MESSAGE` with the text that will be presented to the end user
# `callInitiator` must be either "RP"("Relying Party", e.g. a customer service agent) or "user", depending on who initiated the call.

HTTP POST https://YOUR_DOMAIN.criipto.id/ciba/bc-authorize
Content-Type: application/x-www-form-urlencoded

scope=openid
&callInitiator=RP
&login_hint=sub:ssn:SSN
&acr_values=urn:grn:authn:se:bankid
&binding_message=BINDING_MESSAGE
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=$client_assertion
  1. A successful response will look something like this:
{ 
  "auth_req_id" : "3857f8ff-21b9-48ae-a732-a3bd8128a7ae",
  "expires_in" : 120 
}
  1. Poll the token endpoint (/oauth2/token) to get a response with an ID token.
    The auth_req_id is used to construct a poll request on the token endpoint:
# Replace `AUTH_REQ_ID` with the id returned by authentication response
# Replace `$client_assertion` with your JWT assertion

HTTP POST https://YOUR_DOMAIN.criipto.id/oauth2/token
Content-Type: application/x-www-form-urlencoded

auth_req_id=AUTH_REQ_ID
&grant_type=urn:openid:params:grant-type:ciba
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=$client_assertion

Polling Frequency: Bear in mind, that the authentication process requires interacting multiple times with the end-user, so the identification process could take some time. Consequently, the token endpoint should be polled every 5 seconds.

Token Delivery Modes: CIBA allows three token delivery methods: Poll, Ping and Push. Criipto Verify only supports the Poll mode at the moment.

  1. The result of a poll request will depend on the state of the process:

On successful user identification, a successful token response is returned, e.g.:

{
  token_type: 'Bearer',
  expires_in: '120',
  id_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjgyN0Q5QTNFOTg2MTY0OTVBQzZGRTE3MUFFNkRBM0IzQ0ExNDE5MjEifQ.eyJpc3MiOiJodHRwczovL25hdGFsaWEtZGV2LXRlc3QuY3JpaXB0by5pbyIsImF1ZCI6InVybjpjaWJhIiwiaWRlbnRpdHlzY2hlbWUiOiJzZWJhbmtpZCIsImF1dGhlbnRpY2F0aW9udHlwZSI6InVybjpncm46YXV0aG46c2U6YmFua2lkIiwiYXV0aGVudGljYXRpb25tZXRob2QiOiJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpTb2Z0d2FyZVBLSSIsImF1dGhlbnRpY2F0aW9uaW5zdGFudCI6IjIwMjQtMDUtMjJUMTA6NDE6NDEuMzYxWiIsIm5hbWVpZGVudGlmaWVyIjoiYmI5YzIzNjRkZmFlNDRmM2JjZmQ5OTkwNTNkOTRmOWUiLCJzdWIiOiJ7YmI5YzIzNjQtZGZhZS00NGYzLWJjZmQtOTk5MDUzZDk0ZjllfSIsInNlc3Npb25pbmRleCI6ImI2NWYxMWI2LWViYTctNDg4Mi05MDBhLTVmMmQ5M2EzOGRiYSIsInNzbiI6IjE5NjgwMjAyMDU3NSIsIm5hbWUiOiJUZXJuZSBQYXVsc2VuIiwiZ2l2ZW5uYW1lIjoiVGVybmUiLCJnaXZlbl9uYW1lIjoiVGVybmUiLCJzdXJuYW1lIjoiUGF1bHNlbiIsImZhbWlseV9uYW1lIjoiUGF1bHNlbiIsImlwYWRkcmVzcyI6IjE4NS4xNTcuMTM0LjEzNCIsImNvdW50cnkiOiJTRSIsImlhdCI6MTcxNjM3NDUwMSwibmJmIjoxNzE2Mzc0NTAxLCJleHAiOjE3MTYzNzU3MDF9.RVQnlukfoH597uXzE1Gays5DElGzAr8xgOmi7ZWppaL3QPGhV4vK2o6qLhxXg_-FKG9xCwHR6gEhnNzWA3W3B6Q2zJeQTYh9okUvTmmhAFIyDL7lEtfWVVKUKvauDisYVZDjAxJQS_1zbgPEi5I-UJ6_kvMGH-wC13MAD2bZGTGR2dR-ZevBUn7plOt0PKXrIZD3vwxDfebTMPQqX_9SNT5F7GLjCcpeVK-T5LOgmUMFcTAbHvNyklqP5ymRHsZLDw_ib4I7ZqODhR-3uISWo1NvG4Y84iBcqv50WRNlmMUm004LfPw1flM5DNsVyUWCqYW8m7eBEwLp5va-6OQG4w',
  access_token: 'cf1ce646-7fbe-4740-9c56-fe3f0891f6c6'
}

The user has not yet interacted with the Swedish BankID app:

HTTP/1.1 400 Bad Request
{
  "error": "authorization_pending",
  "error_description": "awaiting first user interaction"
}

The user has been presented with a message requesting to confirm if they can acknowledge that a request for identification is warranted:

HTTP/1.1 400 Bad Request
{
  "error": "authorization_pending",
  "error_description": "awaiting user request acknowledgement"
}

The user has acknowledged the request, but has not yet identified themselves:

HTTP/1.1 400 Bad Request
{
  "error": "authorization_pending",
  "error_description": "awaiting user identification"
}

The user did not acknowledge that the identification request warranted or canceled the request before identification was performed:

HTTP/1.1 400 Bad Request
{
  "error": "access_denied",
  "error_description": "user declined"
}

Signing text/markdown

Swedish BankID supports signing text and markdown.

Text signing is triggered by using the action and message parameters via login_hint.

  • The action parameter must be set to sign
  • The message parameter must be base64 encoded and at most 40,000 characters after base64 encoding.
  • The message parameter supports markdown text.

Note: Signing produces very large JWTs that are not appropriate for authentication/Bearer header use

Text signing has a different eID cost than authentication, please contact Criipto sales if you have questions.

Example

login_hint=action:sign message:VmVuZG9yOgoKIyMgQ29vbCBEZWxpdmVyeQoKQW1vdW50OgoKIyMgMzAwIEVVUgoKLS0tCgpJIGFwcHJvdmUgdGhpcyB0cmFuc2FjdGlvbi4=

Try out the example in our URL builder

Text signing in app

Round-tripping data that is not visible to the end user

Swedish BankID allows you to send data along in both authentication and signature flows, which they will then embed in the evidence claim after a flow completes succesfully.

You can supply this value via a nonVisibleData parameter in the login_hint. The supplied value must be base64 encoded. Criipto does not attempt to parse or validate the value, we only pass on what is given to the native provider API.

Example

login_hint=nonVisibleData:bm90IHZpc2libGUgdG8gZW5kIHVzZXJzLCBhY2Nlc3NpYmxlIGluIHRoZSBgZXZpZGVuY2VgIGNsYWltIGFmdGVyIGEgZmxvdyBjb21wbGV0ZXMgc3VjY2VzZnVsbHk=

Try out the example in our URL builder

Ordering Swedish BankID

To start accepting real users with Swedish BankID, you must first request a certificate to identify your organization.

Criipto acts as a reseller for Swedbank, which means that you will have to go through a simple approval process with Swedbank. The process is managed by Criipto.

To order the actual certificate simply download this form and return a filled out copy to support@criipto.com

Next steps

After Criipto has received the filled out form, we send it to Swedbank where it will be reviewed and typically approved within a few business days.

Once your organization and your intended use of BankID has been approved we will create and install the actual certificate in your Criipto tenant. and you will be ready to continue the process in the getting ready for production guide.