# Migration Guide

The BankID Server signing and signing using Signdoc over OpenID Connect (OIDC) is being migrated to a new BankID Signing solution by the end of 2025 - as previously outlined in several letters.

This new BankID Signing solution offers a modern user experience with Qualified Person signing, including Qualified Timestamping (QTSA).

This is a **breaking change** to all previous signing integrations with BankID, including BankID Server and existing OIDC integrations.

**Please read this migration guide carefully.**

> **Special notice for those implementing SEID-SDO signing**
>
> The SEID-SDO format is **not supported** in the new BankID Signing solution, except in [B2B](https://docs.stoe.no/bankid-esign-provider/apis/b2b/v0/B2B-Bankid-Signer.md) - for now.
> We recommend migrating to [PAdES signing](https://docs.stoe.no/bankid-esign-provider/apis/signdoc-intro.md) for documents, [CSC Signing API](https://docs.stoe.no/bankid-esign-provider/apis/csc/CSC.md), or [B2B](https://docs.stoe.no/bankid-esign-provider/apis/b2b/v0/B2B-Bankid-Signer.md) for hashes or [Permissions API](https://docs.stoe.no/bankid-with-biometrics/permission-types.md) for payment related signing.

## Breaking changes

### Linking BankID user with new BankID Signing certificate

In the BankID Server and OIDC Signdoc solutions, the end-user could be identified using BankID Personal Identifier (`PID`) or the `bankid_altsub` claim in the ID Token.  These identifiers are available in the qualified certificate under a custom OID extension `2.16.578.1.61.2.3` when the end-user authenticates with BankID.

In the new BankID Signing solution, the end-user identity must be extracted from the certificate that was used for signing. Please refer to the [Certificate Profiles](https://docs.stoe.no/bankid-esign-provider/pki/certificate-profiles.md) documentation for details on what fields and extensions are available in the end-user certificate.

**Note:** Norwegian National Identity Number (NNIN) / fødselsnummer are only made available when using the scope `esign/nnin` and the end-user consents to sharing. The NNIN is then included as an additional extension in the certificate under the OID `2.16.578.1.61.2.4`.

### Comparison table

| Topic                         | Legacy (Signdoc OIDC / BankID Server)                                                                            | New Signing solution                                                                                                             | Action Required                                                                                                                     |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Base API URL                  | signdoc-baseurl from [Discovery](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md) endpoint | esign-baseurl from [Discovery](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md) endpoint                   | Update configuration                                                                                                                |
| scope for Client Credentials  | `signdoc/read_write`                                                                                             | `esign`                                                                                                                          | Change scope                                                                                                                        |
| Flow type (PAdES)             | OIDC Authorization Code + Token exchange                                                                         | Direct redirect + callback URI (no OIDC token exchange)                                                                          | Remove token exchange                                                                                                               |
| Signer identity               | ID Token claims                                                                                                  | Extract from certificates in signatures / Upcoming signer info data                                                              | Parse certificate / Signer info                                                                                                     |
| XML / SEID-SDO / text APIs    | Supported                                                                                                        | Not supported                                                                                                                    | Migrate to PAdES / CSC / Permissions                                                                                                |
| Merchant certificates         | Long-lived merchant certificates — end-users see the merchant/company name in the BankID app                     | Short-lived session certs issued automatically — end-users see "BankID Signering" in the BankID app instead of the merchant name | no technical action required                                                                                                        |
| Trust anchor updates          | Existing BankID PKI                                                                                              | [New PKI trust anchors](https://docs.stoe.no/bankid-esign-provider/pki.md) + EU Trust List auto-fetch                            | Update truststore                                                                                                                   |
| Visual seal positioning       | Auto or default                                                                                                  | Not automatic. Use default (0,0) or set position.                                                                                | Set parameter dynamically. See [field documentation](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/v1/v1-pades-fields.md) |
| iFrame embedding              | Possible                                                                                                         | Not supported                                                                                                                    | Redesign integration                                                                                                                |
| Signature level               | AdES-LT/T                                                                                                        | AdES-LTA ( with `extendToLta`)                                                                                                   | Validate archival policy                                                                                                            |
| Identity prefill (login_hint) | Supported                                                                                                        | Not yet (roadmap)                                                                                                                | Remove usage                                                                                                                        |
| Merchant only signing         | Supported                                                                                                        | Supported. See [B2B signing](https://docs.stoe.no/bankid-esign-provider/apis/b2b/v0/B2B-Bankid-Signer.md)                        | Migrate to B2B                                                                                                                      |

### Convert API

- New Base URL for API calls. See `esign-baseurl` in [OpenID Configuration](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md)

- Changes to error messages from the Convert API.

### SEID-SDO signing

- Not supported - migrate to [PAdES signing](https://docs.stoe.no/bankid-esign-provider/apis/signdoc-intro.md) for documents, [CSC Signing API](https://docs.stoe.no/bankid-esign-provider/apis/csc/CSC.md) for hashes or [Permissions API](https://docs.stoe.no/bankid-with-biometrics/permission-types.md) for payment related signing.

### Text signing

- Not supported.
- For Payment confirmation, migrate to [Permissions API](https://docs.stoe.no/bankid-with-biometrics/permission-types.md).
- For other scenarios, see available [Permission types](https://docs.stoe.no/bankid-with-biometrics/permission-types.md).

### Simple text signing using sign_txt parameter

- Deprecated - moving to [Permissions](https://docs.stoe.no/bankid-with-biometrics/permission-types.md) based solution with [PAR](https://docs.stoe.no/bankid-oidc-provider/api/par.md). More info will come soon.

### XML signing

- Not supported.
- Migrate to [PAdES signing](https://docs.stoe.no/bankid-esign-provider/apis/signdoc-intro.md) for documents, [CSC Signing API](https://docs.stoe.no/bankid-esign-provider/apis/csc/CSC.md) for hashes or [Permissions API](https://docs.stoe.no/bankid-with-biometrics/permission-types.md) for payment related signing or other types (more info coming).

### PAdES signing

- New Base URL for API calls. See `esign-baseurl` in [OpenID Configuration](https://docs.stoe.no/bankid-oidc-provider/api/openid-configuration.md)

- New Certificate trust. Trust anchors will need to be updated.
  Merchants would need to add the [new PKI](https://docs.stoe.no/bankid-esign-provider/pki.md) to their truststore. This process is automated for software (like Adobe Reader) that routinely fetches trust anchors from EU Trust List, but systems would most likely need manual updating.

- No more signatures with BankID merchant certificates.
  Instead short lived certificates are generated per session.
  **End-user visible change:** In the BankID app, users will no longer see the merchant/company name during signing. They will instead see **"BankID Signering"**. This is intentional — session certificates issued by the BankID Signing service are used rather than long-lived merchant certificates. No technical action is required, but merchants should inform their end-users about this change to avoid confusion.

- There is no SEID profile.
  Meaning no NNIN via OCSP, but NNIN in cert. Minor changes to certificate contents (subject) etc. See [Certificate Profiles](https://docs.stoe.no/bankid-esign-provider/pki/certificate-profiles.md) for details.

- We now deliver AdES-LTA when `extendToLTA` parameter in a sign order is used, compared to AdES-LT/T that is currently provided

- The service does not auto-adjust the positioning of the visual signature seal. Default position is 0,0.
  The parameter `endUserSealPos` can be used when submitting a sign order to set position.

- No iframe support

- `skipConfirmation` parameter is no longer supported.

- The flow is no longer a OpenID Connect Authorization Code flow request.

- There is no Token Request or ID Token with signer info after signing. Get signer info from the certificate data in the signed documents. NOTE: We are planning to add support for dedicated signer info in Signing API, but this does not replace the need to parse certificate and validate the signature.

- Login Hint to prefill NNIN is currently not supported, but support is on the roadmap.

- Changes to error messages from the Signing API.

### Merchant only signing using BankID Server

- BankID Server SDK can no longer be used, this feature is offered in new [B2B](https://docs.stoe.no/bankid-esign-provider/apis/b2b/v0/B2B-Bankid-Signer.md) solution.

- Requires DPOP and [Private Key JWT](https://docs.stoe.no/bankid-oidc-provider/core-concepts/private-key-jwt.md)

- Supports SEID-SDO.

## Migrating

### Convert API

1. Change Base URL in API calls from `signdoc-baseurl` to `esign-baseurl`.
2. (Recommended) change scope from `signdoc/read_write` to `esign` for Client Credentials Access Token.
3. (Recommended) check if the implementation depends on error messages from the Convert API - those change with the new solution.

See API documentation under [Convert API v1](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/v1/convert-api.md).

### PAdES signing

We recommend to move directly to PAdES Signing API [v1](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/v1/pades-api.md) to be future-proof. This streamlined API-version omits the legacy parameters and adds several new features such as:

- Allowing to pass a callback URL to control where the end-user ends up after signing. Otherwise the user will close the window after signing.
- The option to add an LTA timestamp to the signed document.
- Option to receive signer info together with the signed documents.

#### From BankID Server

If you are migrating from BankID Server, you are no longer depending on the BankID Server SDK. Instead, you implement the flow described in the [PAdES documentation](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/signdoc-intro.md).

#### From Signdoc over OpenID Connect

If you are migrating from Signdoc and the OpenID Connect integration, you need to make some minor changes to the flow and API integration.

The full documentation is available [here](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/signdoc-intro.md), but we have outlined below some of the steps you must take:

1. When asking for Client Credentials access token to perform API requests, change scope from `signdoc/read_write` to `esign`.
2. Change Base URL in API calls from `signdoc-baseurl` to `esign-baseurl`.
3. Make existing call to create Sign Order to the new [v1](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/v1/pades-api.md) API endpoint (as before) with additional parameters:
   - (Optional) Add `signProperties.redirectUrl` with your callback URL for a redirect after signing. You may add your state information to `redirectUrl` here, e.g. `https://example.org/callback?state=1234`. The `sign_id` will also be added automatically.
4. Take `sign_id` from the result from (3), and redirect end-user to new Signing UI (What You See Is What You Sign) endpoint.
   - Test: `https://web.preprod.esign-stoetest.cloud/[locale]/${sign_id}`
   - Prod: `https://web.esign-stoe.cloud/[locale]/${sign_id}`
   - NOTE: Supported locale prefixes are `en` (English), `nb` (Norwegian Bokmål), and `nn` (Norwegian Nynorsk).
   - **NOTE: This is not an OIDC Authorization Code flow.**
5. The end user signs the document(s).
6. (Optional) You can check the status of the signing process using the Signing API.
7. After signing, the end-user will be redirected to the callback URL registered in (3).
   - Remove Token Exchange call as this is not an OIDC Authorization Code flow.
   - **NOTE: This means there are no ID token identifying the end-user. See next step.**
8. Keep existing call to download Signing results from Signing API. The signing results contains the signed documents. The signer identity can be extracted from the certificate in the signed document(s) and validated.

Other things to keep in mind:

- Check the [API documentation](https://docs.stoe.no/bankid-esign-provider/apis/signdoc/v1/pades-api.md) which results the implementation expects from the API - some legacy parameters are still accepted but ignored and some no longer supported result elements are returned empty.
- Check if your implementation depends on error messages from the API - those may change with the new solution.

#### Sequence diagram

```mermaid
sequenceDiagram
    actor u as User
    participant Merchant as Your Web App
    participant BankID as BankID OIDC
    participant MBE as Signing API
    participant FE as Signing UI
    u ->> Merchant: Request signing
    Note right of Merchant: (1) Client requests access token
    Merchant->>BankID: POST /token with `esign` scope
    BankID-->>Merchant: Access token
    Note right of Merchant: (2) Client creates sign order
    Merchant-->>MBE: POST /signdoc/pades with parameters and document(s) data
    MBE-->>Merchant: Sign ID
    Note right of Merchant: (3) Client redirects user to WYSIWYS UI with sign_id
    Merchant->>FE: e.g. https://web.preprod.esign-stoetest.cloud/<SIGN_ID>
    FE-->> Merchant: Redirect to redirect url (optional, if parameter set)
    Note right of Merchant: (8) Client downloads signed document(s)
    Merchant->>MBE: DELETE /signdoc/pades?sign_id={sign_id}
    MBE-->>Merchant: Signing results and document(s)
    Merchant->>u: Signing complete
```

### Checklist

- Obtain new or updated client credentials authorized for scope `esign`.
- Update base URLs in configuration (`esign-baseurl`).
- Remove legacy OIDC Authorization Code + Token Exchange step.
- Implement new sign order creation with `endUserSealPos` and optional `redirectUrl`.
- Implement WYSIWYS redirect.
- Parse session certificate for signer identity (until signer info field is released).
- Update truststore with new BankID E-sign PKI anchors.
- Verify handling of new error codes and map legacy fallbacks.
- Validate that iframe embedding is removed and UX flows are full-page redirect or popup.
- Add archival validation to confirm AdES-LTA presence.
- Inform end-users that the BankID app will display **"BankID Signering"** instead of the merchant/company name during signing. This is expected behaviour with the new session certificate model.
