Skip to content

Commit db2d0d7

Browse files
authored
Feature/470 use new auth properties app and web (#477)
Implement support for the app and web properties in the auth and sign request to the BankID API, used by BankID for risk indication. #470
1 parent e992d00 commit db2d0d7

51 files changed

Lines changed: 1673 additions & 33 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/articles/bankid.md

Lines changed: 149 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ The most common scenbario is to use Active Login for BankID auth/login, so most
4040
+ [Event listeners](#event-listeners)
4141
+ [Store data on auth completion](#store-data-on-auth-completion)
4242
+ [Resolve the end user ip](#resolve-the-end-user-ip)
43+
+ [Resolve the end user device data](#resolve-the-end-user-device-data)
4344
+ [Resolve requirements on Auth request](#resolve-requirements-on-auth-request)
4445
+ [Resolve user data on Auth request](#resolve-user-data-on-auth-request)
4546
+ [Custom QR code generation](#custom-qr-code-generation)
@@ -998,14 +999,148 @@ services.RemoveAll(typeof(IBankIdResultStore));
998999

9991000
### Resolve the end user ip
10001001

1001-
In some scenarios, like running behind a proxy, you might want to resolve the end user IP yourself and override the default implementaion.
1002+
In some scenarios, like running behind a proxy, you might want to resolve the end user IP yourself and override the default implementation.
10021003

10031004
Either register a class implementing `IBankIdEndUserIpResolver`:
10041005

10051006
```csharp
10061007
services.AddTransient<IBankIdEndUserIpResolver, EndUserIpResolver>();
10071008
```
10081009

1010+
---
1011+
### Device data
1012+
1013+
When initiating a flow with BankID, the objects "app" or "web" can be included in the request.
1014+
The information in these two objects differs, but including either of them allows BankID to
1015+
provide a better risk indication.
1016+
1017+
When using BankID, device information provides valuable metadata that enhances security and ensures a smoother user experience.
1018+
Including the **device type** (e.g., `APP` or `WEB`) helps BankID:
1019+
- **Evaluate risk** for each request.
1020+
- **Take automated actions** based on high-risk scenarios (if enabled).
1021+
- Provide **better insights** into the context of the request.
1022+
1023+
#### Configuring Device Data
1024+
1025+
Active Login has a default implementation of the User Device feature that uses a
1026+
web browser as the device type. You can customize the default implementation or create your own.
1027+
1028+
The following service interface must be implemented to use the User Device feature:
1029+
- `IBankIdEndUserDeviceDataResolverFactory`: Factory that provides the resolvers for the device type.
1030+
- `IBankIdEndUserDeviceDataResolver`: Resolver that provides the device data for a given device type.
1031+
- `IBankIdEndUserDeviceDataConfiguration`: Configuration that specifies the device type to use.
1032+
1033+
#### What is included in the requests?
1034+
1035+
| Device Type | Default Resolver Implementation | Metadata Included |
1036+
|---------------|-------------------------------------------|--------------------------------------------|
1037+
| **Web** | `BankIdDefaultEndUserWebDeviceDataResolver` | Referring domain, User-Agent, DeviceIdentifier |
1038+
| **App** | `BankIdDefaultEndUserAppDeviceDataResolver` | App Identifier, Device OS, Model, DeviceIdentifier |
1039+
1040+
The Device identifier must be identical between requests.
1041+
1042+
The `BankIdDefaultEndUserWebDeviceDataResolver` will set a protected cookie named `__ActiveLogin.BankIdDeviceData` that contains
1043+
unique identifier (DeviceIdentifier) to ensure that the identifier is persistent across requests.
1044+
1045+
#### Customizing the User Device feature
1046+
To customize the User Device feature, use the `UseDeviceData` extension in the BankID client builder.
1047+
This allows you to specify the device type and any relevant metadata using resolvers.
1048+
1049+
The BankIdFlowService will automatically include the device data in the BankID request,
1050+
since it is dependent of the `IBankIdEndUserDeviceDataResolverFactory` service.
1051+
1052+
##### Configuration examples
1053+
1054+
If no configuration of the UseDeviceData has been set, the default implementation will be used.
1055+
This implementation will set the device type to `BankIdEndUserDeviceType.Web` and use
1056+
the `BankIdDefaultEndUserDeviceDataResolverFactory` to find the correct resolver for the device type.
1057+
The `BankIdDefaultEndUserWebDeviceDataResolver` is used to fetch the web browser information.
1058+
1059+
*If no custom implementation is made the device data defaults to this:*
1060+
```csharp
1061+
services
1062+
.AddBankId(bankId =>
1063+
{
1064+
bankId.UseDeviceData(config =>
1065+
{
1066+
// Set the device type for the request
1067+
config.DeviceType = BankIdEndUserDeviceType.Web;
1068+
1069+
// Use the default resolver factory
1070+
config.UseResolverFactory<BankIdDefaultEndUserDeviceDataResolverFactory>();
1071+
1072+
// Add the default resolver for Web
1073+
config.AddDeviceResolver<BankIdDefaultEndUserWebDeviceDataResolver>();
1074+
});
1075+
});
1076+
```
1077+
1078+
*Custom implementation requests initiated by av web browser:*
1079+
```csharp
1080+
services
1081+
.AddBankId(bankId =>
1082+
{
1083+
bankId.UseDeviceData(config =>
1084+
{
1085+
// Set the device type for the request
1086+
config.DeviceType = BankIdEndUserDeviceType.Web;
1087+
1088+
// Use a custom resolver factory
1089+
// that implements IBankIdEndUserDeviceDataResolverFactory
1090+
config.UseResolverFactory<MyCustomResolverFactory>();
1091+
1092+
// Add a custom resolver for the device type Web
1093+
// that implements IBankIdEndUserDeviceDataResolver
1094+
config.AddDeviceResolver<MyCustomWebDeviceDataResolver>();
1095+
});
1096+
});
1097+
```
1098+
1099+
1100+
*Custom implementation requests initiated by a mobile app:*
1101+
1102+
```csharp
1103+
services
1104+
.AddBankId(bankId =>
1105+
{
1106+
bankId.UseDeviceData(config =>
1107+
{
1108+
// Set the device type starting the request
1109+
config.DeviceType = BankIdEndUserDeviceType.App;
1110+
1111+
// Use the default resolver factory to find what device data resolvers to use
1112+
config.UseResolverFactory<BankIdDefaultEndUserDeviceDataResolverFactory>();
1113+
1114+
// Use the default data resolver for the device type app
1115+
// On app devices (e.g. MAUI, Xamarin, etc.) we need to set the
1116+
// device data manually at start
1117+
config.AddDeviceResolver(s => new BankIdDefaultEndUserAppDeviceDataResolver()
1118+
{
1119+
// App ID or package name
1120+
AppIdentifier = "com.example.app",
1121+
1122+
// Device operating system
1123+
DeviceOs = "iOS 16.7.7",
1124+
1125+
// Device model
1126+
DeviceModelName = "Apple iPhone14,3",
1127+
1128+
// Unique hardware ID
1129+
DeviceIdentifier = "1234567890"
1130+
});
1131+
1132+
});
1133+
});
1134+
```
1135+
The information for the BankIdDefaultEndUserAppDeviceDataResolver has to be set during startup.
1136+
1137+
#### More information available at:
1138+
- [BankID Risk Indication](https://www.bankid.com/en/foretag/the-service/risk-indication)
1139+
- [BankID Api - Auth](https://developers.bankid.com/api-references/auth--sign/auth)
1140+
- [BankID Api - Sign](https://developers.bankid.com/api-references/auth--sign/sign)
1141+
- [BankID Api - Payment](https://developers.bankid.com/api-references/auth--sign/payment)
1142+
1143+
---
10091144
### Resolve requirements on Auth request
10101145

10111146
If you want to set the requirements on how the authentication order must be performed dynamically for each order instead of statically during startup in `Program.cs`, it can be done by overriding the default implementation of the `IBankIdAuthRequestRequirementsResolver`.
@@ -1320,15 +1455,19 @@ We have choosen not to normalize the capitalization of the names as it´s hard o
13201455

13211456
The `*.AspNetCore` package will issue a cookie to make the auth flow work
13221457

1323-
The cookie is called: `__ActiveLogin.BankIdUiState`
1324-
1325-
The cookie is there to store state during the auth process, as the user will/might be redirected during the flow. The cookie is session based only and will be deleted once the auth process is finished and/or when the user closes the browser.
1326-
1327-
Because it is strictly related to temp storage during auth, you should not have to inform the user about these specific cookies (according to the [EU "cookie law"](https://www.cookielaw.org/the-cookie-law/)).
1328-
1329-
With the current implementaiton (following the convention from Microsoft ASP.NET) the usage of cookies is not optional.
1330-
1331-
A more technical deep dive of the cookies can be found in [this issue](https://github.com/ActiveLogin/ActiveLogin.Authentication/issues/156).
1458+
- Cookie: `__ActiveLogin.BankIdUiState`
1459+
- This cookie is there to store state during the auth process, as the user will/might be redirected during the flow. The cookie is session based only and will be deleted once the auth process is finished and/or when the user closes the browser.
1460+
1461+
- Because it is strictly related to temp storage during auth, you should not have to inform the user about these specific cookies (according to the [EU "cookie law"](https://www.cookielaw.org/the-cookie-law/)).
1462+
1463+
- With the current implementation (following the convention from Microsoft ASP.NET) the usage of cookies is not optional.
1464+
1465+
- A more technical deep dive of this cookie can be found in [this issue](https://github.com/ActiveLogin/ActiveLogin.Authentication/issues/156).
1466+
1467+
- Cookie: `__ActiveLogin.BankIdDeviceData`
1468+
- This cookie is used to store the device data for the user, in the default implementation,
1469+
It is used to ensure that the device data is persistent across requests.
1470+
13321471

13331472

13341473
### Browser support

samples/Standalone.MvcSample/Program.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
using ActiveLogin.Authentication.BankId.AspNetCore;
44
using ActiveLogin.Authentication.BankId.AspNetCore.Auth;
55
using ActiveLogin.Authentication.BankId.AspNetCore.Sign;
6+
using ActiveLogin.Authentication.BankId.AspNetCore.UserContext.Device.Resolvers;
67
using ActiveLogin.Authentication.BankId.AzureKeyVault;
78
using ActiveLogin.Authentication.BankId.AzureMonitor;
89
using ActiveLogin.Authentication.BankId.Core;
9-
using ActiveLogin.Authentication.BankId.Core.CertificatePolicies;
10+
using ActiveLogin.Authentication.BankId.Core.UserContext.Device;
11+
using ActiveLogin.Authentication.BankId.Core.UserContext.Device.Configuration;
12+
using ActiveLogin.Authentication.BankId.Core.UserContext.Device.ResolverFactory;
1013
using ActiveLogin.Authentication.BankId.QrCoder;
1114
using ActiveLogin.Authentication.BankId.UaParser;
1215

@@ -62,6 +65,13 @@
6265
options.LogDeviceUniqueHardwareId = false;
6366
});
6467

68+
bankId.UseDeviceData(config =>
69+
{
70+
config.DeviceType = BankIdEndUserDeviceType.Web;
71+
config.UseResolverFactory<BankIdDefaultEndUserDeviceDataResolverFactory>();
72+
config.UseDeviceResolver<BankIdDefaultEndUserWebDeviceDataResolver>();
73+
});
74+
6575
bankId.UseQrCoderQrCodeGenerator();
6676
bankId.UseUaParserDeviceDetection();
6777

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace ActiveLogin.Authentication.BankId.Api;
2+
public interface IBankIdEndUserDeviceData
3+
{ }

src/ActiveLogin.Authentication.BankId.Api/Models/AuthRequest.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class AuthRequest : Request
1010
/// The user IP address as seen by RP. IPv4 and IPv6 is allowed.
1111
/// Note the importance of using the correct IP address.It must be the IP address representing the user agent (the end user device) as seen by the RP.
1212
/// If there is a proxy for inbound traffic, special considerations may need to be taken to get the correct address.
13-
///
13+
///
1414
/// In some use cases the IP address is not available, for instance for voice based services.
1515
/// In this case, the internal representation of those systems IP address is ok to use.
1616
/// </param>
@@ -27,23 +27,27 @@ public class AuthRequest : Request
2727
/// </param>
2828
/// <param name="returnUrl">The URL to return to when the authentication order is completed.</param>
2929
/// <param name="returnRisk">If set to true, a risk indication will be included in the collect response.</param>
30+
/// <param name="web">Information about the app device the end user is using.</param>
31+
/// <param name="app">Information about the web browser the end user is using.</param>
3032
public AuthRequest(
3133
string endUserIp,
3234
Requirement? requirement = null,
3335
string? userVisibleData = null,
3436
byte[]? userNonVisibleData = null,
3537
string? userVisibleDataFormat = null,
3638
string? returnUrl = null,
37-
bool? returnRisk = null)
39+
bool? returnRisk = null,
40+
DeviceDataWeb? web = null,
41+
DeviceDataApp? app = null)
3842
: base(
3943
endUserIp,
4044
userVisibleData: userVisibleData,
4145
userNonVisibleData: userNonVisibleData,
4246
requirement: requirement,
4347
userVisibleDataFormat: userVisibleDataFormat,
4448
returnUrl: returnUrl,
45-
returnRisk: returnRisk
46-
)
47-
{
48-
}
49+
returnRisk: returnRisk,
50+
web: web,
51+
app: app)
52+
{ }
4953
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
4+
namespace ActiveLogin.Authentication.BankId.Api.Models;
5+
6+
/// <summary>
7+
/// Base class for device parameters.
8+
/// </summary>
9+
/// <param name="deviceIdentifier">
10+
/// The identifier of the device your client is running on.
11+
/// This is used to uniquely identify the device and should be a value
12+
/// that is not tied to a single user of the device.
13+
/// Preferably, it should remain the same even if your app is reinstalled.
14+
/// </param>
15+
public abstract class DeviceData(string deviceIdentifier) : IBankIdEndUserDeviceData
16+
{
17+
/// The identifier of the device your client is running on.
18+
/// This is used to uniquely identify the device and should be a value
19+
/// that is not tied to a single user of the device.
20+
/// Preferably, it should remain the same even if your app is reinstalled.
21+
[JsonPropertyName("deviceIdentifier")]
22+
public string? DeviceIdentifier { get; } = deviceIdentifier;
23+
24+
}
25+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace ActiveLogin.Authentication.BankId.Api.Models;
4+
5+
/// <summary>
6+
/// Parameters for the device where the BankID app is running.
7+
/// </summary>
8+
/// <param name="appIdentifier">
9+
/// The identifier of your application.
10+
/// This is the package name on Android and the bundle identifier on iOS.
11+
/// It is vital to use the correct value.If your service does not supply the correct value legitimate orders might be blocked.</param>
12+
/// E.g. "com.example.myapp"
13+
/// <param name="deviceOs">
14+
/// The device operating system where your app is running.
15+
/// E.g. "IOS 16.7.7"
16+
/// </param>
17+
/// <param name="deviceModelName">
18+
/// The model of the device your app is running on.
19+
/// E.g. "Apple iPhone14,3"
20+
/// </param>
21+
/// <param name="deviceIdentifier">
22+
/// <inheritdoc cref="DeviceData(string)" path="/param[@name='deviceIdentifier']"/>
23+
/// </param>
24+
public sealed class DeviceDataApp(
25+
string appIdentifier,
26+
string deviceOs,
27+
string deviceModelName,
28+
string deviceIdentifier)
29+
: DeviceData(deviceIdentifier)
30+
{
31+
/// <summary>
32+
/// Application Identifier, e.g. package name on Android and the bundle identifier on iOS.
33+
/// </summary>
34+
[JsonPropertyName("appIdentifier")]
35+
public string? AppIdentifier { get; set; } = appIdentifier;
36+
37+
/// <summary>
38+
/// Device operating system.
39+
/// </summary>
40+
[JsonPropertyName("deviceOS")]
41+
public string? DeviceOs { get; set; } = deviceOs;
42+
43+
/// <summary>
44+
/// Device model
45+
/// </summary>
46+
[JsonPropertyName("deviceModelName")]
47+
public string? DeviceModelName { get; set; } = deviceModelName;
48+
49+
}
50+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace ActiveLogin.Authentication.BankId.Api.Models;
4+
5+
/// <summary>
6+
/// Parameters for the browser where the BankID app is running.
7+
/// </summary>
8+
/// <param name="referringDomain">
9+
/// The domain that starts the BankID app.
10+
/// This should generally be your domain name followed by the public suffix,
11+
/// which will generally be the top level domain.
12+
/// E.g. "example.com"
13+
/// </param>
14+
/// <param name="userAgent">
15+
/// The user agent of the user interacting with your web page.
16+
/// E.g. "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/114.0"
17+
/// </param>
18+
/// <param name="deviceIdentifier">
19+
/// <inheritdoc cref="DeviceData(string)" path="/param[@name='deviceIdentifier']"/>
20+
/// </param>
21+
public sealed class DeviceDataWeb(
22+
string referringDomain,
23+
string userAgent,
24+
string deviceIdentifier)
25+
: DeviceData(deviceIdentifier)
26+
{
27+
/// <summary>
28+
/// The domain that starts the BankID app.
29+
/// </summary>
30+
[JsonPropertyName("referringDomain")]
31+
public string? ReferringDomain { get; set; } = referringDomain;
32+
33+
/// <summary>
34+
/// The user agent of the user interacting with your web page.
35+
/// </summary>
36+
[JsonPropertyName("userAgent")]
37+
public string? UserAgent { get; set; } = userAgent;
38+
39+
}

0 commit comments

Comments
 (0)