Getting started¶
This guide will help you get started with integrating BankID in your application.
OpenID Connect is a protocol for authentication that builds on the OAuth 2.0 authorization framework. This section describes how to integrate BankID in your application using authorization code flow with PKCE.
sequenceDiagram
actor u as User
participant b as Your Web App
participant bid as BankID OIDC Provider
u ->>+ b: Request login
b ->>+ bid: GET /auth/realms/.../.well-known/openid-configuration
bid -->>- b: OIDC Configuration
Note right of b: Your App may cache this configuration (at least daily)
b -->>- u: Redirect to the authorization endpoint
u ->>+ bid: Initiate BankID authentication flow
break Authentication failed
bid -->> u: Redirect to the redirect URI with the error
end
bid -> bid: BankID authenticates the user
bid -->>- u: Redirect to the redirect URI with the Authorization Code
u ->>+ b: Invoke callback endpoint
b ->>+ bid: POST /token - Exchange Code for Tokens
bid -->>- b: Access token and ID token
Note right of b: Your App now gets keys (on demand)<br/> from the JWKS endpoint to verify the tokens
b ->>+ bid: GET /auth/realms/.../protocol/openid-connect/certs
bid -->>- b: JWKS keys
b -> b: Verify tokens
b -->>- u: Store user session and mark the user as logged in
Prerequisites
- Contact one of our partners in order to acquire necessary client credentials (i.e. client_id and client_secret) to our test environment.
- Make sure the application that integrates BankID has server side components as it is required when using authorization code flow with PKCE.
1. Authorization Request¶
To successfully implement the OIDC Authorization Code Flow in your application, follow the steps below:
The flow is specified RFC 6749 §4.1.
-
Retrieve the authorization endpoint URL from the OIDC Discovery endpoint. Do not hard code this value. Retrieve the config regularly from the OIDC discovery endpoint, as it may change.
-
Generate a random and non-guessable string, such as a UUID, and store it in a variable called
state
. The value is used to protecting against cross-site request forgery (CSRF) attacks. It will be sent back to your application in the callback. -
Generate a cryptographically random and non-guessable string and store it in a variable called
nonce
. This value ensures the integrity of the ID token and mitigates replay attacks. -
Store the
state
andnonce
value in your application using your preferred session mechanism, so they can be retrieved later. These values should be stored together for proper verification. -
(Optional, but HIGHLY recommended) Generate a cryptographically random and non-guessable string and store it in a variable called
code_verifier
. This value is used to mitigate against authorization code interception attacks through the use of Proof Key for Code Exchange (PKCE). -
Build the authorization endpoint URI by adding the following parameters:
client_id
: The client ID for your BankID OIDC client.scope
: Specifies the requested information and resources. In this example we useopenid
andprofile
and get a regular ID token, and thennin_altsub
scope to get the Norwegian national identity number as a claim in the token.response_type=code
: Indicates the usage of the Authorization Code Flow.redirect_uri
: The callback URI on your server where you want to receive the callback from BankID OIDC.state
: Use the previously generatedstate
value.nonce
: Use the previously generatenonce
value.code_challenge
: Base64-URL encoded value of the SHA-256 hash of your generated value forcode_verifier
. Use the formulacode_challenge = BASE64-ENCODE(SHA256(code_verifier))
. See RFC 7636 §4.2 for more details.code_challenge_method=S256
: Specify the code challenge method as SHA-256.- (Optional)
login_hint=:<nnin>
: Optionally supply the user's national identity number (nnin) to pre-fill the BankID login form. - (Optional)
acr_values=urn:bankid:bid
to specify that the user should be authenticated using BankID on Level of Assurance High. Useurn:bankid:bis
for BankID with biometrics. Read more about usingacr_values
here. - (Optional)
api_version=3
to specify the API version you want to opt-in to. Read more about availableapi_version
and it's effects here.
For more information about the parameters available, read here.
Here is an example of a valid authorization request URI:
GET https://auth.current.bankid.no/auth/realms/current/precheck/auth
?client_id=your-client-id
&scope=openid+profile nnin_altsub
&response_type=code
&redirect_uri=https://localhost:3000/api/auth/callback/bid
&state=4eJYruvMul0SOs5GGuJTjERgtVIovp7PFZt3Qw4EC94
&nonce=6ZlR7ik_7YI740Ayt8DmMV75IoNfI2jLflVDfYexMQc
&code_challenge=rMU4NcLC3_O_tsTZ3gQE1ONoXD6OMZph_2zRuobajhQ
&code_challenge_method=S256
By initializing the authorization code flow with the constructed URI, you will redirect the user to the authorization endpoint. There, the user will authenticate with BankID.
2. Handle callback and exchange the auth code for tokens¶
After the user has authenticated, BankID OIDC will redirect the user back to the callback URI specified
in the redirect_uri
parameter. See RFC 6749 §4.1.2 for more information about the authorization response.
graph TD
classDef error stroke: #ef4444
A[Callback Received] --> B[Verify State]
B -->|Mismatch| C[Authentication failed]:::error
B -->|Match| D[Check for error]
D -->|Present| C
D -->|Not present| E[Exchange code for token]
E --> F[Verify the token]
F -->|Fail| C
F -->|OK| G[Authentication succeeded]
Your application is responsible for performing the token exchange and verification:
-
Retrieve the
code
parameter from the callback request. -
Build the token request by including the following parameters:
grant_type=authorization_code
: Indicates the usage of the Authorization Code Flow.client_id
: The client ID for your BankID OIDC client.client_secret
: The client secret for your BankID OIDC client.redirect_uri
: The same callback URI used in the authorization request.code
: The authorization code received in the callback.code_verifier
: If PKCE was used in the authorization request, include thecode_verifier
used.
- Obtain the
token_endpoint
from the Discovery endpoint. - Send a POST request to the token endpoint with the constructed parameters. The parameters should be encoded as
application/x-www-form-urlencoded
. Remember to include theclient_id
andclient_secret
as part of the basic authentication header in the request. See RFC 6749 §4.1.3 and RFC 6749 §2.3.1 for more details on sending the request.
Example token request:
POST https://auth.current.bankid.no/auth/realms/current/protocol/openid-connect/token
?grant_type=authorization_code
&redirect_uri=https://localhost:3000/api/auth/callback/bid
&code=AUTHORIZATION_CODE
&code_verifier=code_verifier
Authorization: Basic YmlvZXhhbXBsZS1iYW5raWQtY3VycmVudDpzZWNyZXQ=
The example is formatted for readability.
Note
For a more secure and FAPI compliant implementation, you can use the client_assertion
and client_assertion_type
parameters instead of the client_id
and client_secret
parameters.
Read about private_key_jwt here. Contact us for public key registration.
3. Validate the ID token¶
To ensure the authenticity and integrity of the received ID token, you must perform the following steps:
1. Verify the signature¶
- Verify that the token is signed by a key from the JWKS (JSON Web Key Set) document.
The URI for the JWKS document can be found under the
jwks_uri
key in the BankID OIDC configuration you retrieved in Discovery endpoint. You must also verify that the algorithm used is found in the BankID OIDC configuration underid_token_signing_alg_values_supported
. - Verify the certificate chain of the signing key used. See guide.
2. Verify the token claims¶
- Verify that the
nonce
claim in the received tokens corresponds to thenonce
value belonging to the same session (i.e. thenonce
associated with the state). - Verify that the
acr
claim include the expected Level of Assurance. This indicating the desired level of trust in the authentication process. - We recommend verifying these additional properties:
iss
(issuer) - The issuer of the token must match the issuer in the BankID with biometrics OIDC configuration.aud
(audience) - The audience of the token must match your client ID.exp
(expiration time) - The token must not be expired.iat
(issued at) - The token must not be issued in the future.
Further information on how to validate the ID token can be found in the OpenID Connect Core specification.
Next steps¶
- Our versioned API are continuously being updated with new changes and features. See API Versions and Changelog.
- The list of error codes displayed to the end-user is useful for troubleshooting.
- The Deprecations list is also interesting to keep an eye on.