IdP API Endpoint Overview

Version: 1.1

How to read the guideline

The CAPITALIZED words throughout these guidelines have a special meaning as defined in RFC2119:

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document, are to be interpreted as described in RFC2119.

Glossary

  • Request object - Object representing action which requires end-users consent.
  • Authorization - If not explicitly stated otherwise, in context of this document Authorization is defined as voluntary and conscious consent with action represented by object
  • IDP - Identity Provider - A component on the side of the Bank which handles authorization (in OpenID Connect sense) and consent and issues tokens
  • Authorization server - A component on the side of the Bank with handles request objects, and their authorization by end user
  • OIDC - OpenID Connect - An authentication framework, it is a superset of the OAuth2 authorization framework
  • RP - Relying Party - An OpenID Connect a middleman and orchestrator which sits between Service Providers and Banks - Bank iD
  • JWT - JSON Web Token - A Base64 encoded, signed and possibly encrypted JSON document
  • JWK - JSON Web Key - A JSON describing keys for JWT encryption, description, signing and verification

The following endpoints are to be implemented by the Bank to be compliant with the Bank iD system. Each of these endpoints only contains illustratory examples. Please see the referenced OpenAPI documents for a full authoritative description of these resources.

OpenID Configuration Discovery API

Exposed by the Bank. Authoritatively described in idp_for_bankid.yaml. Not authenticated.

This endpoint provides information about OpenID Connect configuration.

The values given in the configuration response should strictly correspond to reality. According to the declared values, Bank iD registers applications to IDP (parameter values) and calls individual endpoints.

GET /.well-known/openid-configuration

Response 200 OK:

{
  "request_parameter_supported": false,
  "claims_parameter_supported": false,
  "introspection_endpoint": "https://oidc.sandbox.bankid.cz/token-info",
  "profile_endpoint": "https://oidc.sandbox.bankid.cz/profile",
  "scopes_supported": [
    "openid",
    "offline_access",
    "profile.addresses",
    "profile.birthdate",
    "profile.birthnumber",
    "profile.birthplaceNationality",
    "profile.email",
    "profile.gender",
    "profile.idcards",
    "profile.legalstatus",
    "profile.locale",
    "profile.maritalstatus",
    "profile.name",
    "profile.paymentAccounts",
    "profile.phonenumber",
    "profile.titles",
    "profile.updatedat",
    "profile.zoneinfo",
    "profile.verification"
  ],
  "issuer": "https://oidc.sandbox.bankid.cz/",
  "acr_values_supported": [
    "loa2",
    "loa3"
  ],
  "userinfo_encryption_enc_values_supported": [
    "A256GCM"
  ],
  "id_token_encryption_enc_values_supported": [
    "A256GCM"
  ],
  "authorization_endpoint": "https://oidc.sandbox.bankid.cz/auth",
  "service_documentation": "https://oidc.sandbox.bankid.cz/about",
  "request_object_encryption_enc_values_supported": [
    "A256GCM"
  ],
  "device_authorization_endpoint": "https://oidc.sandbox.bankid.cz/devicecode",
  "userinfo_signing_alg_values_supported": [
    "ES512",
    "PS512"
  ],
  "claims_supported": [
    "addresses.buildingapartment",
    "addresses.city",
    "addresses.country",
    "addresses.ruian_reference",
    "addresses.street",
    "addresses.streetnumber",
    "addresses.type",
    "addresses.zipcode",
    "age",
    "birthdate",
    "birthnumber",
    "birthplace",
    "date_of_death",
    "email",
    "email_verified",
    "family_name",
    "gender",
    "given_name",
    "idcards.country",
    "idcards.description",
    "idcards.issue_date",
    "idcards.issuer",
    "idcards.number",
    "idcards.type",
    "idcards.valid_to",
    "limited_legal_capacity",
    "locale",
    "majority",
    "maritalstatus",
    "middle_name",
    "name",
    "nationalities",
    "nickname",
    "paymentAccounts",
    "pep",
    "phone_number",
    "phone_number_verified",
    "preferred_username",
    "primary_nationality",
    "sub",
    "title_prefix",
    "title_suffix",
    "txn",
    "updated_at",
    "verified_claims.verification",
    "zoneinfo"
  ],
  "claim_types_supported": [
    "normal"
  ],
  "op_policy_uri": "https://oidc.sandbox.bankid.cz/about",
  "token_endpoint_auth_methods_supported": [
    "client_secret_post",
    "client_secret_jwt",
    "private_key_jwt"
  ],
  "response_modes_supported": [
    "query"
  ],
  "token_endpoint": "https://oidc.sandbox.bankid.cz/token",
  "response_types_supported": [
    "code",
    "token"
  ],
  "request_uri_parameter_supported": true,
  "userinfo_encryption_alg_values_supported": [
    "RSA-OAEP-256"
  ],
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "refresh_token"
  ],
  "end_session_endpoint": "https://oidc.sandbox.bankid.cz/logout",
  "userinfo_endpoint": "https://oidc.sandbox.bankid.cz/userinfo",
  "token_endpoint_auth_signing_alg_values_supported": [
    "ES512",
    "PS512"
  ],
  "op_tos_uri": "https://oidc.sandbox.bankid.cz/about",
  "require_request_uri_registration": true,
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ],
  "id_token_encryption_alg_values_supported": [
    "RSA-OAEP-256"
  ],
  "jwks_uri": "https://oidc.sandbox.bankid.cz/.well-known/jwks",
  "subject_types_supported": [
    "public",
    "pairwise"
  ],
  "id_token_signing_alg_values_supported": [
    "ES512",
    "PS512",
    "none"
  ],
  "request_object_signing_alg_values_supported": [
    "ES512",
    "PS512"
  ],
  "request_object_encryption_alg_values_supported": [
    "RSA-OAEP-256"
  ]
}

JWK Keys Discovery API

Exposed by the Bank and Bank iD. Authoritatively described in idp_for_bankid.yaml. Not authenticated.

This endpoint returns JSON Web Keys to be used as public keys for verifying OIDC ID Tokens and responses, as well as for encrypting requests.

GET /.well-known/jwks.json

Response 200 OK:

{
  "keys": [
    {
      "alg": "RS256",
      "kid": "1603dfe0af8f4596",
      "key_ops": [
        "sign",
        "verify"
      ],
      "use": "sig",
      "kty": "RSA",
      "x5c": "MIICUDCCAbmgAwIBAgIBADANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJjejEOMAwGA1UECAwFUHJhaGExEDAOBgNVBAoMB0V4YW1wbGUxFDASBgNVBAMMC2V4YW1wbGUuY29tMB4XDTIwMDExNjE2NDExOFoXDTIxMDExNTE2NDExOFowRTELMAkGA1UEBhMCY3oxDjAMBgNVBAgMBVByYWhhMRAwDgYDVQQKDAdFeGFtcGxlMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArOEYBRyBhcd6u3phrbU2xvTaBoy6W14CpqqfsBrfsUsuSB+JELBCj3a+zRIvy4EY9cnQbF7cPNxbXdCbGEokAUjIIuVBk/I6XhKRe01vlax82o+eFfIhUfl7Xb2Bx9U3m98Qbt3WNrv+VYJjjFP8HWSsWCHKCazj+yvozjuFXUsCAwEAAaNQME4wHQYDVR0OBBYEFN5SUrsStd4aLhBs+MWGRDxLeUP4MB8GA1UdIwQYMBaAFN5SUrsStd4aLhBs+MWGRDxLeUP4MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAL59fE6itiRrck6Z7RCjwnOnebQJxpoB/L7TUC/aUIXss40mCviBVKD+Hl4+3sGyp4J2LlzzqhFcPgR9NyxQt0bkahJGH0UXvZETJe719UA0kGFrPMdt6ujwB6/rafT6TinzXN0lEEGikersTrh3BR9Hjw+v7nCQ0D5RfuDn6s5s="
    }
  ]
}

HealthCheck API

Exposed by the Bank. Authoritatively described in idp_for_bankid.yaml. Not authenticated.

This endpoint returns the current Bank liveness and outage information.

HealthCheck MUST describe the current system availability (OK|ERROR). This information is required for:

  1. This information is presented to the End-User, possibly in a derived form, or form that is aggregated from multiple Banks at once
  2. This information is needed to prevent unnecessary failing calls to the Bank APIs, this lightens the load of failing Bank APIs (which may be failing due to high load) and minimizes chance of data loss and corruption

Outage

In the context of Bank iD specification, an outage is a state of the system which is unavailable due to a planned or unplanned maintenance. The Bank SHOULD communicate outage end-time, when available, through the outage_planned_until property.

Design of this API is intended to allow automatic propagation of the outage information from internal Bank systems into the Bank iD RP.

Sub-system outages

It is possible that a only part of the system is experiencing an outage, however the rest remains fully operational. For this reason the HealthCheck Endpoint SHOULD implement the details property whenever possible.

Sub-system health information allows the Bank iD and SeP to only stop processes which are dependent on the failing services keep the rest operational if possible.

Differences between Bank iD HealthCheck and COBS RuleBook HealthCheck

  • outage_description has been added. The Bank SHOULD use this property to communicate the reason for the current outage
  • details property has been updated to reflect Bank iD sub-systems
  • poll_interval has changed from free-form string into a number specified in milliseconds to prevent ambiguity

GET /healthcheck

Response 200 OK:

{
  "status": "OK",
  "description": "Bank iD API",
  "version": "1.1.0",
  "time": "2020-05-20T11:06:27.767Z",
  "outage_planned_until": null,
  "outage_description": null,
  "poll_interval": 200,
  "details": {
    "dynamic-registration": {
      "status": "OK",
      "description": "Dynamic Registration API",
      "version": "1.1.2",
      "time": "2020-05-20T11:06:27.767Z"
    },
    "oidc-core": {
      "status": "OK",
      "description": "Core OpenID Connect APIs",
      "version": "1.1.7",
      "time": "2020-05-20T11:06:27.767Z"
    },
    "revoke": {
      "status": "OK",
      "description": "OAuth2 Token Revocation API",
      "version": "1.1.2",
      "time": "2020-05-20T11:06:27.768Z"
    },
    "kyc": {
      "status": "OK",
      "description": "KYC API",
      "version": "1.1.0",
      "time": "2020-05-20T11:06:27.768Z"
    }
  }
}

Dynamic Registration API

CRUD over registered clients. Protected by mTLS and HTTP Bearer authentication where bearer token is a JWT signed with a key from /.well-known/jwks.json of the Bank iD. This JWT contains claims defined in the RegistrationAuthJWT schema.

Example of RegistrationAuthJWT payload. This token is sent in signed form as the value of the client_assertion request header parameter:

{
  "aud": "https://op.example.com/register",
  "jti": "95E3440A-C986-4E8B-9678-605F9B2FE7C5",
  "exp": 1630492200,
  "iat": 1598956200
}

For dynamic registration, the aud parameter in the RegistrationAuthJWT payload always contains the URL of the POST endpoint of the called registration API (ie, also in the case of the PUT, GET and DELETE methods).

Exposed by the Bank. Authoritatively described in idp_for_bankid.yaml. Uses HTTP Bearer authentication using a JWT token signed on the Bank iD side. See the RegistrationAuthJWT specification..

POST (create) /register

GET (read), PUT (update), DELETE (remove) /register/{client_id}

Request header in case of POST:

POST /register HTTP/1.1
Host: idp.somebank.cz
Content-Type: application/json
client_assertion: eyJraWQiOiJycC1zaWduIiw......7xpA26QF5_Oung7E4y2n6
client_assertion_type: urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer

Request header in case of PUT,GET and DELETE:

POST /register HTTP/1.1
Host: idp.somebank.cz
Content-Type: application/json
client_assertion: eyJraWQiOiJycC1zaWduIiw......7xpA26QF5_Oung7E4y2n6
client_assertion_type: urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
Authorization: Bearer 44010DFF-F77F-461A-8F3D-1466B24C5CC1

Please note that the authorization_access_token value obtained in the POST call must be here sent as a Bearer token in the Authorization header parameter.

Request body (POST and PUT):

{
  "redirect_uris": [
    "https://client.example.com/callback",
    "https://rp.example.com/callback"
  ],
  "response_types": [
    "code"
  ],
  "grant_types": [
    "authorization_code",
    "refresh_token"
  ],
  "application_type": "web",
  "contacts": [
    "ve7jtb@example.com",
    "mary@example.com"
  ],
  "client_name": "My Example",
  "logo_uri": "https://client.example.com/logo.png",
  "client_uri": "https://client.example.com",
  "policy_uri": "https://client.example.com/policy",
  "tos_uri": "https://client.example.com/tos",
  "jwks_uri": "https://client.example.com/my_public_keys.jwks",
  "sector_identifier_uri": "https://other.example.net/file_of_redirect_uris.json",
  "subject_type": "pairwise",
  "id_token_signed_response_alg": "PS512",
  "id_token_encrypted_response_alg": "RSA-OAEP-256",
  "id_token_encrypted_response_enc": "A256GCM",
  "userinfo_signed_response_alg": "PS512",
  "userinfo_encrypted_response_alg": "RSA-OAEP-256",
  "userinfo_encrypted_response_enc": "A256GCM",
  "profile_signed_response_alg": "PS512",
  "profile_encrypted_response_alg": "RSA-OAEP-256",
  "profile_encrypted_response_enc": "A256GCM",
  "request_object_signing_alg": "PS512",
  "request_object_encryption_alg": "RSA-OAEP-256",
  "request_object_encryption_enc": "A256GCM",
  "token_endpoint_auth_method": "private_key_jwt",
  "token_endpoint_auth_signing_alg": "PS512",
  "default_max_age": 3600,
  "require_auth_time": false,
  "default_acr_values": [
    "loa3"
  ],
  "initiate_login_uri": "https://client.example.com/login",
  "request_uris": [
    "https://client.example.com/rf.txt",
    "#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA"
  ],
  "backchannel_logout_uri": "https://client.example.com/backchannel_logout\"",
  "scope": "openid profile.name profile.addresses offline_access",
  "required_scope": "profile.addresses",
  "notification_uri": "https://api.bankid.cz/v1/notifyme"
}

Response 200 OK:

{
  "client_id": "D40D25DB-C330-4331-A191-0A4F6CCD17D8",
  "client_secret": "689A79B8-9EE4-45A9-83B1-4F0130649394",
  "registration_access_token": "44010DFF-F77F-461A-8F3D-1466B24C5CC1",
  "registration_client_uri": "https://idp.example.com/connect/register/D40D25DB-C330-4331-A191-0A4F6CCD17D8",
  "client_id_issued_at": 1579263956,
  "redirect_uris": [
    "https://client.example.com/callback",
    "https://rp.example.com/callback"
  ],
  "response_types": [
    "code"
  ],
  "grant_types": [
    "authorization_code",
    "refresh_token"
  ],
  "application_type": "web",
  "contacts": [
    "ve7jtb@example.com",
    "mary@example.com"
  ],
  "client_name": "My Example",
  "logo_uri": "https://client.example.com/logo.png",
  "client_uri": "https://client.example.com",
  "policy_uri": "https://client.example.com/policy",
  "tos_uri": "https://client.example.com/tos",
  "jwks_uri": "https://client.example.com/my_public_keys.jwks",
  "sector_identifier_uri": "https://other.example.net/file_of_redirect_uris.json",
  "subject_type": "pairwise",
  "id_token_signed_response_alg": "PS512",
  "id_token_encrypted_response_alg": "RSA-OAEP-256",
  "id_token_encrypted_response_enc": "A256GCM",
  "userinfo_signed_response_alg": "PS512",
  "userinfo_encrypted_response_alg": "RSA-OAEP-256",
  "userinfo_encrypted_response_enc": "A256GCM",
  "profile_signed_response_alg": "PS512",
  "profile_encrypted_response_alg": "RSA-OAEP-256",
  "profile_encrypted_response_enc": "A256GCM",
  "request_object_signing_alg": "PS512",
  "request_object_encryption_alg": "RSA-OAEP-256",
  "request_object_encryption_enc": "A256GCM",
  "token_endpoint_auth_method": "private_key_jwt",
  "token_endpoint_auth_signing_alg": "PS512",
  "default_max_age": 3600,
  "require_auth_time": false,
  "default_acr_values": [
    "loa3"
  ],
  "initiate_login_uri": "https://client.example.com/login",
  "request_uris": [
    "https://client.example.com/rf.txt",
    "#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA"
  ],
  "backchannel_logout_uri": "https://client.example.com/backchannel_logout\"",
  "scope": "openid profile.name profile.addresses offline_access",
  "required_scope": "profile.addresses",
  "notification_uri": "https://api.bankid.cz/v1/notifyme"
}

Response 400 Request invalid:

{
  "error": "invalid_redirect_uri",
  "error_description": "Redirect uri must be using https scheme"
}

Sequence diagram of new application registration


Authentication API

For Service providers, Bank iD supports various Authentication flow types of grants for the authentication process and obtaining access_token and id_token.

Flow typeDescription
authorization_code refresh_tokenCode grant is the most common authentication flow. It allows applications to securely exchange tokens and obtain a refresh_token in case of offline access.
implicitNo matter what type of grant the Service Provider has chosen for its application, all calls to the IDP are made by Bank iD within the code grant flow!

Diagram with example of code grant flow

The sequence diagram shows the course of the authentication flow with the exchange of code for tokens. In the case of offline access, the chart is supplemented by an example of exchanging a refresh token for an access token.

The authentication GET endpoint is a starting point for OAuth2 and OpenID Connect authorization code flows. This request authenticates the user and returns tokens to the client application as a part of the callback response.

Exposed by the Bank. Authoritatively described in idp_for_bankid.yaml. Not authenticated.

GET /auth?
  redirect_uri=https://bankid.cz/callback
  &client_id=D40D25DB-C330
  &response_type=code
  &state=1234
  &scope=openid%20profile.name%20profile.gender%20offline_access
Host: somebank.cz

Scope openid is required! In the context of its use, it is specified that the authorization flow control will be a process established by the OpenID standard (e.g., including the issuing of id_token).

The scope offline_access should be specified whenever the application, based on the authentication flow, requires the release of not only access_token but also refresh_token. For such a case, the application must have registered code grant flow and refresh_token grant (during dynamic registration to the IDP).

Response redirection:

HTTP/1.1 302 Found
Location: https://bankid.cz/callback?
  code=6a72a932a67cf859570a8fb986dcefce19c844995d30fe1ad32d1e5af5579eb2
  &state=1234

Error redirection:

HTTP/1.1 302 Found
Location: https://bankid.cz/callback?
  error=unauthorized_client
  &state=1234

Tokens used in the Bank iD solution

An overview of the tokens and their characteristics that Bank iD requires from IDP when issuing these tokens.

Tokens

Token typeUseRequired minimum token validity
access_tokenToken used to authorize API requests.3600 seconds
refresh_tokenToken representing offline (long-term) access. Refresh_token is used to release a new short-term access_token.1 year
id_tokenThis token was identifying the end-user within the current context and session.At least as long as access_token (3600 seconds)

Basic assumptions:

  • The issuance of these tokens MUST be independent of the context of previous and future authentications.
  • The authentication process MUST not affect the validity of previously issued tokens. Except in specific cases where the authentication process will be evaluated as a security risk and, for example, if the authentication device will be temporarily or permanently blocked.
  • The authentication process MUST do not affect the context (scopes) of previously issued tokens.
  • Any token CAN be invalidated with immediate effect using the mechanisms provided for this purpose (revoke, logout services).
  • Whether an application has a scope registered as optional or required has no effect on the scopes' final composition

in the token. Suppose the application does not require any of the required registered scopes in a specific authentication. In that case, this scope will not appear either on the consent screen or during successful authentication at the token. The scope obligation only affects the GUI controls on the consent screen.

Access Token

The access_token is the main result of the authentication process. This token is used to call user-centric APIs (primarily /userinfo and /profile). In the case of Bank iD, it may be a signed stateless token. The access_token hash can be specified as one of the id_token claims (specifically at_hash claim), which is issued simultaneously with the access_token to ensure integrity.

This token's validity can be found directly at issue in response (authorization_code and refresh_token grant flow) to the API /token or call the API /token-info. The response to the call /token MUST also include a list of scopes for the issued token.

Refresh Token

Refresh_token is used to issue a new access_token, for example, if the access_token expires. Refresh_token is issued if the application requesting its release has a refresh_token grant registered with the IDP and the application asked for an offline_access scope in the authentication request.

The scope of this token's context corresponds to the result of the authentication at which it was issued. When exchanging refresh_token for access_token, the application can request the same or smaller range of scopes.

ID Token

The id_token represents the identification of the end-user and is issued together with the access_token. The id_token is always signed and contains information about the time of issue and validity of the token. In the case of Bank iD, it always contains the end-user identifier as a claim sub.

The id_token is issued signed by the issuer's key, and the application must verify this signature in each case.

The id_token can be issued in encrypted form if this IDP declares in its configuration. Encryption is performed using one of the application's public encryption keys (listed on the registered JWKs URI). Bank iD does not directly require this feature (because the required id_token does not contain any sensitive data).


Token exchange API

The token endpoint is used by the client to obtain an access token by presenting its authorization grant or refresh token.

To clarify the usage of token exchange API here are a few scenarios which could take place one after another:

Scenario 1 code exchange

  1. SeP requires these scopes "openid profile.name profile.idcards offline_access" in /auth
  2. IdP shows consent screen
  3. SeP exchanges code for access_token
  4. SeP calls /profile with access_token and receives data from IdP

Scenario 2 code exchange with less scopes

  1. SeP requires these scopes "openid profile.name profile.idcards" in /auth
  2. IdP may not show consent screen
  3. SeP exchanges code for access_token
  4. SeP calls /profile with access_token and receives data from IdP

Scenario 3 code exchange with more scopes

  1. SeP requires these scopes "openid profile.name profile.idcards profile.address offline_access" in /auth
  2. IdP shows consent screen, because consent for profile.address was not given by enduser
  3. SeP exchanges code for access_token
  4. SeP calls /profile with access_token and receives data from IdP

Scenario 4 code exchange

  1. SeP requires only "openid" in /auth
  2. IdP may not show consent, if for all registered scopes via /register endpoint has been given consent by enduser, otherwise it has to show consent screen
  3. SeP exchanges code for access_token and IdP assigns for this access_token all scopes registered via /register endpoint eg. "openid profile.name profile.idcards profile.address offline_access"
  4. SeP calls /profile with access_token and receives data from IdP

Scenario 5 refresh_token exchange

  1. SeP exchanges refresh_token for access_token with scopes "openid profile.name profile.idcards profile.address profile.email"
  2. IdP returns error, because profile.email is not assigned with current refresh_token

Scenario 6 refresh_token exchange

  1. SeP exchanges refresh_token for access_token and doesn't specify any scope
  2. IdP returns access_token with assigned scopes from previous refresh_token, IdP may include new refresh_token with the same expiration as previous refresh_token in which case previous refresh_token has to be discarded

Scenario 7 refresh_token exchange

  1. SeP exhanges refresh_token with scope "openid"
  2. IdP returns access_token with assigned only "sub"
  3. SeP calls /profile a gets only "sub" and txn will have only "openid"

Scenario 8 refresh_token exchange

  1. SeP exhanges refresh_token with scope "openid profile.name profile.idcards"
  2. IdP returns access_token with assigned scopes which are subset of scopes assigned to the refresh_token
  3. SeP calls /profile with access_token and receives data from IdP

Exposed by the Bank. Authoritatively described in idp_for_bankid.yaml. Uses client credentials for authentication.

POST /token

Authorization code exchange request:

POST /token HTTP/1.1
Host: idp.somebank.cz
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=2a54acba-f5d8-48cb-9c28-a06583724adb
&code=8BFAC1DA-3F94-4BBD-A743-473080FB6073
&redirect_uri=https://bankid.cz/callback
&client_assertion=eyJraWQiOiJycC1zaWduIiw......7xpA26QF5_Oung7E4y2n6
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer

Client assertion JWT payload for /token endpoint example:

{
  "aud": "https://idp.somebank.cz/token",
  "sub": "D40D25DB-C330",
  "iss": "D40D25DB-C330",
  "exp": 1605544030,
  "iat": 1605540430,
  "jti": "c7588da5-3732-421d-a974-1427bc5035c6"
}

Authorization code exchange response 200 OK:

{
  "access_token": "c03e997c-aa96-4b3f-ad0c-98626833145d",
  "token_type": "Bearer",
  "refresh_token": "1f703f5f-75da-4b58-a1b0-e315700e4227",
  "expires_in": 6000,
  "scope": "openid profile.name profile.addresses",
  "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}

Refresh token exchange request body:

POST /token HTTP/1.1
Host: idp.somebank.cz
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&scope=openid%20profile.name%20profile.addresses
&code=A9B54609-FF9E-42F0-B089-89E1E73E224F
&redirect_uri=https://bankid.cz/callback
&client_assertion=eyJraWQiOiJycC1zaWduIiw......7xpA26QF5_Oung7E4y2n6
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer

Client assertion JWT payload for /token endpoint example:

{
  "aud": "https://idp.somebank.cz/token",
  "sub": "D40D25DB-C330",
  "iss": "D40D25DB-C330",
  "exp": 1605544030,
  "iat": 1605540430,
  "jti": "c7588da5-3732-421d-a974-1427bc5035c6"
}

Refresh token exchange response 200 OK:

{
  "access_token": "c03e997c-aa96-4b3f-ad0c-98626833145d",
  "token_type": "Bearer",
  "expires_in": 30000001,
  "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}

Response 400 Request invalid:

{
  "error": "invalid_request",
  "error_description": "The request is missing a required parameter"
}

TokenInfo API

The introspection endpoint is an OAuth 2.0 endpoint that takes a parameter representing an OAuth 2.0 token and returns a JSON representing the meta information surrounding the token, including whether this token is currently active.

Exposed by the Bank. Authoritatively described in idp_for_bankid.yaml. Uses client credentials or a client access token for authentication.

POST /token-info

Request body:

POST /token-info HTTP/1.1
Host: idp.somebank.cz
Content-Type: application/x-www-form-urlencoded

token=WwVEraxkI7KbtP31wD3XSpZKqGpsLiXg
&token_type_hin=refresh_token
&client_assertion=eyJraWQiOiJycC1zaWduIiw......7xpA26QF5_Oung7E4y2n6
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer

Client assertion JWT payload for /token-info endpoint example:

{
  "aud": "https://idp.somebank.cz/token-info",
  "sub": "D40D25DB-C330",
  "iss": "D40D25DB-C330",
  "exp": 1605544030,
  "iat": 1605540430,
  "jti": "c7588da5-3732-421d-a974-1427bc5035c6"
}

Response:

{
  "active": true,
  "scope": "openid profile.addresses",
  "client_id": "d1bdc32e-1b06-4609-9f60-073685267f88",
  "token_type": "access_token",
  "exp": 1419356238,
  "iat": 1419350238,
  "sub": "25657805-66d4-4707-980a-f12429f17592",
  "aud": "https://idp.somebank.cz/token-info",
  "iss": "https://idp.somebank.com/"
}

Token revocation API

Token revocation endpoint. Revokes access and refresh tokens. Revoking a refresh token effectively cancels the "session".

Exposed by the Bank. Authoritatively described in idp_for_bankid.yaml. Uses client credentials or a client access token for authentication.

POST /revoke

Request body:

POST /revoke HTTP/1.1
Host: idp.somebank.cz
Content-Type: application/x-www-form-urlencoded

token=WwVEraxkI7KbtP31wD3XSpZKqGpsLiXg
&token_type_hin=refresh_token
&client_assertion=eyJraWQiOiJycC1zaWduIiw......7xpA26QF5_Oung7E4y2n6
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer

Client assertion JWT payload for /revoke endpoint example:

{
  "aud": "https://idp.somebank.cz/revoke",
  "exp": 1605544030,
  "iat": 1605540430,
  "jti": "c7588da5-3732-421d-a974-1427bc5035c6"
}

User info API

The UserInfo and Profile API are the basic interfaces for retrieving authenticated user data. The range of user-approved scopes strictly controls the range of data. A detailed list of scopes and their associated claims is available in the API technical documentation idp-for-bankid.yaml.

UserInfo endpoint is intended primarily for frequently performed identification and authentication, such as repeated login processes to the system/application. This endpoint's data range corresponds to the data ranges for logins using social network identities (Google, LinkedIn).

Access is authorized using a valid end-user access_token that was obtained from a completed login flow.

GET /userinfo

Request example:

GET /userinfo HTTP/1.1
Host: idp.somebank.cz
Accept: application/jwt
Authorization: Bearer eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwi

Response 200 OK (application/jwt):

eyJraWQiOiJBNjJGMjIyNUJGNzBCIiwiY3R5IjoiSldUIiwiZW5jIjoiQTI1NkdDTSIsImFsZyI6IlJTQS1PQUVQLTI1NiJ9.rHJXU29na1PQTqVbmwgyfub
RnWN9X5IhkERXrlF6pffr3vjPXfNe7M-YvPlDf7qiUvAlYGHCoeYvH31q6RmaLI9YHsHWXWjpaQjoI-ubLduY1wN2t6xUb2g0bH-RE48zawDL18ZLvEn_6f8
97Y2SAYO3xEzRTHifmDJhdLPPhoYi0mACxoSWCeeXIbe1wPs235aNY2K6CjTlbnU-aIfiBagyRWSeaHjColbTVEXFfGvoLWfyayaftvkezxP9zGjIaQbi9KNX
cx4NgCp99vk-rfchLpuQHFNVXldKd3mEXhwlKeG-rp0AMpONk8tmrXuTtD0XmaQMVOXO585mqWrvOblqeeXMXUwYQsOx02F3QdfsJ3-5irT4IBkLo-KZRzc5J
Jwh-UBKcK78IWfSssiTAsC3cbZUyG3hwjguf13lIJGbwmjlZZ6u9hPxRgP1Ke_wgJ20pUEDgtPOzZMPVppM4Iloj6XpX0S4kYDFhhH0MQCcBVTHBxTgaBVjW8
RVliL5-5yowZVVuJMJiyMWpTY1K2EdX2lUjyW-a2hkafobRag0aKQaKHLLZeDV3Q26RjJ134xI86ftEjHl-KePc_q5DqjZbqJ4-MGD-ZGXJAyk_29vdH3I3a
wu-rZineAmAXtJd0FTaBeYPBXHLiERoGN1DPQPZSTD2XonFLRDIJN_UVo.fbYdUiuJ_Q9Bl4IY.c0gJoDfJideIwVUGyG9fQWmP5CT99Ebc95WCqPx_2z9Hx
vs4cTz8OFOoKdOueUZhbPH6quVgaQsdoOD8-eotRd5uTAhWn06o3CVxUVwhOxwbgr-NGQjNLn6F6DDbPXRF_S5mZ6_1QdRW50Un119C6TWqEFWTdYewqWJKZ
97MbBSDS4hfCjQbzVFaNL5sdiAJn5hK6FZtquBcxzj84joLqMuZo5LGIPE9WWScMzzgfuf8RjRENSipNQdFqJLEeXlA9xI13jx0_iJQxv0OhR4zZUMG0UQ9v
GnTJH-agNGxClDPM4Z9f40Od34bdGIOke0-AiIAXvVPelnDVhNR14fuGcHlNZ53ftCYqP6KIECOMCW94_J8Wxz2OUhwocGYI5_bvL24opLQAC9qlHXJk5Syx
jkmPROwypa3Fwx0Al8o7oQUCr8Az2Q-e_-jugSYhVi99hQBCIO5oiK2WYB6V04Ka8tXYM9SVfyANY_82vf3GR9cwuQz_pUwfw-YjLH5FDmXCjZzBKeHooLJ0
odyA1agxUuqOhAsEz9tQ64w9wNXe3NI7PVgmEvLMvp6DPfcuBaZuR_gzomkV2JefoguirQ8dMfeulSGIBY8h5Icq9Nt5S6MTKpUsulxfgRRrlxwMP-pvGaf4
5hUUsVQTSglrZ8hU_anEuVprShwFPqdTCcYYqne9dGjfw8O8vqAi2bLNUxbfnvdi1WblbYtqS7_VgXcu7Hfzb_u1YyM0jfnwzwJaKx3ptcNwdQodiGpot0p
vSpRf1iYj4Sp806Tz3eVdnuY4UDI6XPHXIGtMal6wqR1oCNepSyAXfZ_J_HOj4KMTnpq1cW0XQQOAT6APHeL3VeMpk94WVInCkHvoc1ZJj3Sf0NATmVOj9XR
y_Z7lnvwdIu7C1J6EFebnxkPB0rWSouKEcJVnNLT8i7Nx2WiXM1JJzpVhD0bgM2VAU0UcnQQmR-DnsKsBUoPXf8NFODqQob5WYr0z-1xj_2TT5KeUBNiuKcQ
8arAeq57FLPWeN9QGun9jakdkAO76dkQYuwew6pWuAJ1prBswvQCmSkzVOGSu644WOSALwqwN4tKoQo008gEMvlpwXoBCZ0Tv5iHBoggsYExdc1dCIGsLAoS
FkhhSg26YVWBLBXs6X2uyqAZXzVBV2-Mn3dXpuyKXehZmPEEjfGQgyrXuo8XSW7hHVyOe-u-n-nJ7WLnGkBMlih8h2JUvyBJ3fXGLn5wXXlKZTRCIsvAjq1Q
D835KWloJNy0_3el1Uew2GgmY8uc2EloKmNDHbFRwQPZori0JBaW8CdZe8pFiiNt90RT837V01vWEN5YLDuDVcsHr77ueiiyu0v3ZZjRVZtUO1XqKa4RlL3IK
utb0twc6ehxbF4OQ9LfKKfS2SXljWyKV9VDqp0HhnJhJyJOwIJ9s_Aq1ue7xntbrs2D9pg17f7d6gCaqkfM5_kd4e8FertkDfx4cfBGhFEF5tL4oIUJy-l6xh
PBDwq0KqEct6MMf9oboQKjEqKnDYSvCcdeQlfd4AHooBXssRQ6uiiQ4ROJBM_MlLaPYsKCBQdp9KRzJNeb3OcDHfVWJ_C949I-YRgpyEBS6-jNJYrFrIJpPG
C2sV4KpB5lWLEZsKKSAFGGp97VPccw3pR_DIsaefC5ZCD-W5PPuVaUvUlgPtQB1oYRseutYXECbiV2VCkByLhvyt11XpK2eviZxZ0XgptmDSiyyGZrjcNF9K-
2taoS4XiDRsCC2OABcCn4TQqi4tiElQ.LWq6zSH5jUdt6V-zdo63qQ

Sequence diagram of the Userinfo API call

Profile API

Unlike UserInfo, the Profile API is designed primarily to perform KYC or AML client authentication. This corresponds to a much more extensive range of data provided. A complete overview of claims and scopes is in the detailed API documentation idp-for-bankid.yaml.

Access is authorized using a valid end-user access_token that was obtained from a completed login flow.

GET https://oidc.sandbox.bankid.cz/profile

Request example:

GET /profile HTTP/1.1
Host: idp.somebank.cz
Accept: application/json
Authorization: Bearer eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwi

Response 200 OK (application/jwt):

eyJraWQiOiJBNjJGMjIyNUJGNzBCIiwiY3R5IjoiSldUIiwiZW5jIjoiQTI1NkdDTSIsImFsZyI6IlJTQS1PQUVQLTI1NiJ9.rHJXU29na1PQTqVbmwgyfub
RnWN9X5IhkERXrlF6pffr3vjPXfNe7M-YvPlDf7qiUvAlYGHCoeYvH31q6RmaLI9YHsHWXWjpaQjoI-ubLduY1wN2t6xUb2g0bH-RE48zawDL18ZLvEn_6f8
97Y2SAYO3xEzRTHifmDJhdLPPhoYi0mACxoSWCeeXIbe1wPs235aNY2K6CjTlbnU-aIfiBagyRWSeaHjColbTVEXFfGvoLWfyayaftvkezxP9zGjIaQbi9KNX
cx4NgCp99vk-rfchLpuQHFNVXldKd3mEXhwlKeG-rp0AMpONk8tmrXuTtD0XmaQMVOXO585mqWrvOblqeeXMXUwYQsOx02F3QdfsJ3-5irT4IBkLo-KZRzc5J
Jwh-UBKcK78IWfSssiTAsC3cbZUyG3hwjguf13lIJGbwmjlZZ6u9hPxRgP1Ke_wgJ20pUEDgtPOzZMPVppM4Iloj6XpX0S4kYDFhhH0MQCcBVTHBxTgaBVjW8
RVliL5-5yowZVVuJMJiyMWpTY1K2EdX2lUjyW-a2hkafobRag0aKQaKHLLZeDV3Q26RjJ134xI86ftEjHl-KePc_q5DqjZbqJ4-MGD-ZGXJAyk_29vdH3I3a
wu-rZineAmAXtJd0FTaBeYPBXHLiERoGN1DPQPZSTD2XonFLRDIJN_UVo.fbYdUiuJ_Q9Bl4IY.c0gJoDfJideIwVUGyG9fQWmP5CT99Ebc95WCqPx_2z9Hx
vs4cTz8OFOoKdOueUZhbPH6quVgaQsdoOD8-eotRd5uTAhWn06o3CVxUVwhOxwbgr-NGQjNLn6F6DDbPXRF_S5mZ6_1QdRW50Un119C6TWqEFWTdYewqWJKZ
97MbBSDS4hfCjQbzVFaNL5sdiAJn5hK6FZtquBcxzj84joLqMuZo5LGIPE9WWScMzzgfuf8RjRENSipNQdFqJLEeXlA9xI13jx0_iJQxv0OhR4zZUMG0UQ9v
GnTJH-agNGxClDPM4Z9f40Od34bdGIOke0-AiIAXvVPelnDVhNR14fuGcHlNZ53ftCYqP6KIECOMCW94_J8Wxz2OUhwocGYI5_bvL24opLQAC9qlHXJk5Syx
jkmPROwypa3Fwx0Al8o7oQUCr8Az2Q-e_-jugSYhVi99hQBCIO5oiK2WYB6V04Ka8tXYM9SVfyANY_82vf3GR9cwuQz_pUwfw-YjLH5FDmXCjZzBKeHooLJ0
odyA1agxUuqOhAsEz9tQ64w9wNXe3NI7PVgmEvLMvp6DPfcuBaZuR_gzomkV2JefoguirQ8dMfeulSGIBY8h5Icq9Nt5S6MTKpUsulxfgRRrlxwMP-pvGaf4
5hUUsVQTSglrZ8hU_anEuVprShwFPqdTCcYYqne9dGjfw8O8vqAi2bLNUxbfnvdi1WblbYtqS7_VgXcu7Hfzb_u1YyM0jfnwzwJaKx3ptcNwdQodiGpot0p
vSpRf1iYj4Sp806Tz3eVdnuY4UDI6XPHXIGtMal6wqR1oCNepSyAXfZ_J_HOj4KMTnpq1cW0XQQOAT6APHeL3VeMpk94WVInCkHvoc1ZJj3Sf0NATmVOj9XR
y_Z7lnvwdIu7C1J6EFebnxkPB0rWSouKEcJVnNLT8i7Nx2WiXM1JJzpVhD0bgM2VAU0UcnQQmR-DnsKsBUoPXf8NFODqQob5WYr0z-1xj_2TT5KeUBNiuKcQ
8arAeq57FLPWeN9QGun9jakdkAO76dkQYuwew6pWuAJ1prBswvQCmSkzVOGSu644WOSALwqwN4tKoQo008gEMvlpwXoBCZ0Tv5iHBoggsYExdc1dCIGsLAoS
FkhhSg26YVWBLBXs6X2uyqAZXzVBV2-Mn3dXpuyKXehZmPEEjfGQgyrXuo8XSW7hHVyOe-u-n-nJ7WLnGkBMlih8h2JUvyBJ3fXGLn5wXXlKZTRCIsvAjq1Q
D835KWloJNy0_3el1Uew2GgmY8uc2EloKmNDHbFRwQPZori0JBaW8CdZe8pFiiNt90RT837V01vWEN5YLDuDVcsHr77ueiiyu0v3ZZjRVZtUO1XqKa4RlL3IK
utb0twc6ehxbF4OQ9LfKKfS2SXljWyKV9VDqp0HhnJhJyJOwIJ9s_Aq1ue7xntbrs2D9pg17f7d6gCaqkfM5_kd4e8FertkDfx4cfBGhFEF5tL4oIUJy-l6xh
PBDwq0KqEct6MMf9oboQKjEqKnDYSvCcdeQlfd4AHooBXssRQ6uiiQ4ROJBM_MlLaPYsKCBQdp9KRzJNeb3OcDHfVWJ_C949I-YRgpyEBS6-jNJYrFrIJpPG
C2sV4KpB5lWLEZsKKSAFGGp97VPccw3pR_DIsaefC5ZCD-W5PPuVaUvUlgPtQB1oYRseutYXECbiV2VCkByLhvyt11XpK2eviZxZ0XgptmDSiyyGZrjcNF9K-
2taoS4XiDRsCC2OABcCn4TQqi4tiElQ.LWq6zSH5jUdt6V-zdo63qQ

Sequence diagram of the Profile API call


SIGN API

The SeP wishes to request explicit consent from the End-User for some action, for example to obtain consent from end-user or sign document with end-user.

Bank iD has a universal system for request object authorization based on OpenID Financial-grade API. Prior to start of authorization on end user side client MAY obtain end-user access token with grated scope "authorization". Authorization API is secured by using mutual TLS and use of signed and encrypted JWTs on endpoints. See more in Security Considerations.

Authorization usage

Authorization flow is composed of 3 endpoints - /ros , /authorize and /token.

  • Endpoint /ros MUST be called first for registration of request object on authorization server. Request object must be passed directly in request body. Endpoint returns request_uri that is used in other endpoints.

      Notes on interface: 
      - Authorization Bearer is not required for this resource. If it is not present, Bank iD will redirect end user to standard authentication process and after that will perform authorization.
      - If end user is not authenticated use of id_token_hint field is highly recommended, since Bank SHOULD allow skipping initial identification.
      - if end user is not authenticated additional scopes openid and authorization MUST be present
      - If you require to sign document, LoA 3 MUST be sent as acr_value, otherwise Bank MUST return error 
      - If field scope is present and not empty, IdP MUST request consent for new scopes added by SeP prior or after authorization, if end user doesn't consent or authorize IdP SHOULD return error to SeP
      - max_age fields defines how long SeP will wait for authorization process to finish, IdP SHOULD take this value into consideration in setting exp value in response, since SeP could require out-of-bound authorization and such objects SHALL have longer life span than objects that are authorized in single session by end user. Out-of-bound authorization can be recognized by missing access_token
    
  • Endpoint /authorize is called next for initiating authorization on object by end-user. Returns redirect for end-user to authorize the object on Authorization Server. After a client's consent Authorization server redirects end-user on redirect URL provided in request. In case of anonymous ROS, authentication flow is initiated on Bank iD side to authenticate end-user. Interface is straightforward.

  • Standard OIDC endpoint /token is used to get final result of authorization on Authorization server. Returns encrypted and signed JWT with the authorized object in an id_token and subject who had made authorization.

General notes on behavior of authorization

  • Bank iD can initiate authorization flow for anonymous user.
  • Bank can also require for anonymous user to use remote authorization - meaning authorization flow is started without end-user's input and end-user authentication and authorization is executed asynchronously i.e. document signature with insurance agents or with utilities.
  • For purposes of remote authorization Bank iD MAY also provide an id_token (even old and expired) in /ros resource to prevent authentication of client and directly initiate authorization flow.
  • If Bank iD initiates authorization flow for authenticated user i.e. provide access token with granted scope, this end-user will be REQUIRED to use same bank to provide consent with adequate identity method.
  • Sequence diagrams of each flow can be found in documentation for Service Providers.

Authorization server requirements

  • shall support only confidential clients;
  • shall require the request object to contain a max_age claim;
  • shall require explicit consent by the user to authorize the requested scope if it has not been previously authorized;
  • shall return token responses that conform to section 4.1.4 of [RFC6749];
  • shall return the list of granted scopes with the issued access token;
  • shall require the redirect URIs to use the https scheme;

Structured scope

Structured scope is object that represents action or statement for which end user gives consent by using identity proofing with substantial assurance level if required. Bank iD currently provides 3 types of object:

  • SignObject
  • DocumentObject
  • DocumentObjects

SignObject is general structure consisting of key-value fields and SHOULD be used for simple text consents, confirming of advertisements or similar tasks. Since SignObject is very general structure IdP SHOULD evaluate ui_locale in request thoroughly for correct language settings. SeP SHOULD also follow this guide as stated in Bank iD API description and fill labels and values in correct language. IdP SHOULD support minimum of Czech and English mutations. Other languages MAY NOT be supported and these languages SHOULD be converted to Czech or English following rules that Czech and Slovak ui_locales SHOULD be converted as Czech, other languages as English. IdP SHOULD also respect priority given by SeP in request.

DocumentObject in specialized structure for enabling document signature by Bank iD. Both objects requires authorization page by Bank and end user consent for Bank iD to allow it to get user data. See sequence diagram. Appropriate scopes MUST be granted by a bank's IdP to Bank iD. Following are required:

profile.name
profile.titles
profile.birthdate
profile.address
profile.email
profile.legalstatus

These scopes are required for full identification for purposes of correct issue of certificates. Some of these data will be used for creation of certificate itself and some are for auditing purposes of proofing signatory identity.

DocumentObjects is a specialized structure for enabling up to 10 documents signature by Bank iD in bulk. Requirements for authorization page by Bank and end user consent is similar to DocumentObject. On top of single document signature the documents are encapsulated in an envelope, thus following is required:

envelope_name
envelope_hash

Please note that set of these objects can grow. Also, it's possible to combine more objects together in one request henceforth end user can authorize more actions in one bulk.

Auditing

For purposes of legal disputes bank must keep logs of processed authorization by their users. Bank MUST keep mainly log of successful authorizations with basic user identification, authorization data and result. These logs should be kept as long as possible with adherence to GDPR and legal requirements. Bank iD does not prescribe exact log structure but Bank MUST be able to prove or disprove that that exact transaction was or was not authorize by its end user.

Security considerations

Usage of authorization flow is bounded by general security guidelines which are extended in following way

General

Only following cipher suites are allowed for mTLS

TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

Following rules SHALL be followed for both client and authorization server JWS algorithms

SHALL use PS256 or ES256 algorithms;
SHALL not use algorithms that use RSASSA-PKCS1-v1_5 (e.g. RS256);
SHALL not use none;

Authorization server

Following guidelines must be followed by a bank to ensure security.

  • shall authenticate the confidential client at the token endpoint using by mutual TLS for OAuth Client Authentication as specified in section 2 of [MTLS] and private_key_jwt as specified in section 9 of [OIDC];
  • shall require a key of size 256 bits or larger for elliptic curve algorithms used for the client authentication;
  • shall require the redirect URIs to be pre-registered;
  • shall require the redirect_uri parameter in the authorization request;
  • shall require the value of redirect_uri to exactly match one of the pre-registered redirect URIs;
  • shall require user authentication at LoA 3 as defined in [X.1254] or more; LoA2 CAN be used in case of general objects authorization.
  • shall provide opaque non-guessable access tokens with a minimum of 128 bits of entropy where the probability of an attacker guessing the generated token is less than or equal to 2^(-160) as per [RFC6749] section 10.10;
  • shall support [MTLS] as a holder of key mechanism;
  • shall require the response_type values code id_token or code id_token token;
  • may support the request object endpoint as described in section 7;

Bank iD API endpoint overview

The following endpoints are to be made available to the Bank by the Bank iD. Each of these endpoints only contains illustratory examples. Please see the referenced OpenAPI documents for a full authoritative description of these resources.

Logout API

Logout endpoint specified in OpenID.BackChannelLogout.

Exposed by Bank iD. Authoritatively described in bankid_for_idp.yaml. Not authenticated.

POST /back-channel/logout

Request body (Form encoded):

logout_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Notification API

Batch notification endpoint which accepts a list of notification tokens. These are mainly claim update notifications.

Exposed by Bank iD. Authoritatively described in bankid_for_idp.yaml. Not authenticated.

POST /notify

Request body (Form encoded):

notification_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Notification token JWT:

{
  "iss": "https://idp.example.com",
  "iat": "1582797458",
  "jti": "913cc0f7-27ba-40d9-9f4f-8df74ac3596b",
  "events": [
    {
      "type": "claim_updated",
      "original_event_at": "2020-06-15T14:16:32+02:00",
      "sub": "9456b875-62d3-4533-a502-e05d39936f3a",
      "affected_client_ids": [
        "f932ff05-e04c-4cd1-86e4-ce82f1f51efb",
        "3556b875-61d3-5533-a502-e05d3993645a"
      ],
      "affected_claims": [
        "profile.phone_number"
      ]
    }
  ]
}

Sequence diagram of the full notification flow