From 644d93624f3209662d2ed4bd5afd17d11f23b1b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C3=96rneholm?= Date: Fri, 5 Jan 2024 15:00:32 +0100 Subject: [PATCH 1/6] Custom app --- docs/articles/bankid.md | 21 +------ .../IBankIdBuilderExtensions.cs | 18 +++++- ...ankIdLauncherUserAgentCustomAppCallback.cs | 12 ++-- .../Launcher/BankIdLauncher.cs | 58 ++++++++++--------- .../BankIdLauncherCustomAppCallbackContext.cs | 2 +- .../BankIdLauncherCustomAppCallbackResult.cs | 13 +++++ ...erReloadBehaviourOnReturnFromBankIdApp.cs} | 44 +++++++------- .../IBankIdLauncherCustomAppCallback.cs | 5 +- .../BankIdLauncher_Tests.cs | 10 ++-- 9 files changed, 98 insertions(+), 85 deletions(-) create mode 100644 src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs rename src/ActiveLogin.Authentication.BankId.Core/Launcher/{ReloadBehaviourOnReturnFromBankIdApp.cs => BrowserReloadBehaviourOnReturnFromBankIdApp.cs} (61%) diff --git a/docs/articles/bankid.md b/docs/articles/bankid.md index 0f0c2ccb..37480b6e 100644 --- a/docs/articles/bankid.md +++ b/docs/articles/bankid.md @@ -1136,29 +1136,14 @@ public class BankIdFacebookAppCallback : IBankIdLauncherCustomAppCallback public Task GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context) { - return Task.FromResult("fb://"); + return Task.FromResult( + new BankIdLauncherCustomAppCallbackResult("fb://", BrowserReloadBehaviourOnReturnFromBankIdApp.Never) + ); } } ``` -By default, Safari on iOS will reload when you return from the BankID -app. If the flow starts in a native iOS app, you want to turn off this -behavior by implementing -`IBankIdLauncherCustomAppCallback.ReloadPageOnReturnFromBankIdApp` if -you are using an embedded Web View in your app. - -```csharp -public class BankIdFacebookAppCallback : IBankIdLauncherCustomAppCallback -{ - ... - - public ReloadBehaviourOnReturnFromBankIdApp - ReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice) => - ReloadBehaviourOnReturnFromBankIdApp.Never; -} -``` - ### Verify digital ID card To use the API for "Verify digital ID card" you first need to register the BankID services, select an environment etc. diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs b/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs index fa87a599..be9a6d16 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs @@ -11,17 +11,33 @@ public static class IBankIdBuilderExtensions { /// /// Adds a custom return url resolver. + /// When only returnUrl is specified, the reload behaviour will fall back to "Never". As we know, only Safari on iOS have the Always behaviour. /// /// /// /// /// public static IBankIdBuilder AddCustomAppCallbackByUserAgent(this IBankIdBuilder builder, Func isApplicable, Func getReturnUrl) + { + Func getResult = + (context) => new(getReturnUrl(context), BrowserReloadBehaviourOnReturnFromBankIdApp.Never); + + return AddCustomAppCallbackByUserAgent(builder, isApplicable, getResult); + } + + /// + /// Adds a custom return url resolver. + /// + /// + /// + /// + /// + public static IBankIdBuilder AddCustomAppCallbackByUserAgent(this IBankIdBuilder builder, Func isApplicable, Func getResult) { builder.Services.AddTransient(x => { var httpContextAccessor = x.GetRequiredService(); - var customApp = new BankIdLauncherUserAgentCustomAppCallback(httpContextAccessor, isApplicable, getReturnUrl); + var customApp = new BankIdLauncherUserAgentCustomAppCallback(httpContextAccessor, isApplicable, getResult); return customApp; }); diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs index 62ddc552..6c75c8e3 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs @@ -8,13 +8,13 @@ public class BankIdLauncherUserAgentCustomAppCallback : IBankIdLauncherCustomApp { private readonly IHttpContextAccessor _httpContextAccessor; private readonly Func _isApplicable; - private readonly Func _getReturnUrl; + private readonly Func _getResult; - public BankIdLauncherUserAgentCustomAppCallback(IHttpContextAccessor httpContextAccessor, Func isApplicable, Func getReturnUrl) + public BankIdLauncherUserAgentCustomAppCallback(IHttpContextAccessor httpContextAccessor, Func isApplicable, Func getResult) { _httpContextAccessor = httpContextAccessor; _isApplicable = isApplicable; - _getReturnUrl = getReturnUrl; + _getResult = getResult; } public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context) @@ -29,9 +29,9 @@ public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context) return Task.FromResult(isApplicable); } - public Task GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context) + public Task GetCustomAppCallbackResult(BankIdLauncherCustomAppCallbackContext context) { - var returnUrl = _getReturnUrl(context); - return Task.FromResult(returnUrl); + var result = _getResult(context); + return Task.FromResult(result); } } diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs index 50114c1e..9bfaae71 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Text; using ActiveLogin.Authentication.BankId.Core.Helpers; @@ -36,9 +35,11 @@ public async Task GetLaunchInfoAsync(LaunchUrlRequest request) var customAppCallbackContext = new BankIdLauncherCustomAppCallbackContext(detectedDevice, request); var customAppCallback = await GetRelevantCustomAppCallbackAsync(customAppCallbackContext, _customAppCallbacks); + var customAppCallbackResult = customAppCallback != null ? (await customAppCallback.GetCustomAppCallbackResult(customAppCallbackContext)) : null; - var deviceWillReloadPageOnReturn = GetDeviceWillReloadPageOnReturnFromBankIdApp(detectedDevice, customAppCallback); - var launchUrl = await GetLaunchUrl(detectedDevice, request, customAppCallback); + var deviceWillReloadPageOnReturn = GetDeviceWillReloadPageOnReturnFromBankIdApp(detectedDevice, customAppCallbackResult); + var launchUrl = GetLaunchUrl(detectedDevice, request, customAppCallbackResult); + return new BankIdLaunchInfo(launchUrl, deviceMightRequireUserInteractionToLaunch, deviceWillReloadPageOnReturn); } @@ -55,27 +56,28 @@ private bool GetDeviceMightRequireUserInteractionToLaunchBankIdApp(BankIdSupport && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Opera; } - private bool GetDeviceWillReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice, IBankIdLauncherCustomAppCallback? customAppCallback) + private bool GetDeviceWillReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice, BankIdLauncherCustomAppCallbackResult? customAppCallbackResult) { - var reloadBehaviour = customAppCallback?.ReloadPageOnReturnFromBankIdApp(detectedDevice) ?? - ReloadBehaviourOnReturnFromBankIdApp.Default; + var reloadBehaviour = customAppCallbackResult?.BrowserReloadBehaviourOnReturnFromBankIdApp ?? BrowserReloadBehaviourOnReturnFromBankIdApp.Default; return reloadBehaviour switch { - ReloadBehaviourOnReturnFromBankIdApp.Always => true, - ReloadBehaviourOnReturnFromBankIdApp.Never => false, + BrowserReloadBehaviourOnReturnFromBankIdApp.Always => true, + BrowserReloadBehaviourOnReturnFromBankIdApp.Never => false, // By default, Safari on iOS will refresh the page/tab when returned from the BankID app - ReloadBehaviourOnReturnFromBankIdApp.Default => detectedDevice is { DeviceOs: BankIdSupportedDeviceOs.Ios, DeviceBrowser: BankIdSupportedDeviceBrowser.Safari }, - - _ => throw new ArgumentOutOfRangeException(nameof(reloadBehaviour), reloadBehaviour, "Unknown reload behaviour") + _ => detectedDevice is + { + DeviceOs: BankIdSupportedDeviceOs.Ios, + DeviceBrowser: BankIdSupportedDeviceBrowser.Safari + } }; } - private async Task GetLaunchUrl(BankIdSupportedDevice device, LaunchUrlRequest request, IBankIdLauncherCustomAppCallback? customAppCallback) + private string GetLaunchUrl(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomAppCallbackResult? customAppCallback) { var prefix = GetPrefixPart(device); - var queryString = await GetQueryStringPart(device, request, customAppCallback); + var queryString = GetQueryStringPart(device, request, customAppCallback); return $"{prefix}{queryString}"; } @@ -98,21 +100,24 @@ private static bool CanUseAppLink(BankIdSupportedDevice device) private static bool IsSafariOnIos(BankIdSupportedDevice device) { - return device.DeviceOs == BankIdSupportedDeviceOs.Ios - && device.DeviceBrowser == BankIdSupportedDeviceBrowser.Safari; + return device is + { + DeviceOs: BankIdSupportedDeviceOs.Ios, + DeviceBrowser: BankIdSupportedDeviceBrowser.Safari + }; } private static bool IsChromeOrEdgeOnAndroid6OrGreater(BankIdSupportedDevice device) { - return device.DeviceOs == BankIdSupportedDeviceOs.Android - && device.DeviceOsVersion.MajorVersion >= 6 - && ( - device.DeviceBrowser == BankIdSupportedDeviceBrowser.Chrome - || device.DeviceBrowser == BankIdSupportedDeviceBrowser.Edge - ); + return device is + { + DeviceOs: BankIdSupportedDeviceOs.Android, + DeviceOsVersion.MajorVersion: >= 6, + DeviceBrowser: BankIdSupportedDeviceBrowser.Chrome or BankIdSupportedDeviceBrowser.Edge + }; } - private async Task GetQueryStringPart(BankIdSupportedDevice device, LaunchUrlRequest request, IBankIdLauncherCustomAppCallback? customAppCallback) + private string GetQueryStringPart(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomAppCallbackResult? customAppCallback) { var queryStringParams = new Dictionary(); @@ -126,19 +131,18 @@ private async Task GetQueryStringPart(BankIdSupportedDevice device, Laun queryStringParams.Add(BankIdRpRefQueryStringParamName, Base64Encode(request.RelyingPartyReference)); } - var redirectUrl = await GetRedirectUrl(device, request, customAppCallback); + var redirectUrl = GetRedirectUrl(device, request, customAppCallback); queryStringParams.Add(BankIdRedirectQueryStringParamName, redirectUrl); return QueryStringGenerator.ToQueryString(queryStringParams); } - private static async Task GetRedirectUrl(BankIdSupportedDevice device, LaunchUrlRequest request, IBankIdLauncherCustomAppCallback? customAppCallback) + private static string GetRedirectUrl(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomAppCallbackResult? customAppCallbackResult) { // Allow for easy override of callback url - if (customAppCallback != null) + if (customAppCallbackResult != null && customAppCallbackResult.ReturnUrl != null) { - var customAppCallbackContext = new BankIdLauncherCustomAppCallbackContext(device, request); - return await customAppCallback.GetCustomAppReturnUrl(customAppCallbackContext); + return customAppCallbackResult.ReturnUrl; } // Only use redirect url for iOS as recommended in BankID Guidelines 3.1.2 diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs index 3187a906..4ab22061 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs @@ -4,7 +4,7 @@ namespace ActiveLogin.Authentication.BankId.Core.Launcher; public class BankIdLauncherCustomAppCallbackContext { - internal BankIdLauncherCustomAppCallbackContext(BankIdSupportedDevice device, LaunchUrlRequest launchUrlRequest) + public BankIdLauncherCustomAppCallbackContext(BankIdSupportedDevice device, LaunchUrlRequest launchUrlRequest) { Device = device; LaunchUrlRequest = launchUrlRequest; diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs new file mode 100644 index 00000000..49031eb8 --- /dev/null +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs @@ -0,0 +1,13 @@ +namespace ActiveLogin.Authentication.BankId.Core.Launcher; + +public class BankIdLauncherCustomAppCallbackResult +{ + public BankIdLauncherCustomAppCallbackResult(string? returnUrl, BrowserReloadBehaviourOnReturnFromBankIdApp browserReloadBehaviourOnReturnFromBankIdApp = BrowserReloadBehaviourOnReturnFromBankIdApp.Default) + { + ReturnUrl = returnUrl; + BrowserReloadBehaviourOnReturnFromBankIdApp = browserReloadBehaviourOnReturnFromBankIdApp; + } + + public string? ReturnUrl { get; set; } + public BrowserReloadBehaviourOnReturnFromBankIdApp BrowserReloadBehaviourOnReturnFromBankIdApp { get; set; } +} diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/ReloadBehaviourOnReturnFromBankIdApp.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs similarity index 61% rename from src/ActiveLogin.Authentication.BankId.Core/Launcher/ReloadBehaviourOnReturnFromBankIdApp.cs rename to src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs index f6a0edef..266fd7fc 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/ReloadBehaviourOnReturnFromBankIdApp.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs @@ -1,22 +1,22 @@ -namespace ActiveLogin.Authentication.BankId.Core.Launcher; - -/// -/// Represents the reload behaviour of the device when returning from the BankID app. -/// -public enum ReloadBehaviourOnReturnFromBankIdApp -{ - /// - /// The device will reload the page for Safari on iOS. - /// - Default = 0, - - /// - /// The device will always reload the page. - /// - Always, - - /// - /// The device will never reload the page. - /// - Never -} +namespace ActiveLogin.Authentication.BankId.Core.Launcher; + +/// +/// Represents the reload behaviour of the browser when returning from the BankID app. +/// +public enum BrowserReloadBehaviourOnReturnFromBankIdApp +{ + /// + /// Use the default implementation in Active Login. + /// + Default = 0, + + /// + /// The device will always reload the page. + /// + Always, + + /// + /// The device will never reload the page. + /// + Never +} diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs index b9b77cf3..9282ba1b 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs @@ -1,10 +1,7 @@ -using ActiveLogin.Authentication.BankId.Core.SupportedDevice; - namespace ActiveLogin.Authentication.BankId.Core.Launcher; public interface IBankIdLauncherCustomAppCallback { public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context); - public Task GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context); - public ReloadBehaviourOnReturnFromBankIdApp ReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice) => ReloadBehaviourOnReturnFromBankIdApp.Default; + public Task GetCustomAppCallbackResult(BankIdLauncherCustomAppCallbackContext context); } diff --git a/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs b/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs index 10409079..ead92666 100644 --- a/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs +++ b/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs @@ -40,14 +40,12 @@ public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context) return Task.FromResult(true); } - public Task GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context) + public Task GetCustomAppCallbackResult(BankIdLauncherCustomAppCallbackContext context) { - return Task.FromResult("/return"); + return Task.FromResult( + new BankIdLauncherCustomAppCallbackResult("/return", BrowserReloadBehaviourOnReturnFromBankIdApp.Always) + ); } - - public ReloadBehaviourOnReturnFromBankIdApp - ReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice) => - ReloadBehaviourOnReturnFromBankIdApp.Always; } private class TestBankIdSupportedDeviceDetector : IBankIdSupportedDeviceDetector From c294d6be5960db6181a0e219a30de5462cd1712d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C3=96rneholm?= Date: Fri, 5 Jan 2024 15:31:49 +0100 Subject: [PATCH 2/6] Rename things --- BREAKINGCHANGES.md | 13 +++ docs/articles/bankid.md | 34 +++++-- samples/Standalone.MvcSample/Program.cs | 4 +- .../IBankIdBuilderExtensions.cs | 39 ++++---- ...> BankIdLauncherUserAgentCustomBrowser.cs} | 10 +- .../IBankIdBuilderExtensions.cs | 6 +- .../Launcher/BankIdLauncher.cs | 95 +++++++++---------- .../BankIdLauncherCustomAppCallbackResult.cs | 13 --- .../BankIdLauncherCustomBrowserConfig.cs | 29 ++++++ ... => BankIdLauncherCustomBrowserContext.cs} | 4 +- ...wserMightRequireUserInteractionToLaunch.cs | 22 +++++ ...serReloadBehaviourOnReturnFromBankIdApp.cs | 4 +- .../IBankIdLauncherCustomAppCallback.cs | 7 -- .../Launcher/IBankIdLauncherCustomBrowser.cs | 7 ++ .../BankIdLauncher_Tests.cs | 12 +-- 15 files changed, 182 insertions(+), 117 deletions(-) rename src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/{BankIdLauncherUserAgentCustomAppCallback.cs => BankIdLauncherUserAgentCustomBrowser.cs} (56%) delete mode 100644 src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs create mode 100644 src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserConfig.cs rename src/ActiveLogin.Authentication.BankId.Core/Launcher/{BankIdLauncherCustomAppCallbackContext.cs => BankIdLauncherCustomBrowserContext.cs} (65%) create mode 100644 src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserMightRequireUserInteractionToLaunch.cs delete mode 100644 src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs create mode 100644 src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomBrowser.cs diff --git a/BREAKINGCHANGES.md b/BREAKINGCHANGES.md index c4cc4825..b06b379d 100644 --- a/BREAKINGCHANGES.md +++ b/BREAKINGCHANGES.md @@ -21,6 +21,19 @@ ___Note:___ We might, and will probably, miss to document some of this - if so - Breaking changes between version 8.0.0 and 7.0.0 +### IBankIdLauncherCustomAppCallback becomes IBankIdLauncherCustomBrowser + +We have broadedned the scope of the interface `IBankIdLauncherCustomAppCallback` to `IBankIdLauncherCustomBrowser` to allow for more flexibility in the implementation. + +We have renamed these things as a result of that: +* `IBankIdLauncherCustomAppCallback` becomes `IBankIdLauncherCustomBrowser` +* `AddCustomAppCallback` becomes `AddCustomBrowser` +* `AddCustomAppCallbackByUserAgent` becomes `AddCustomBrowserByUserAgent` + +Also, the return URL is now only applied on iOS, as the expected behaviour on Android is to apply null so that Android automatically can return to the previous app. + +```csharp + ### Upgrade to .NET 7 We now require .NET 8 - so this requires you to upgrade your website that uses Active Login. diff --git a/docs/articles/bankid.md b/docs/articles/bankid.md index 37480b6e..8f094f37 100644 --- a/docs/articles/bankid.md +++ b/docs/articles/bankid.md @@ -1077,12 +1077,16 @@ In Active Login device and browser detection is required for example to determin The default implementation provided in `ActiveLogin.Authentication.BankId.AspNetCore` is limited to supports the ~top 5 most common browsers on both iOS and Android. But since an incorrect browser detection can lead to an incorrect launch URL and result in a broken user flow, `UAParserDeviceDetector` in the `ActiveLogin.Authentication.BankId.UAParser` package should be used to support additional browsers. It has a dependency on package [uap-csharp](https://github.com/ua-parser/uap-csharp) for improved user agent parsing. -#### Shorthand for only overriding return URL for custom apps +#### Shorthand for only overriding config for custom browsers -If you want to support your custom app, or a third party app (like the built in browsers in Instagram, Facebook etc.) we've made it simple to support those scenarios by allowing you to specify a custom return URL. +If you want to support your custom app, or a third party app (like the built in browsers in Instagram, Facebook etc.) we've made it simple to support those scenarios by allowing you to specify a custom browser config. The most common scenario is that you will set the schema for the app as return URL if you detect a specific User Agent, so for that scenario we've made an extension method. +Note: The return url will onlt by applied on iOS, as Android will return the user to the app automatically. + +```csharp + In the sample below we add support for Instagram and Facebook: ```csharp @@ -1091,14 +1095,28 @@ services { // ... - bankId.AddCustomAppCallbackByUserAgent(userAgent => userAgent.Contains("Instagram"), "instagram://"); - bankId.AddCustomAppCallbackByUserAgent(userAgent => userAgent.Contains("FBAN") || userAgent.Contains("FBAV"), "fb://"); + bankId.AddCustomBrowserByUserAgent(userAgent => userAgent.Contains("Instagram"), "instagram://"); + bankId.AddCustomBrowserByUserAgent(userAgent => userAgent.Contains("FBAN") || userAgent.Contains("FBAV"), "fb://"); + + // ... + }); +``` + +If you need, you can also specify the reload behaviour on the custom browser: + +```csharp +services + .AddBankId(bankId => + { + // ... + + bankId.AddCustomBrowserByUserAgent(userAgent => userAgent.Contains("Instagram"), new BankIdLauncherUserAgentCustomBrowser("instagram://", BrowserReloadBehaviourOnReturnFromBankIdApp.Never)); // ... }); ``` -If you need to do something custom, you can implement `IBankIdLauncherCustomAppCallback`: +If you need to do something custom, you can implement `IBankIdLauncherCustomBrowser`: ```csharp services @@ -1106,14 +1124,14 @@ services { // ... - bankId.AddCustomAppCallback(); + bankId.AddCustomBrowser(); // ... }); ``` ```csharp -public class BankIdFacebookAppCallback : IBankIdLauncherCustomAppCallback +public class BankIdFacebookAppBrowserConfig : IBankIdLauncherCustomAppCallback { private readonly IHttpContextAccessor _httpContextAccessor; @@ -1137,7 +1155,7 @@ public class BankIdFacebookAppCallback : IBankIdLauncherCustomAppCallback public Task GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context) { return Task.FromResult( - new BankIdLauncherCustomAppCallbackResult("fb://", BrowserReloadBehaviourOnReturnFromBankIdApp.Never) + new BankIdLauncherCustomAppCallbackResult("fb://", BrowserReloadBehaviourOnReturnFromBankIdApp.Never, BrowserMightRequireUserInteractionToLaunch.Default) ); } } diff --git a/samples/Standalone.MvcSample/Program.cs b/samples/Standalone.MvcSample/Program.cs index e4fbb8e5..3c5e38c7 100644 --- a/samples/Standalone.MvcSample/Program.cs +++ b/samples/Standalone.MvcSample/Program.cs @@ -64,8 +64,8 @@ bankId.UseQrCoderQrCodeGenerator(); bankId.UseUaParserDeviceDetection(); - bankId.AddCustomAppCallbackByUserAgent(userAgent => userAgent.Contains("Instagram"), "instagram://"); - bankId.AddCustomAppCallbackByUserAgent(userAgent => userAgent.Contains("FBAN") || userAgent.Contains("FBAV"), "fb://"); + bankId.AddCustomBrowserByUserAgent(userAgent => userAgent.Contains("Instagram"), "instagram://"); + bankId.AddCustomBrowserByUserAgent(userAgent => userAgent.Contains("FBAN") || userAgent.Contains("FBAV"), "fb://"); if (configuration.GetValue("ActiveLogin:BankId:UseSimulatedEnvironment", false)) { diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs b/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs index be9a6d16..62691619 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs @@ -11,48 +11,47 @@ public static class IBankIdBuilderExtensions { /// /// Adds a custom return url resolver. + /// + /// + /// + /// + /// + public static IBankIdBuilder AddCustomBrowserByUserAgent(this IBankIdBuilder builder, Func isApplicable, string returnUrl) + { + return AddCustomBrowserByUserAgent(builder, isApplicable, context => returnUrl); + } + + /// + /// Adds support for a custom browser (like a third party app). /// When only returnUrl is specified, the reload behaviour will fall back to "Never". As we know, only Safari on iOS have the Always behaviour. /// /// /// /// /// - public static IBankIdBuilder AddCustomAppCallbackByUserAgent(this IBankIdBuilder builder, Func isApplicable, Func getReturnUrl) + public static IBankIdBuilder AddCustomBrowserByUserAgent(this IBankIdBuilder builder, Func isApplicable, Func getReturnUrl) { - Func getResult = - (context) => new(getReturnUrl(context), BrowserReloadBehaviourOnReturnFromBankIdApp.Never); + BankIdLauncherCustomBrowserConfig GetResult(BankIdLauncherCustomBrowserContext context) => new(getReturnUrl(context), BrowserReloadBehaviourOnReturnFromBankIdApp.Never); - return AddCustomAppCallbackByUserAgent(builder, isApplicable, getResult); + return AddCustomBrowserByUserAgent(builder, isApplicable, GetResult); } /// - /// Adds a custom return url resolver. + /// Adds support for a custom browser (like a third party app). /// /// /// /// /// - public static IBankIdBuilder AddCustomAppCallbackByUserAgent(this IBankIdBuilder builder, Func isApplicable, Func getResult) + public static IBankIdBuilder AddCustomBrowserByUserAgent(this IBankIdBuilder builder, Func isApplicable, Func getResult) { - builder.Services.AddTransient(x => + builder.Services.AddTransient(x => { var httpContextAccessor = x.GetRequiredService(); - var customApp = new BankIdLauncherUserAgentCustomAppCallback(httpContextAccessor, isApplicable, getResult); + var customApp = new BankIdLauncherUserAgentCustomBrowser(httpContextAccessor, isApplicable, getResult); return customApp; }); return builder; } - - /// - /// Adds a custom return url resolver. - /// - /// - /// - /// - /// - public static IBankIdBuilder AddCustomAppCallbackByUserAgent(this IBankIdBuilder builder, Func isApplicable, string returnUrl) - { - return AddCustomAppCallbackByUserAgent(builder, isApplicable, context => returnUrl); - } } diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomBrowser.cs similarity index 56% rename from src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs rename to src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomBrowser.cs index 6c75c8e3..f698ac00 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomBrowser.cs @@ -4,20 +4,20 @@ namespace ActiveLogin.Authentication.BankId.AspNetCore.Launcher; -public class BankIdLauncherUserAgentCustomAppCallback : IBankIdLauncherCustomAppCallback +public class BankIdLauncherUserAgentCustomBrowser : IBankIdLauncherCustomBrowser { private readonly IHttpContextAccessor _httpContextAccessor; private readonly Func _isApplicable; - private readonly Func _getResult; + private readonly Func _getResult; - public BankIdLauncherUserAgentCustomAppCallback(IHttpContextAccessor httpContextAccessor, Func isApplicable, Func getResult) + public BankIdLauncherUserAgentCustomBrowser(IHttpContextAccessor httpContextAccessor, Func isApplicable, Func getResult) { _httpContextAccessor = httpContextAccessor; _isApplicable = isApplicable; _getResult = getResult; } - public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context) + public Task IsApplicable(BankIdLauncherCustomBrowserContext context) { var userAgent = _httpContextAccessor.HttpContext?.Request.Headers.UserAgent.FirstOrDefault(); if (string.IsNullOrWhiteSpace(userAgent)) @@ -29,7 +29,7 @@ public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context) return Task.FromResult(isApplicable); } - public Task GetCustomAppCallbackResult(BankIdLauncherCustomAppCallbackContext context) + public Task GetCustomAppCallbackResult(BankIdLauncherCustomBrowserContext context) { var result = _getResult(context); return Task.FromResult(result); diff --git a/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs b/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs index 8ad1ffee..cad65cac 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs @@ -124,14 +124,14 @@ public static IBankIdBuilder AddResultStore(this IBankIdBuilder } /// - /// Adds a class to resolve custom return url. + /// Adds a class to resolve custom browser config. /// /// /// /// - public static IBankIdBuilder AddCustomAppCallback(this IBankIdBuilder builder) where TImplementation : class, IBankIdLauncherCustomAppCallback + public static IBankIdBuilder AddCustomBrowser(this IBankIdBuilder builder) where TImplementation : class, IBankIdLauncherCustomBrowser { - builder.Services.AddTransient(); + builder.Services.AddTransient(); return builder; } diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs index 9bfaae71..0fdf1cf7 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs @@ -20,45 +20,52 @@ internal class BankIdLauncher : IBankIdLauncher private const string IosFirefoxScheme = "firefox://"; private readonly IBankIdSupportedDeviceDetector _bankIdSupportedDeviceDetector; - private readonly List _customAppCallbacks; + private readonly List _customBrowsers; - public BankIdLauncher(IBankIdSupportedDeviceDetector bankIdSupportedDeviceDetector, IEnumerable customAppCallbacks) + public BankIdLauncher(IBankIdSupportedDeviceDetector bankIdSupportedDeviceDetector, IEnumerable customBrowsers) { _bankIdSupportedDeviceDetector = bankIdSupportedDeviceDetector; - _customAppCallbacks = customAppCallbacks.ToList(); + _customBrowsers = customBrowsers.ToList(); } public async Task GetLaunchInfoAsync(LaunchUrlRequest request) { var detectedDevice = _bankIdSupportedDeviceDetector.Detect(); - var deviceMightRequireUserInteractionToLaunch = GetDeviceMightRequireUserInteractionToLaunchBankIdApp(detectedDevice); - var customAppCallbackContext = new BankIdLauncherCustomAppCallbackContext(detectedDevice, request); - var customAppCallback = await GetRelevantCustomAppCallbackAsync(customAppCallbackContext, _customAppCallbacks); - var customAppCallbackResult = customAppCallback != null ? (await customAppCallback.GetCustomAppCallbackResult(customAppCallbackContext)) : null; + var customBrowserContext = new BankIdLauncherCustomBrowserContext(detectedDevice, request); + var customBrowser = await GetRelevantCustomAppCallbackAsync(customBrowserContext, _customBrowsers); + var customBrowserConfig = customBrowser != null ? (await customBrowser.GetCustomAppCallbackResult(customBrowserContext)) : null; + + var deviceMightRequireUserInteractionToLaunch = GetDeviceMightRequireUserInteractionToLaunchBankIdApp(detectedDevice, customBrowserConfig); + var deviceWillReloadPageOnReturn = GetDeviceWillReloadPageOnReturnFromBankIdApp(detectedDevice, customBrowserConfig); + var launchUrl = GetLaunchUrl(detectedDevice, request, customBrowserConfig); - var deviceWillReloadPageOnReturn = GetDeviceWillReloadPageOnReturnFromBankIdApp(detectedDevice, customAppCallbackResult); - var launchUrl = GetLaunchUrl(detectedDevice, request, customAppCallbackResult); - return new BankIdLaunchInfo(launchUrl, deviceMightRequireUserInteractionToLaunch, deviceWillReloadPageOnReturn); } - private bool GetDeviceMightRequireUserInteractionToLaunchBankIdApp(BankIdSupportedDevice detectedDevice) + private bool GetDeviceMightRequireUserInteractionToLaunchBankIdApp(BankIdSupportedDevice detectedDevice, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { - // On Android, some browsers will (for security reasons) not launching a - // third party app/scheme (BankID) if there is no user interaction. - // - // - Chrome, Edge, Samsung Internet Browser and Brave is confirmed to require User Interaction - // - Firefox and Opera is confirmed to work without User Interaction - - return detectedDevice.DeviceOs == BankIdSupportedDeviceOs.Android - && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Firefox - && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Opera; + var userInteractionBehaviour = customBrowserConfig?.BrowserMightRequireUserInteractionToLaunch ?? BrowserMightRequireUserInteractionToLaunch.Default; + + return userInteractionBehaviour switch + { + BrowserMightRequireUserInteractionToLaunch.Always => true, + BrowserMightRequireUserInteractionToLaunch.Never => false, + + // On Android, some browsers will (for security reasons) not launching a + // third party app/scheme (BankID) if there is no user interaction. + // + // - Chrome, Edge, Samsung Internet Browser and Brave is confirmed to require User Interaction + // - Firefox and Opera is confirmed to work without User Interaction + _ => detectedDevice.DeviceOs == BankIdSupportedDeviceOs.Android + && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Firefox + && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Opera + }; } - private bool GetDeviceWillReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice, BankIdLauncherCustomAppCallbackResult? customAppCallbackResult) + private bool GetDeviceWillReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { - var reloadBehaviour = customAppCallbackResult?.BrowserReloadBehaviourOnReturnFromBankIdApp ?? BrowserReloadBehaviourOnReturnFromBankIdApp.Default; + var reloadBehaviour = customBrowserConfig?.BrowserReloadBehaviourOnReturnFromBankIdApp ?? BrowserReloadBehaviourOnReturnFromBankIdApp.Default; return reloadBehaviour switch { @@ -74,10 +81,10 @@ private bool GetDeviceWillReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice }; } - private string GetLaunchUrl(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomAppCallbackResult? customAppCallback) + private string GetLaunchUrl(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { var prefix = GetPrefixPart(device); - var queryString = GetQueryStringPart(device, request, customAppCallback); + var queryString = GetQueryStringPart(device, request, customBrowserConfig); return $"{prefix}{queryString}"; } @@ -94,22 +101,12 @@ private static bool CanUseAppLink(BankIdSupportedDevice device) // Only Safari on IOS and Chrome or Edge on Android version >= 6 seems to support // the https://app.bankid.com/ launch url - return IsSafariOnIos(device) - || IsChromeOrEdgeOnAndroid6OrGreater(device); - } - - private static bool IsSafariOnIos(BankIdSupportedDevice device) - { return device is { DeviceOs: BankIdSupportedDeviceOs.Ios, DeviceBrowser: BankIdSupportedDeviceBrowser.Safari - }; - } - - private static bool IsChromeOrEdgeOnAndroid6OrGreater(BankIdSupportedDevice device) - { - return device is + } + or { DeviceOs: BankIdSupportedDeviceOs.Android, DeviceOsVersion.MajorVersion: >= 6, @@ -117,7 +114,7 @@ private static bool IsChromeOrEdgeOnAndroid6OrGreater(BankIdSupportedDevice devi }; } - private string GetQueryStringPart(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomAppCallbackResult? customAppCallback) + private string GetQueryStringPart(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { var queryStringParams = new Dictionary(); @@ -131,28 +128,28 @@ private string GetQueryStringPart(BankIdSupportedDevice device, LaunchUrlRequest queryStringParams.Add(BankIdRpRefQueryStringParamName, Base64Encode(request.RelyingPartyReference)); } - var redirectUrl = GetRedirectUrl(device, request, customAppCallback); + var redirectUrl = GetRedirectUrl(device, request, customBrowserConfig); queryStringParams.Add(BankIdRedirectQueryStringParamName, redirectUrl); return QueryStringGenerator.ToQueryString(queryStringParams); } - private static string GetRedirectUrl(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomAppCallbackResult? customAppCallbackResult) + private static string GetRedirectUrl(BankIdSupportedDevice device, LaunchUrlRequest request, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { - // Allow for easy override of callback url - if (customAppCallbackResult != null && customAppCallbackResult.ReturnUrl != null) - { - return customAppCallbackResult.ReturnUrl; - } - // Only use redirect url for iOS as recommended in BankID Guidelines 3.1.2 return device.DeviceOs == BankIdSupportedDeviceOs.Ios - ? GetIOsBrowserSpecificRedirectUrl(device, request.RedirectUrl) + ? GetIOsBrowserSpecificRedirectUrl(device, request.RedirectUrl, customBrowserConfig) : NullRedirectUrl; } - private static string GetIOsBrowserSpecificRedirectUrl(BankIdSupportedDevice device, string redirectUrl) + private static string GetIOsBrowserSpecificRedirectUrl(BankIdSupportedDevice device, string redirectUrl, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { + // Allow for easy override of callback url + if (customBrowserConfig != null && customBrowserConfig.IosReturnUrl != null) + { + return customBrowserConfig.IosReturnUrl; + } + // If it is a third party browser, don't specify the return URL, just the browser scheme. // This will launch the browser with the last page used (the Active Login status page). // If a URL is specified these browsers will open that URL in a new tab and we will lose context. @@ -175,11 +172,11 @@ private static string GetIOsBrowserSpecificRedirectUrl(BankIdSupportedDevice dev }; } - private static async Task GetRelevantCustomAppCallbackAsync(BankIdLauncherCustomAppCallbackContext customAppCallbackContext, List customAppCallbacks) + private static async Task GetRelevantCustomAppCallbackAsync(BankIdLauncherCustomBrowserContext customBrowserContext, List customAppCallbacks) { foreach (var callback in customAppCallbacks) { - if (await callback.IsApplicable(customAppCallbackContext)) + if (await callback.IsApplicable(customBrowserContext)) { return callback; } diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs deleted file mode 100644 index 49031eb8..00000000 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ActiveLogin.Authentication.BankId.Core.Launcher; - -public class BankIdLauncherCustomAppCallbackResult -{ - public BankIdLauncherCustomAppCallbackResult(string? returnUrl, BrowserReloadBehaviourOnReturnFromBankIdApp browserReloadBehaviourOnReturnFromBankIdApp = BrowserReloadBehaviourOnReturnFromBankIdApp.Default) - { - ReturnUrl = returnUrl; - BrowserReloadBehaviourOnReturnFromBankIdApp = browserReloadBehaviourOnReturnFromBankIdApp; - } - - public string? ReturnUrl { get; set; } - public BrowserReloadBehaviourOnReturnFromBankIdApp BrowserReloadBehaviourOnReturnFromBankIdApp { get; set; } -} diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserConfig.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserConfig.cs new file mode 100644 index 00000000..284a66c2 --- /dev/null +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserConfig.cs @@ -0,0 +1,29 @@ +namespace ActiveLogin.Authentication.BankId.Core.Launcher; + +public class BankIdLauncherCustomBrowserConfig +{ + public BankIdLauncherCustomBrowserConfig(string? iosReturnUrl, BrowserReloadBehaviourOnReturnFromBankIdApp browserReloadBehaviourOnReturnFromBankIdApp = BrowserReloadBehaviourOnReturnFromBankIdApp.Default, BrowserMightRequireUserInteractionToLaunch browserMightRequireUserInteractionToLaunch = BrowserMightRequireUserInteractionToLaunch.Default) + { + IosReturnUrl = iosReturnUrl; + BrowserReloadBehaviourOnReturnFromBankIdApp = browserReloadBehaviourOnReturnFromBankIdApp; + BrowserMightRequireUserInteractionToLaunch = browserMightRequireUserInteractionToLaunch; + } + + /// + /// The URL that the BankID app will try to launch once the BankID app is finished. + /// Set to null to fall back to default Active Login behaviour. + /// Set to empty string to not launch any URL, and instead the BanKID app will ask the user to open the last app. + /// This will only be applied to iOS as Android automatically launches the previous app. + /// + public string? IosReturnUrl { get; set; } + + /// + /// The reload behaviour of the browser when returning from the BankID app. + /// + public BrowserReloadBehaviourOnReturnFromBankIdApp BrowserReloadBehaviourOnReturnFromBankIdApp { get; set; } + + /// + /// If the browser might require user interaction to launch the BankID app. + /// + public BrowserMightRequireUserInteractionToLaunch BrowserMightRequireUserInteractionToLaunch { get; set; } +} diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserContext.cs similarity index 65% rename from src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs rename to src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserContext.cs index 4ab22061..d75e0f91 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserContext.cs @@ -2,9 +2,9 @@ namespace ActiveLogin.Authentication.BankId.Core.Launcher; -public class BankIdLauncherCustomAppCallbackContext +public class BankIdLauncherCustomBrowserContext { - public BankIdLauncherCustomAppCallbackContext(BankIdSupportedDevice device, LaunchUrlRequest launchUrlRequest) + public BankIdLauncherCustomBrowserContext(BankIdSupportedDevice device, LaunchUrlRequest launchUrlRequest) { Device = device; LaunchUrlRequest = launchUrlRequest; diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserMightRequireUserInteractionToLaunch.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserMightRequireUserInteractionToLaunch.cs new file mode 100644 index 00000000..84141ae6 --- /dev/null +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserMightRequireUserInteractionToLaunch.cs @@ -0,0 +1,22 @@ +namespace ActiveLogin.Authentication.BankId.Core.Launcher; + +/// +/// Represents the result of a custom app launch. +/// +public enum BrowserMightRequireUserInteractionToLaunch +{ + /// + /// Use the default implementation in Active Login. + /// + Default = 0, + + /// + /// The browser will always require user interaction to launch BankID app. + /// + Always, + + /// + /// The browser will never require user interaction to launch BankID app. + /// + Never +} diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs index 266fd7fc..0bcaf496 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs @@ -11,12 +11,12 @@ public enum BrowserReloadBehaviourOnReturnFromBankIdApp Default = 0, /// - /// The device will always reload the page. + /// The browser will always reload the page. /// Always, /// - /// The device will never reload the page. + /// The browser will never reload the page. /// Never } diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs deleted file mode 100644 index 9282ba1b..00000000 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ActiveLogin.Authentication.BankId.Core.Launcher; - -public interface IBankIdLauncherCustomAppCallback -{ - public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context); - public Task GetCustomAppCallbackResult(BankIdLauncherCustomAppCallbackContext context); -} diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomBrowser.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomBrowser.cs new file mode 100644 index 00000000..e7e0508c --- /dev/null +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomBrowser.cs @@ -0,0 +1,7 @@ +namespace ActiveLogin.Authentication.BankId.Core.Launcher; + +public interface IBankIdLauncherCustomBrowser +{ + public Task IsApplicable(BankIdLauncherCustomBrowserContext context); + public Task GetCustomAppCallbackResult(BankIdLauncherCustomBrowserContext context); +} diff --git a/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs b/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs index ead92666..1c02718f 100644 --- a/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs +++ b/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs @@ -14,7 +14,7 @@ public async Task BankIdLauncher_Should_DefaultReloadBehavior() { var launcher = new BankIdLauncher( new TestBankIdSupportedDeviceDetector(), - System.Array.Empty()); + System.Array.Empty()); var info = await launcher.GetLaunchInfoAsync(new LaunchUrlRequest("", "")); @@ -26,24 +26,24 @@ public async Task BankIdLauncher_Should_UseReloadBehaviourWhenImplemented() { var launcher = new BankIdLauncher( new TestBankIdSupportedDeviceDetector(), - new [] { new TestBankIdLauncherCustomAppCallback() }); // Override behaviour on return from BankID app + new [] { new TestBankIdLauncherCustomBrowser() }); // Override behaviour on return from BankID app var info = await launcher.GetLaunchInfoAsync(new LaunchUrlRequest(string.Empty, string.Empty)); Assert.True(info.DeviceWillReloadPageOnReturnFromBankIdApp); } - private class TestBankIdLauncherCustomAppCallback : IBankIdLauncherCustomAppCallback + private class TestBankIdLauncherCustomBrowser : IBankIdLauncherCustomBrowser { - public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context) + public Task IsApplicable(BankIdLauncherCustomBrowserContext context) { return Task.FromResult(true); } - public Task GetCustomAppCallbackResult(BankIdLauncherCustomAppCallbackContext context) + public Task GetCustomAppCallbackResult(BankIdLauncherCustomBrowserContext context) { return Task.FromResult( - new BankIdLauncherCustomAppCallbackResult("/return", BrowserReloadBehaviourOnReturnFromBankIdApp.Always) + new BankIdLauncherCustomBrowserConfig("/return", BrowserReloadBehaviourOnReturnFromBankIdApp.Always) ); } } From 24a9c654964460d334c3d2821ea42a427489342b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C3=96rneholm?= Date: Fri, 5 Jan 2024 15:46:41 +0100 Subject: [PATCH 3/6] Move things --- .../IBankIdBuilderExtensions.cs | 5 ++-- ...BankIdLauncherCustomBrowserByUserAgent.cs} | 4 +-- .../IBankIdBuilderExtensions.cs | 14 +++++++++++ .../Launcher/BankIdLauncher.cs | 2 +- .../BankIdLauncherCustomBrowserByContext.cs | 25 +++++++++++++++++++ 5 files changed, 44 insertions(+), 6 deletions(-) rename src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/{BankIdLauncherUserAgentCustomBrowser.cs => BankIdLauncherCustomBrowserByUserAgent.cs} (79%) create mode 100644 src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserByContext.cs diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs b/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs index 62691619..ab5d8094 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs @@ -20,7 +20,7 @@ public static IBankIdBuilder AddCustomBrowserByUserAgent(this IBankIdBuilder bui { return AddCustomBrowserByUserAgent(builder, isApplicable, context => returnUrl); } - + /// /// Adds support for a custom browser (like a third party app). /// When only returnUrl is specified, the reload behaviour will fall back to "Never". As we know, only Safari on iOS have the Always behaviour. @@ -48,8 +48,7 @@ public static IBankIdBuilder AddCustomBrowserByUserAgent(this IBankIdBuilder bui builder.Services.AddTransient(x => { var httpContextAccessor = x.GetRequiredService(); - var customApp = new BankIdLauncherUserAgentCustomBrowser(httpContextAccessor, isApplicable, getResult); - return customApp; + return new BankIdLauncherCustomBrowserByUserAgent(httpContextAccessor, isApplicable, getResult); }); return builder; diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomBrowser.cs b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherCustomBrowserByUserAgent.cs similarity index 79% rename from src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomBrowser.cs rename to src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherCustomBrowserByUserAgent.cs index f698ac00..02653d6f 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomBrowser.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherCustomBrowserByUserAgent.cs @@ -4,13 +4,13 @@ namespace ActiveLogin.Authentication.BankId.AspNetCore.Launcher; -public class BankIdLauncherUserAgentCustomBrowser : IBankIdLauncherCustomBrowser +public class BankIdLauncherCustomBrowserByUserAgent : IBankIdLauncherCustomBrowser { private readonly IHttpContextAccessor _httpContextAccessor; private readonly Func _isApplicable; private readonly Func _getResult; - public BankIdLauncherUserAgentCustomBrowser(IHttpContextAccessor httpContextAccessor, Func isApplicable, Func getResult) + public BankIdLauncherCustomBrowserByUserAgent(IHttpContextAccessor httpContextAccessor, Func isApplicable, Func getResult) { _httpContextAccessor = httpContextAccessor; _isApplicable = isApplicable; diff --git a/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs b/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs index cad65cac..06181a9c 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs @@ -136,6 +136,20 @@ public static IBankIdBuilder AddCustomBrowser(this IBankIdBuild return builder; } + /// + /// Adds support for a custom browser (like a third party app). + /// + /// + /// + /// + /// + public static IBankIdBuilder AddCustomBrowserByContext(this IBankIdBuilder builder, Func isApplicable, Func getResult) + { + builder.Services.AddTransient(x => new BankIdLauncherCustomBrowserByContext(isApplicable, getResult)); + + return builder; + } + internal static IBankIdBuilder UseEnvironment(this IBankIdBuilder builder, Uri appApiBaseUrl, Uri verifyApiBaseUrl, string environment) { SetActiveLoginContext(builder.Services, environment, BankIdUrls.AppApiVersion, BankIdUrls.VerifyApiVersion); diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs index 0fdf1cf7..88ed6df9 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs @@ -58,7 +58,7 @@ private bool GetDeviceMightRequireUserInteractionToLaunchBankIdApp(BankIdSupport // - Chrome, Edge, Samsung Internet Browser and Brave is confirmed to require User Interaction // - Firefox and Opera is confirmed to work without User Interaction _ => detectedDevice.DeviceOs == BankIdSupportedDeviceOs.Android - && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Firefox + && && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Opera }; } diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserByContext.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserByContext.cs new file mode 100644 index 00000000..9093c477 --- /dev/null +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserByContext.cs @@ -0,0 +1,25 @@ +namespace ActiveLogin.Authentication.BankId.Core.Launcher; + +public class BankIdLauncherCustomBrowserByContext : IBankIdLauncherCustomBrowser +{ + private readonly Func _isApplicable; + private readonly Func _getResult; + + public BankIdLauncherCustomBrowserByContext(Func isApplicable, Func getResult) + { + _isApplicable = isApplicable; + _getResult = getResult; + } + + public Task IsApplicable(BankIdLauncherCustomBrowserContext context) + { + var isApplicable = _isApplicable(context); + return Task.FromResult(isApplicable); + } + + public Task GetCustomAppCallbackResult(BankIdLauncherCustomBrowserContext context) + { + var result = _getResult(context); + return Task.FromResult(result); + } +} From c076f349d2ac7d96b4855a50a45eb42705155d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C3=96rneholm?= Date: Fri, 5 Jan 2024 15:49:44 +0100 Subject: [PATCH 4/6] Fix docs --- BREAKINGCHANGES.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/BREAKINGCHANGES.md b/BREAKINGCHANGES.md index b06b379d..7509ac61 100644 --- a/BREAKINGCHANGES.md +++ b/BREAKINGCHANGES.md @@ -32,8 +32,6 @@ We have renamed these things as a result of that: Also, the return URL is now only applied on iOS, as the expected behaviour on Android is to apply null so that Android automatically can return to the previous app. -```csharp - ### Upgrade to .NET 7 We now require .NET 8 - so this requires you to upgrade your website that uses Active Login. From 3a729b797a63a9420eaa3dbcdd33f581a111fa75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C3=96rneholm?= Date: Fri, 5 Jan 2024 15:50:15 +0100 Subject: [PATCH 5/6] Fix docs --- docs/articles/bankid.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/articles/bankid.md b/docs/articles/bankid.md index 8f094f37..6d9da8e2 100644 --- a/docs/articles/bankid.md +++ b/docs/articles/bankid.md @@ -1085,8 +1085,6 @@ The most common scenario is that you will set the schema for the app as return U Note: The return url will onlt by applied on iOS, as Android will return the user to the app automatically. -```csharp - In the sample below we add support for Instagram and Facebook: ```csharp From ab0b4082293e80ba8537aec8f90e3178c96c233e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C3=96rneholm?= Date: Fri, 5 Jan 2024 15:50:57 +0100 Subject: [PATCH 6/6] Fix error --- .../Launcher/BankIdLauncher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs index 88ed6df9..0fdf1cf7 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs @@ -58,7 +58,7 @@ private bool GetDeviceMightRequireUserInteractionToLaunchBankIdApp(BankIdSupport // - Chrome, Edge, Samsung Internet Browser and Brave is confirmed to require User Interaction // - Firefox and Opera is confirmed to work without User Interaction _ => detectedDevice.DeviceOs == BankIdSupportedDeviceOs.Android - && + && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Firefox && detectedDevice.DeviceBrowser != BankIdSupportedDeviceBrowser.Opera }; }