Signed JWTs (JWS) are crucial to the OpenID Connect specification in order to ensure the authenticity and integrity of data exchanged between parties.
Encrypted JWTs (JWE) are also used to encrypt sensitive data when applicable. Cryptographic keys used for this purpose are published in the JWKs endpoint as JWKs. Note that these keys may change over time.
When integrating BankID over OpenID Connect you must always validate Tokens that are issued. You should also strongly consider encrypting sensitive data using encrypted request objects.
Topics
Validation of Signed Tokens
Following well established OpenID Connect standards, BankID will sign all Tokens issued:
You must validate JWT signatures and ensure that the signing key certificate was issued by the officially published root certificate.
Keys used for signing are all marked with "use": "sig"
.
Steps to validate a signed JWT Token
The steps required to securely validate a JWS Token (like ID Token):
- Extract the key information from the JWS Token header:
kid
,alg
- Retrieve all JWK entries that BankID exposes from the JWKs endpoint.
- Keys used for signing can be filtered by the
use
attribute on each JWK. This value should besig
. - Find the key used to sign the JWS Token by matching the
kid
,alg
from (1) with the JWK entries. - Extract the public key and certificate chain (x5c) from the JWK entry.
- Validate the origin of the key by verifying it's complete certificate chain (x5c) with our published root certificate.
- Validate the JWS token using the key.
Note: Using a secure and community provided library to validate JWS tokens is highly recommended.
Signed Authorization Requests
BankID OIDC can support signing incoming Authorization Requests:
- request authorize parameter
- private_key_jwt client_assertion object
To support this, a jwks_uri must be registered for the given merchant (OIDC Client), so BankID can retrieve validation keys.
Contact us for more information.
Encrypted Authorization Requests
BankID supports encryption of incoming Authorization Requests through:
- request authorize parameter
- login_hint encryption (deprecated)
This can be useful in order to ensure personal information is not leaked in the browser history or URL (for example through login_hint).
The login_hint encryption is deprecated as it is being replaced by the encrypted request parameter.
Keys used for encryption in JWKs are all marked with "use": "enc"
.
Encrypted request parameter (recommended)
Supported key encryption algorithms | Supported content encryption algorithms |
---|---|
RSA1_5 RSA-OAEP RSA-OAEP-256 | A256GCM A192GCM A128GCM A128CBC-HS256 A192CBC-HS384 A256CBC-HS512 |
Steps to encrypt a request object
- Generate a random content encryption key.
- Encrypt the content encryption key using the appropriate public key from our JWKs endpoint.
- Encrypt the request object using the content encryption key.
- Create the JWT with the encrypted content and key.
- Send the encrypted JWT as value in the
request
parameter in the Authorization Request.
Note: Using a secure and community provided library for your chosen platform is highly recommended.
Encrypted login hint (deprecated)
Supported key encryption algorithms | Supported content encryption algorithms |
---|---|
ECDH-ES RSA-OAEP RSA-OAEP-256 | A128GCM A128CBC-HS256 A128CBC-HS256 |
The encrypted login_hint should be formatted as a JWE Compact Serialization. The ciphertext is the encrypted plaintext login_hint.
A typical login hint:
login_hint=BID:14025800177
will using the encryption key in the JWK example, be:
login_hint=eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJjSm1XTWtrcXlWUDYtbFcya3hoSElUZG5oNkR1MkNzUklZZzBja3lXdVdBIiwieSI6IlRpbDROMFlGNWFSNnJJUWpHRjY4cWRkQ2ZfcDJuVmJCM1RMY2U2bDNxVlkifSwia2lkIjoiZW5jcnlwdGtleSIsImVuYyI6IkExMjhHQ00iLCJhbGciOiJFQ0RILUVTIn0..DzbBsb5mQSl-S-zG.-hL1oyZNRrqkp4UJHxX_.Q0n47mXdkmAoDfSqu-vkEg
The header part of the JWE object is in this case:
{ "epk": { "kty": "EC", "crv": "P-256", "x": "cJmWMkkqyVP6-lW2kxhHITdnh6Du2CsRIYg0ckyWuWA", "y": "Til4N0YF5aR6rIQjGF68qddCf_p2nVbB3TLce6l3qVY" }, "kid": "encryptkey", "enc": "A128GCM", "alg": "ECDH-ES" }
BankID OIDC provider will use the kid value to extract the correct key for decryption. If the kid value is not set, the decryption will fail.
The message to be encrypted is not JSON, it is simply:
BID:14025800177