Standard for receiving audit-messages from BankID self-service ( BASS )
This integration guide is designed to help you, as a client receiving audit events from our service, set up and manage the integration. The standards used for delivering events are CloudEvents delivered through Webhooks over HTTPS.
Table of Contents
- 1 Table of Contents
- 2 1. Introduction
- 3 2. Integration Steps
- 4 3. Handling Cloudevents
- 5 4. Security
- 5.1 4.1. Webhook URL
- 5.2 4.2. Authentication
- 5.2.1 Authorization header
- 5.2.2 Azure AD App
- 5.2.3 Entra ID JWT
- 5.2.3.1 Overview
- 5.2.3.2 Token Issuance
- 5.2.3.3 Token Validation
- 5.2.3.4 Implementation
- 5.2.3.5 Example
- 6 5. Troubleshooting
- 7 6 Further documentation
1. Introduction
From the Cloudevents documentation;
CloudEvents is a specification for describing event data in common formats to provide interoperability across services, platforms and systems.
By utilizing Cloudevents delivered to a Webhook over HTTPS, we adhere to standard protocols decoupled from specific libraries or SDKs. In this guide, we aim to provide you with the necessary information to set up a receiver capable of receiving audit events from our systems.
1.1 Audit events in the future
The current integration sends audit events when BAPP is added as OTP and when a password is reset. In the future, we will likely expand the integration to send more audit events. The integration should be able to receive any event and internally decide how to handle it. Some examples of events that could be sent in the future are:
Automatic block of BankID certificate based on anti-fraud signals
Biometric activation
2. Integration Steps
2.1. Send us required information
The required information is the following:
Webhook url: This is the full URL you will receive events on. It has to be publicly accessible from the internet, in all environments.
Authentication: One of
Static token: A static token sent in the Authorization header
AppId and TenantId: Application ID for our application registration in your Azure AD tenant and Tenant ID for your Azure tenant.
For further information regarding authentication, see separate bulletpoint bellow.
2.2. Validate subscription
Once we attempt to create the subscription, a subscription validation request will be sent to the provided URL by a HTTP Options call. A header, WebHook-Request-Origin, will be included in this request. It contains a DNS expression identifying the system sending the events. At the time of writing, this will be "eventgrid.azure.net"
To accept the subscription, reply with HTTP Status 200 and the following two headers:
WebHook-Allowed-Origin: One of two possible values; the same value as was sent in the WebHook-Request-Origin header or an asterix(“*”)
WebHook-Allowed-Rate: An asterix(“*”) to indiciate no rate limitation, or a positive integer number to indicate requests per minute.
There are more headers sent in the request, both standard http-headers and application-specific headers, but the headers mentioned here are the ones you have to strictly handle to validate the subscription
2.3. Receive audit events
Response code for a successfull delivery must be one of 200, 201, 202, 203 or 204. A response code of 400, 401, 403, 404 and 413 will stop retries and put the event in our dead-letter event storage. Other failure codes will be retried as described above. If repeated failures occurs during a short time, all deliveries to the endpoint may be suspended for up to several hours.
If the delivery fails, a retry with exponential backoff will be retried on a best-effort basis. If the delivery still fails after 24 hours, the event is sent to our dead-letter storage for manual processing and debugging.
2.4. Example Cloudevents subscriber
An example implementation of a Cloudevents subscriber can be found here; https://github.com/BankIDNorge/example-cloudevent-subscriber
It is written in Typescript for Azure Functions.
3. Handling Cloudevents
A reworked example request from the Cloudevents documentation can be seen here:
POST /your-subscription HTTP/1.1 Host: webhook.example.com Content-Type: application/cloudevents+json; charset=utf-8 Content-Length: nnnn Authorization: a-token { "specversion" : "1.0", "type" : "com.example.someevent", ... further attributes omitted ... "data" : { ... application data ... } }
Two main things to note about the payload are the type and data fields.
3.1 Event payloads
The CloudEvent type and related data payload are described on the following pages.
3.2 Handle incorrect messages
While the messages are defined, typos and errors may occur on either end. As such, you need to have proper handling of errors related to the messages - such as, but not limited to, unknown type, unknown data fields, missing data fields, unknown data values etc.
If you discover incorrect messages, contact us for troubleshooting. Please include the full message and time of delivery.
4. Security
4.1. Webhook URL
The following requirements for the webhook URL are absolute:
It must be publicly accessible
It must be available via HTTPS with a valid certificate
It must accept Options and Post calls
4.2. Authentication
To prevent anyone from calling your subscription webhooks, there needs to be a layer of authentication. We support the following three options:
Static token in the authorization header
Azure AD App
Entra ID JWT
Authorization header
For the static options, we need to agree on a routine for rolling the secret. You will also need to accept both the old and the new token, at least for a short periode of time, while we update our system with the new token. The format will be Authorization: Bearer <static-token>
.
Azure AD App
For Azure AD App, you need to perform the following steps:
Create an Azure AD app for your Webhook.
Create a service principal for Microsoft.EventGrid if it doesn't already exist.
Create a role named AzureEventGridSecureWebhookSubscriber in the Azure AD app for your Webhook.
Create a service principal for our event subscription writer app if it doesn't already exist.
Add service principal of event subscription writer Azure AD app to the AzureEventGridSecureWebhookSubscriber role
Add service principal of Microsoft.EventGrid to the AzureEventGridSecureWebhookSubscriber role as well
Link to source for these steps: Secure WebHook delivery with Azure AD Application in Azure Event Grid
Note that the link also contains a Powershell script which can perform the setup. For step 4, and the eventSubscriptionWriterAppId
variable, you'll need the relevant applicationID from us, which will be provided on request.
We have one app for test and one for production, so some or all of the steps will have to be duplicated depending on your setup. If you decide on creating one Azure AD App for the webhook in each environment, all but the second step will have to be duplicated. If you go for just one Azure AD App, only step 4 and 5 will have to be duplicated. appId for the two apps will be provided to you on request.
Once you have finished setting up the service principals, roles and Azure AD Apps, send us the following info:
Your Azure tenant ID
appId of the Azure AD Apps that was created
Entra ID JWT
Overview
The Azure AD App alternative above is utilizes Entra ID JWT behind the scenes. This means that an Entra ID JWT is sent as a Bearer Token, so we can use that directly instead to simplify the integration-part for both parties. This method of authentication would then leverage short-lived tokens, enhancing security by reducing the risk associated with long-lived static tokens or certificates.
If would would like to use this, Tenant ID and the values for the different claims will be provided on demand.
Token Issuance
The JWT is issued to a specific pair of applications in Azure Entra ID. This token contains claims that identify the sender and the intended receiver of the message. The token is signed by Azure Entra ID, ensuring its authenticity. We would manage both applications - one for our service sending the events, and one representing your endpoint.
Token Validation
To validate the JWT, follow these steps:
Set Up Trust: Establish trust with Azure Entra ID v2. Documentation for setting up trust can be found here.
Validate Signature: Use standard JWT validation methods to verify the token's signature. This ensures that the token was indeed issued by Azure Entra ID and has not been tampered with.
Validate Claims: Check the claims within the token to ensure they match the expected values. Key claims to validate include:
Application ID: Verify that the token was issued to the specific application dedicated to sending events.
Audience: Ensure the token is intended for your system.
Expiration: Confirm that the token is still valid and has not expired.
Implementation
Token Acquisition: The sender will acquire a JWT from Azure Entra ID for each API call. This token will be included in the Authorization header of the HTTP request.
Token Validation: On receiving the API call, your system should:
Extract the JWT from the Authorization header.
Validate the token's signature and claims as described above.
Proceed with processing the request only if the token is valid.
Example
For an example of how to validate a JWT in your application, refer to the example-cloudevent-subscriber repository.
5. Troubleshooting
Validation of subscription fails
Check that firewalls are open according to 4.1.
Check that you accept the correct Content-Type("application/cloudevents+json; charset=utf-8")
6 Further documentation
Azure Event Grid: https://learn.microsoft.com/en-us/azure/event-grid/
Endpoint validation with Azure Event Grid: https://learn.microsoft.com/en-us/azure/event-grid/webhook-event-delivery
Event Grid CloudEvents Schema: https://learn.microsoft.com/en-us/azure/event-grid/cloud-event-schema
Webhook delivery with Azure AD: https://learn.microsoft.com/en-us/azure/event-grid/secure-webhook-delivery