# 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.

> **New BankID Signing solution**
>
> BankID is moving to a new signing solution. [Read all about it](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/signdoc-intro.md). See the [migration guide](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/signdoc-migration.md).

> **Prerequisites**
>
> - Contact one of our [partners](https://bankid.no/en/company/bankid-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.

> **Tip: Authorization Code Sequence diagram**
>
> This diagram should help you understand the steps involved for integrating BankID authentication.
>
> ```mermaid
> sequenceDiagram
>     actor u as User
>     participant b as Your Web App
>     participant bid as BankID
>
>     u ->>+ b: Request login
>     b ->>+ bid: GET .well-known/openid-configuration
>     bid -->>- b: OIDC Configuration
>     Note right of b: Your App may cache this configuration (at least daily)
>     b ->>- bid: Redirect to the authorization endpoint
>     activate bid
>     bid -->> u: BankID authenticates the user
>     bid ->>- b: Redirect to the redirect URI with the Authorization Code and state
>     activate b
>     b -->> b: Verify state and session
>     b ->>+ bid: POST /token - Exchange Code for Tokens with PKCE
>     bid -->>- b: Access token and ID token
>     b ->>+ bid: GET certs
>     bid -->>- b: JWKS keys
>     Note right of b: Your App may cache this configuration (at least daily)
>     b -> b: Verify tokens
>     b -->>- u: Mark the user as logged in
> ```

### 1. Authorization Request

To successfully implement the [OIDC Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth) in your application, follow the steps below:

1. Retrieve the authorization endpoint URL from the OIDC [Discovery](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md) endpoint. Do **not** hard code this value. Retrieve the config regularly from the OIDC discovery endpoint, as it may change.

2. Generate a `state` value, a random and [non-guessable](https://datatracker.ietf.org/doc/html/rfc6749#section-10.10) string, such as a UUID. The value is used to protecting against
   [cross-site request forgery (CSRF)](https://datatracker.ietf.org/doc/html/rfc6749#section-10.12) attacks.
   It will be sent back to your application in the callback.

3. Generate a `nonce` value, a random and [non-guessable](https://datatracker.ietf.org/doc/html/rfc6749#section-10.10) string
   and store it in a variable called `nonce`. This value ensures the integrity of the ID token and mitigates replay attacks.

4. Generate a `code_verifier`, a random and [non-guessable](https://datatracker.ietf.org/doc/html/rfc6749#section-10.10) 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)](https://datatracker.ietf.org/doc/html/rfc7636).

5. Store the `state`, `nonce` and `code_verifier` value in your application using your preferred session mechanism, so they can be retrieved later.
   These values should be stored together for proper verification.

6. Build the authorization endpoint URI by adding the following parameters:
   - `client_id`: The client ID for your BankID Client.
   - `scope`: Specifies the requested information and resources. In this example we use `openid` and `profile` and get a
     [regular ID token](https://docs.stoe.no/bankid-oidc-provider/core-concepts/id-token.md),
     and the `nnin_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.
   - `state`: Use the previously generated `state` value.
   - `nonce`: Use the previously generated `nonce` value.
   - `code_challenge`: Base64-URL encoded value of the SHA-256 hash of your generated value for `code_verifier`.
     Use the formula `code_challenge = BASE64-ENCODE(SHA256(code_verifier))`. See
     [RFC 7636 §4.2](https://datatracker.ietf.org/doc/html/rfc7636#section-4.2) for more details.
   - `code_challenge_method=S256`: Specify the code challenge method as SHA-256.
   - (Optional) `acr_values=urn:bankid:bid` to specify that the user should be authenticated using BankID on Level of Assurance High. Use `urn:bankid:bis` for BankID with biometrics. [Read more about using ACR values](https://docs.stoe.no/bankid-oidc-provider/core-concepts/identity-providers.md).
   - (Optional) `api_version=3` to specify the API version you want to opt-in to. [Read more about API Versions](https://docs.stoe.no/bankid-oidc-provider/api-versions.md).

For more information about the parameters available, read [here](https://docs.stoe.no/bankid-oidc-provider/api/authorize.md).

> **Do you want to send NNIN as login hint? See [here](https://docs.stoe.no/bankid-oidc-provider/core-concepts/login-hint.md)**

Here is an example of a valid authorization request URI:

```properties
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 will redirect the user back to the callback URI specified
in the `redirect_uri` parameter. See [RFC 6749 §4.1.2](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2) for more information about the authorization response.

> **Tip: Flow chart for Token exchange**
>
> This diagram shows the processing flow during Token Exchange
>
> ```mermaid
> 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:

1. Retrieve the `code` parameter from the callback request.

2. 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 client.
   - `client_secret`: The client secret for your BankID client.
   - `redirect_uri`: The same callback URI used in the authorization request.
   - `code`: The authorization code received in the callback.
   - `code_verifier`: When PKCE is used in the authorization request, include the `code_verifier` used.

3. Obtain the `token_endpoint` from the [Discovery](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md) endpoint.

4. 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 the `client_id` and `client_secret` as part of the basic authentication header in the request.
   See [RFC 6749 §4.1.3](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3) and [RFC 6749 §2.3.1](https://datatracker.ietf.org/doc/html/rfc6749#section-2.3)
   for more details on sending the request.

**Example token request:**

```properties
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](https://oauth.net/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](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) 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)](https://datatracker.ietf.org/doc/html/rfc7517) document.
  The URI for the JWKS document can be found under the `jwks_uri` key in the BankID configuration you received in [Discovery](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md) endpoint. You must also verify that the algorithm
  used is found in the configuration under `id_token_signing_alg_values_supported`.
- Verify the certificate chain of the signing key used. See [guide](https://docs.stoe.no/bankid-oidc-provider/advanced-topics/verify-token.md).

### 2. Verify the token claims

- Verify that the `nonce` claim in the received tokens corresponds to the `nonce` value belonging to the same session (i.e. the `nonce` associated with the state).
- Verify that the `acr` claim includes the expected Level of Assurance. This indicates 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](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation).

## Next steps

- Our [versioned API](https://docs.stoe.no/bankid-oidc-provider/api-versions.md) are continuously being updated with new changes and features.
- The [list of error codes](https://docs.stoe.no/bankid-oidc-provider/resources/error-codes.md) displayed to the end-user is useful for troubleshooting.
- The [Deprecations list](https://docs.stoe.no/bankid-oidc-provider/resources/deprecations.md) is also interesting to keep an eye on.
