ActiveLogin.Authentication

repository·main·Indexed 42 days ago

https://github.com/activelogin/activelogin.authentication

A .NET implementation for integrating Swedish BankID (Auth and Sign) into applications. Built on the BankID V6.0 JSON API, it supports ASP.NET Core and cross-platform environments (.NET Standard 2.0 and .NET 8). Key features include support for animated QR codes, Azure KeyVault integration, Azure Monitor telemetry, and various flows including Phone Auth and digital ID card verification.

Tokens
27.6K
Snippets
60
Records
88
Agent score
53%

What's inside ActiveLogin.Authentication

  1. Overview of ActiveLogin.Authentication

    main

    ActiveLogin.Authentication is a .NET library that enables applications to support Swedish BankID (svenskt BankID) authentication and signing. It is built on the BankID V6.0 JSON API and supports various BankID flows including Auth, Sign, Phone Auth, Phone Sign, and digital ID card verification.

    Key features include:

    • Cross-platform: Targets .NET Standard 2.0 and .NET 8.
    • BankID Support: API, Flow, and UI for Auth and Sign; API for Phone and Digital ID.
    • Modern UI: Supports BankID animated QR codes (Secure start).
    • Cloud Native: Designed for Microsoft Azure (KeyVault, Monitor, Application Insights, AD B2C).
    • Extensible: Customizable and multi-language (English and Swedish).
  2. Configure Data Protection for BankID Device Data cookie

    main

    Version 10.1.0 introduced a new long-lived cookie __ActiveLogin.BankIdDeviceData to store end-user device information for BankID risk indication.

    Because all Active Login cookies are protected using ASP.NET Core Data Protection, you must ensure your environment is configured to handle persistent keys if you are running in multi-instance deployments or containers. Without a persistent key store (e.g., Azure Blob Storage, Redis, SQL Server, or a shared file system), cookies may fail to be unprotected across app restarts or different instances.

  3. BankID Browser and Mobile Support

    main

    The library supports all major desktop and mobile browsers.

    Mobile Redirects:

    • Uses the App Link https://app.bankid.com/ by default for autostart.
    • Android Exceptions: Firefox and Samsung Internet do not support the App Link for launching the BankID app; the library automatically falls back to the bankid:/// custom scheme for these browsers.
    • Brave Browser Warning: Brave on iOS/Android identifies as Safari or Chrome for privacy reasons, which causes the redirect flow to fail.
  4. How BankID Authentication works

    main

    The BankID authentication implementation follows the standard ASP.NET authentication provider pattern. It is treated as a RemoteAuthenticationProvider because the flow requires redirecting the user to a UI and waiting for completion. During the flow, state is protected and stored via query strings and cookies.

    Key Components

    • AuthenticationBuilderBankIdAuthExtensions.AddBankIdAuth(): The entry point for adding BankID authentication. It adds default IoC implementations, configures ASP.NET Core authentication, and executes the IBankIdAuthBuilder pipeline.
    • BankIdAuthBuilderExtensions.Add*: Used to add specific schemes with configuration for 'Same' or 'Other' device scenarios.
    • BankIdAuthHandler: A RemoteAuthenticationHandler that implements IAuthenticationHandler.
    • BankIdUiAuthController: An MVC controller that handles the authentication UI.
    • BankIdUiAuthApiController: An API controller that handles backend calls from the UI (e.g., init, status, cancel).
  5. How BankID Signing works

    main

    Signing follows a simplified version of the authentication concepts. It uses a dedicated service to initiate the flow and handle callbacks.

    Key Components

    • ServiceCollectionBankIdSignExtensions.AddBankIdSign(): The entry point for adding BankID signing. It adds default IoC implementations, configures ASP.NET Core, and executes the IBankIdSignBuilder pipeline.
    • BankIdSignBuilder.AddConfig: Registers configuration in the IBankIdSignConfigurationProvider. Unlike authentication schemes, this does not register a callback URL; instead, the callback URL is specified during the call to BankIdSignService.InitiateSign.
    • IBankIdSignConfigurationProvider: Maintains the list of registered BankIdSignConfiguration objects.
    • BankIdSignService: The primary service for consumers. It allows initiating the sign flow, redirecting the user, handling the callback, and retrieving state from cookies to return to the consumer's specified URL.
    • BankIdUiSignController: An MVC controller handling the signing UI.
    • BankIdUiSignApiController: An API controller handling backend calls from the UI (e.g., initialize, qrCode, status, cancel).
  6. Configure Collect States in the Simulated Environment

    main

    You can control the sequence of states the simulated environment transitions through. This is useful for testing UI handling of different success codes or for speeding up automated tests.

    • BankIdSimulatedAppApiClient.FastCollectStates: A sequence containing only the states needed to reach a successful result (faster for tests).
    • BankIdSimulatedAppApiClient.AllSuccessfulCollectStates: A sequence used to verify UI handling of various successful collect hint codes and text lengths. It does not include failed terminal states.
    • Custom Sequence: You can provide a custom List<BankIdSimulatedAppApiClient.CollectState>. The final state in your list must have CollectStatus.Complete for the authentication to finish successfully.
    // Using FastCollectStates for automated tests
    services.AddBankId(bankId =>
    {
        bankId.UseSimulatedEnvironment(options =>
        {
            options.CollectStates = BankIdSimulatedAppApiClient.FastCollectStates;
        });
    });
    
    // Using a custom state sequence
    services.AddBankId(bankId =>
    {
        bankId.UseSimulatedEnvironment(options =>
        {
            options.CollectStates = new List<BankIdSimulatedAppApiClient.CollectState>
            {
                new(CollectStatus.Pending, CollectHintCode.Started),
                new(CollectStatus.Complete, CollectHintCode.UserSign)
            };
        });
    });
  7. Configure Device Data for Risk Indication

    main

    To provide BankID with accurate risk indication, you can include device data (web or app parameters) in the request.

    • Web: The default BankIdDefaultEndUserWebDeviceDataResolver uses a protected cookie named __ActiveLogin.BankIdDeviceData to store a unique Device Identifier. This identifier must remain identical across requests and should not rely on session cookies.
    • App: For mobile apps, you must implement your own resolvers as no default is provided for mobile.

    To customize device data resolution, implement the following interfaces:

    • IBankIdEndUserDeviceDataResolverFactory
    • IBankIdEndUserDeviceDataResolver
    • IBankIdEndUserDeviceDataConfiguration
  8. Integrate BankID with Azure AD B2C

    main

    You can provide BankID support to Azure AD B2C by using it as a custom identity provider via OpenID Connect.

    To achieve this, deploy Active Login as part of IdentityServer (refer to the provided samples). You can then configure your Azure AD B2C instance to federate to that IdentityServer instance, enabling BankID authentication for your users.

  9. Understand BankID cookies and Data Protection requirements

    main

    The package issues several session-based cookies to manage state during the BankID flow:

    • __ActiveLogin.BankIdUiState: Stores state during the auth process.
    • __ActiveLogin.BankIdUiOptions: Stores configured requirements for Auth, Sign, and Payment requests.
    • __ActiveLogin.BankIdDeviceData: Stores device data to ensure persistence across requests.

    Critical Requirement: All cookies are protected using ASP.NET Core Data Protection. In multi-instance or containerized environments, you must configure a persistent key store (e.g., Redis, Azure Blob Storage, or a shared file system) so that cookies can be decrypted across different instances or after app restarts.

  10. Implement a BankID payment flow

    main

    A typical BankID payment flow involves initiating the payment and then handling the callback to resolve the result.

    1. Initiate Payment

    Create a BankIdPaymentProperties object containing the transaction details (amount, currency, recipient, etc.). Use the BankIdInitiatePayment helper to redirect the user to the provider.

    2. Resolve Result

    In your callback endpoint, use IBankIdPaymentService.GetPaymentResultAsync(provider) to retrieve the outcome. Check result.Succeeded and access result.BankIdCompletionData to get user information (Personal Identity Number, Name) and device data (IP Address).

    // Inside a Controller
    [HttpPost("Payment")]
    public IActionResult Payment([FromQuery] string provider, [FromForm] PaymentRequestModel model)
    {
        var props = new BankIdPaymentProperties(TransactionType.card, "Demo Merchant Name")
        {
            Money = new("100,00", "SEK"),
            UserVisibleData = "Demo of Payment with Active Login.",
            Items = {
                {"scheme", provider},
                {"transactionType", nameof(TransactionType.card)},
                {"recipientName", "Demo Merchant Name"},
                {"amount", "100,00"},
                {"currency", "SEK"}
            },
        };
    
        var returnPath = $"{Url.Action(nameof(Callback))}?provider={provider}";
        return this.BankIdInitiatePayment(props, returnPath, provider);
    }
    
    [HttpPost]
    public async Task<IActionResult> Callback(string provider)
    {
        var result = await _bankIdPaymentService.GetPaymentResultAsync(provider);
        if (result?.Succeeded != true || result.BankIdCompletionData == null)
        {
            throw new Exception("Payment error");
        }
        // Process result.BankIdCompletionData...
    }
  11. Configure BankID for local development using a simulated environment

    main

    For development and testing without a real BankID certificate, use the .UseSimulatedEnvironment() method. This uses an in-memory implementation that allows you to test the authentication flow immediately. It is also recommended to add a debug event listener to monitor the process during development.

    services
        .AddBankId(bankId =>
        {
            bankId
                .AddDebugEventListener()
                .UseSimulatedEnvironment();
        });
    
    services
        .AddAuthentication()
        .AddBankIdAuth(bankId =>
        {
            bankId
                .AddSameDevice();
        });