# OpenID Connect Authorization Code flow for upfront permissions

When using the OIDC authorization code flow for authenticating payments, cards or accounts the permission needs to be registered upfront.
This requires you to go through some extra steps before you can start with the OIDC authorization code flow.

## Steps

\[TOC]

## 1. Register a client with BankID OIDC

If you don't have a client registered with [BankID OIDC](https://docs.stoe.no/bankid-oidc-provider/introduction.md)
yet, you'll need to register one. Follow the instructions
[here](https://docs.stoe.no/bankid-oidc-provider/resources/provisioning.md) to register your
application and obtain the necessary [client credentials](https://tools.ietf.org/html/rfc6749#section-1.3.4) (`client_id` and `client_secret`).
You will need two clients, one for the test environment and one for the production environment.

Ensure that your client has the `permissions/client` scope available.

For testing the CIBA flow in the test environment, you will need to register a test user and get access to the BankID preprod app.
Detailed instructions on how to do this can be found in the [testing document](https://docs.stoe.no/bankid-with-biometrics/testing.md).

## 2. Get the BankID OpenID Connect Configuration

To ensure seamless integration with BankID OIDC and avoid hardcoding specific endpoints in you application, follow these
steps to dynamically fetch the [OpenID Connect configuration](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig):

1. Determine the appropriate configuration URL based on the environment:

   | Environment                       | Url                                                                                   |
   | --------------------------------- | ------------------------------------------------------------------------------------- |
   | Production                        | <https://auth.bankid.no/auth/realms/prod/.well-known/openid-configuration>            |
   | Current (public test environment) | <https://auth.current.bankid.no/auth/realms/current/.well-known/openid-configuration> |

2. Send an HTTP GET request to the respective configuration URL using your preferred programming language or API tool.

3. Capture the response which will contain a JSON document with the configuration. By dynamically fetching the OIDC configuration, your application remains flexible,
   allowing for future changes or updates to the endpoints without requiring modifications to your code.

4. To enhance the reliability and performance of your integration, we strongly advise implementing response caching for the OIDC configuration.

   > **Example response from Current (relevant fields only)**
   >
   > ```json
   > {
   >   ...
   >   "token_endpoint": "https://auth.current.bankid.no/auth/realms/current/protocol/openid-connect/token",
   >   ...
   > }
   > ```

   _This is a sample response. The actual response may differ._

## 3. Get an access token from BankID OIDC

To obtain an access token from OIDC, follow these steps:

1. Retrieve the token endpoint URL `token_endpoint` dynamically from the OIDC configuration.

2. Call the token endpoint URL with your client credentials.

   You can find more detailed information about acquiring access tokens in the [BankID OIDC documentation](https://docs.stoe.no/bankid-oidc-provider/api/token.md).

3. In the scope field, include the following: `permissions/client`. This field specifies the scope of access granted to the token.

4. To enhance the reliability and performance of your integration, we strongly advise implementing response caching for the access token. For example based on the expires_in property in the token response.

Here's an example of a valid request in the `current` environment
(replace placeholder in Authorization header with your own credentials):

```http
POST /auth/realms/current/protocol/openid-connect/token HTTP/1.1
Host: auth.current.bankid.no
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <Base64-encoded client id:client secret>

grant_type=client_credentials&scope=permissions%2Fclient
```

## 4. Get the BankID with biometrics OIDC configuration

To ensure seamless integration and avoid hardcoding specific endpoints in you application, follow these
steps to dynamically fetch the [OpenID Connect configuration](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig):

1. Determine the appropriate configuration URL based on the environment:

   | Environment                       | Url                                                                        |
   | --------------------------------- | -------------------------------------------------------------------------- |
   | Production                        | <https://app.bankid.no/.well-known/openid-configuration>                   |
   | Current (public test environment) | <https://current.aletheia-test.idtech.no/.well-known/openid-configuration> |

2. Send an HTTP GET request to the respective configuration URL using your preferred programming language or API tool.

3. Capture the response which will contain a JSON document with the configuration. By dynamically fetching the OIDC configuration, your application remains flexible,
   allowing for future changes or updates to the endpoints without requiring modifications to your code.

4. To enhance the reliability and performance of your integration, we strongly advise implementing response caching for
   the OIDC configuration.

## 5. Register the permission

> **Alternative: Rich Authorization Requests**
>
> Instead of registering a permission via the Permissions API as described below, you can use [Rich Authorization Requests (RAR)](https://docs.stoe.no/bankid-oidc-provider/advanced-topics/authorization-details.md#authorization-details) to include the permission statement directly in a [Pushed Authorization Request (PAR)](https://docs.stoe.no/bankid-oidc-provider/api/par.md) to the BankID OIDC Provider. When using RAR, you can skip steps 3–6 and go straight to step 7. See the [RAR details below](https://docs.stoe.no/bankid-with-biometrics/flows/code-flow-for-payments.md#alternative-rich-authorization-requests) for more information.

This is done by constructing a _permission statement_ containing the payment amount and creditor name, encoding this
permission statement using URL safe b64 encoding, and sending a POST request to the [permissions](https://docs.stoe.no/bankid-with-biometrics/apis/permissions-api.md)
endpoint.

First, create the permission statement and encode it as an URL Safe Base 64 string.

```javascript
const permissionStatement = {
    "nonce": "dW5pcXVlIHZhbHVl", // Must be unique
    "id": "YmFza2V0IGlk", // Your reference
    "payments": [
        {
            "paymentId": "cGF5bWVudCBpZA", // Your reference
            "amount": "123.45",
            "currency": "NOK",
            "creditorName": "Scrooge McDuck"
        }
    ]
}

// Example implementation of a b64 URL Safe Encoder
function b64URLSafeEncode(stringData) {
    return btoa(stringData)
        .replace(/\+/g, "-")
        .replace(/\//g, "_")
        .replace(/=/g, "");
}

b64URLSafeEncode(
    JSON.stringify(
        permissionStatement
    )
);
// -> "eyJub25jZSI6ImRXNXBjWFZsSUhaaGJIVmwiLCJpZCI6IlltRnphMlYwSUdsayIsInBheW1lbnRzIjpbeyJwYXltZW50SWQiOiJjR0Y1YldWdWRDQnBaQSIsImFtb3VudCI6IjEyMy40NSIsImN1cnJlbmN5IjoiTk9LIiwiY3JlZGl0b3JOYW1lIjoiU2Nyb29nZSBNY0R1Y2sifV19"
```

Notes:

- The `nonce` must be a unique value for each permission you register.
- Use id (basket ID) and paymentId as references to the payment(s) in your systems. These will not be shown to the end
  user.
- `amount` is a decimal amount in string and must use the dot as the decimal separator.

> **Hint**
>
> Authenticating from an iOS app? Using `app_callback_uri` can improve the user experience by automatically redirecting
> the user back to your app after the BankID with biometrics authentication is completed. See the [iOS section](https://docs.stoe.no/bankid-with-biometrics/advanced-topics/native-applications.md#bringing-the-user-back-to-your-ios-app) for more information.

You are now ready to send a POST request to the [permissions](https://docs.stoe.no/bankid-with-biometrics/apis/permissions-api.md)
endpoint, passing the access token received in first step as a bearer token and a permission equaling the URL safe b64
encoding over the permission statement object.

```http
POST /permissions/v1/ HTTP/1.1
Host: api.current.aletheia-test.idtech.no
Content-Type: application/json
Authorization: Bearer <access token from step 1>

{
  "type": "payment.v1",
  "iat": 1617091752,
  "exp": 1617092652,
  "permission": < URL safe b64 encoded permission statement >
}
```

Notes:

- `iat` and `exp` are timestamps in seconds since the UNIX epoch. `iat` can be at most 1 minute into the past. exp sets
  the maximum time by which the permission must be granted, and should normally be set just a few minutes into the
  future.

On a successful request, you will get a response body back containing a permission ID, permission token:

```json
{
  "id": "1.BY.MEKrA-00GVtmvWOCDYQko_fSg93LO5n2rBnlj-X4MQg.BiDEl_CgfakqahcXjLrFet_GGpEkR_W8D-RK4hORBO0",
  "permissionToken": "eyJhbGciOiJIUzI1NiIsImtpZCI6IjB5Z3hDX3UzQlpPWXlKZ0Y3eDJ0eWtQaTRCTml2cG9KMDBmYjFzTGliUVUiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2MTcwOTU3NDQsImlhdCI6MTYxNzA5MjE0NCwicyI6IjA6LTEjOTIzIiwicCI6IkJpREVsX0NnZmFrcWFoY1hqTHJGZXRfR0dwRWtSX1c4RC1SSzRoT1JCTzAiLCJuYmYiOjE2MTcwOTIxNDh9.39GWvNjNMSKKhKOF4t4HcDnZGNJmLmPT3f612z1VKko"
}
```

## 6. Pass permission to redirect flow

Pass the `permissionToken` as an additional query parameter `permission_token`
when you start the BankID OIDC flow.

## 7. Execute the OIDC authorization code flow

At this point you can continue with the steps in the [OIDC authorization code flow](https://docs.stoe.no/bankid-with-biometrics/flows/code.md).

## 8. Get the signed permission

After the user has completed the BankID OIDC flow, you can get the signed permission.

To get the signed permission you can send in a GET request to the `permissionId/grant` endpoint. The `permissionId` you use is the one that you
got from your [permissions](https://docs.stoe.no/bankid-with-biometrics/apis/permissions-api.md) POST request. Be aware that it can return a 404 error code
(permission not yet granted) but as mentioned in the api specification you can set up a polling request on the `permissionId/grant`
endpoint until your initial permission has been signed.

If your permission has been successfully granted you will receive this response:

```json
{
  "gv": 1,
  "pt": "string",
  "type": "string",
  "rpId": "bankid-app",
  "sv": "2020-10-30@deadbeef",
  "iat": 1800000000,
  "iss": "string",
  "nonce": "string",
  "proofKeyId": "string",
  "sub": "nnin:010112345",
  "permissionId": "string",
  "digest": "string"
}
```

The grant is a JWT token that can be validated as follows:

- In the BankID with biometrics OIDC configuration (as mentioned [here](https://docs.stoe.no/bankid-with-biometrics/flows/code-flow-for-payments.md#4-get-the-bankid-with-biometrics-oidc-configuration)) get the Grant JWK set from the URI pointed to by the `jwks_uri_grants` property in this document.
- Check that the token is signed by one of the keys in the Grant JWK set.
- Check that the `nonce` claim inside the token payload is equal to the `nonce` in the permission statement created in [step 5](https://docs.stoe.no/bankid-with-biometrics/flows/code-flow-for-payments.md#5-register-the-permission).

## Alternative: Rich Authorization Requests

Instead of registering a permission upfront via the Permissions API (steps 3–6), you can use [Rich Authorization Requests (RAR)](https://docs.stoe.no/bankid-oidc-provider/advanced-topics/authorization-details.md#authorization-details) to include the permission statement directly in a [Pushed Authorization Request (PAR)](https://docs.stoe.no/bankid-oidc-provider/api/par.md) to the BankID OIDC Provider. The permission statement uses the same Base64url-encoded JSON format as described in [step 5](https://docs.stoe.no/bankid-with-biometrics/flows/code-flow-for-payments.md#5-register-the-permission).

See the [BankID OIDC Provider authorization_details documentation](https://docs.stoe.no/bankid-oidc-provider/advanced-topics/authorization-details.md#authorization-details) for details on how to use RAR.
