diff --git a/BREAKINGCHANGES.md b/BREAKINGCHANGES.md index c4cc4825..7509ac61 100644 --- a/BREAKINGCHANGES.md +++ b/BREAKINGCHANGES.md @@ -21,6 +21,17 @@ ___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. + ### 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 0f0c2ccb..6d9da8e2 100644 --- a/docs/articles/bankid.md +++ b/docs/articles/bankid.md @@ -1077,12 +1077,14 @@ 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. + In the sample below we add support for Instagram and Facebook: ```csharp @@ -1091,14 +1093,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 +1122,14 @@ services { // ... - bankId.AddCustomAppCallback(); + bankId.AddCustomBrowser(); // ... }); ``` ```csharp -public class BankIdFacebookAppCallback : IBankIdLauncherCustomAppCallback +public class BankIdFacebookAppBrowserConfig : IBankIdLauncherCustomAppCallback { private readonly IHttpContextAccessor _httpContextAccessor; @@ -1136,29 +1152,14 @@ public class BankIdFacebookAppCallback : IBankIdLauncherCustomAppCallback public Task GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context) { - return Task.FromResult("fb://"); + return Task.FromResult( + new BankIdLauncherCustomAppCallbackResult("fb://", BrowserReloadBehaviourOnReturnFromBankIdApp.Never, BrowserMightRequireUserInteractionToLaunch.Default) + ); } } ``` -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/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 fa87a599..ab5d8094 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/IBankIdBuilderExtensions.cs @@ -14,29 +14,43 @@ public static class IBankIdBuilderExtensions /// /// /// + /// + /// + 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) { - builder.Services.AddTransient(x => - { - var httpContextAccessor = x.GetRequiredService(); - var customApp = new BankIdLauncherUserAgentCustomAppCallback(httpContextAccessor, isApplicable, getReturnUrl); - return customApp; - }); + BankIdLauncherCustomBrowserConfig GetResult(BankIdLauncherCustomBrowserContext context) => new(getReturnUrl(context), BrowserReloadBehaviourOnReturnFromBankIdApp.Never); - return builder; + 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, string returnUrl) + public static IBankIdBuilder AddCustomBrowserByUserAgent(this IBankIdBuilder builder, Func isApplicable, Func getResult) { - return AddCustomAppCallbackByUserAgent(builder, isApplicable, context => returnUrl); + builder.Services.AddTransient(x => + { + var httpContextAccessor = x.GetRequiredService(); + return new BankIdLauncherCustomBrowserByUserAgent(httpContextAccessor, isApplicable, getResult); + }); + + return builder; } } diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherCustomBrowserByUserAgent.cs similarity index 50% rename from src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs rename to src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherCustomBrowserByUserAgent.cs index 62ddc552..02653d6f 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherUserAgentCustomAppCallback.cs +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/Launcher/BankIdLauncherCustomBrowserByUserAgent.cs @@ -4,20 +4,20 @@ namespace ActiveLogin.Authentication.BankId.AspNetCore.Launcher; -public class BankIdLauncherUserAgentCustomAppCallback : IBankIdLauncherCustomAppCallback +public class BankIdLauncherCustomBrowserByUserAgent : IBankIdLauncherCustomBrowser { 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 BankIdLauncherCustomBrowserByUserAgent(IHttpContextAccessor httpContextAccessor, Func isApplicable, Func getResult) { _httpContextAccessor = httpContextAccessor; _isApplicable = isApplicable; - _getReturnUrl = getReturnUrl; + _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,9 +29,9 @@ public Task IsApplicable(BankIdLauncherCustomAppCallbackContext context) return Task.FromResult(isApplicable); } - public Task GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context) + public Task GetCustomAppCallbackResult(BankIdLauncherCustomBrowserContext 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/IBankIdBuilderExtensions.cs b/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs index 8ad1ffee..06181a9c 100644 --- a/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs +++ b/src/ActiveLogin.Authentication.BankId.Core/IBankIdBuilderExtensions.cs @@ -124,14 +124,28 @@ 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; + } + + /// + /// 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; } diff --git a/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncher.cs index 50114c1e..0fdf1cf7 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; @@ -21,61 +20,71 @@ 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 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, customAppCallback); - var launchUrl = await GetLaunchUrl(detectedDevice, request, customAppCallback); 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, IBankIdLauncherCustomAppCallback? customAppCallback) + private bool GetDeviceWillReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { - var reloadBehaviour = customAppCallback?.ReloadPageOnReturnFromBankIdApp(detectedDevice) ?? - ReloadBehaviourOnReturnFromBankIdApp.Default; + var reloadBehaviour = customBrowserConfig?.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, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { var prefix = GetPrefixPart(device); - var queryString = await GetQueryStringPart(device, request, customAppCallback); + var queryString = GetQueryStringPart(device, request, customBrowserConfig); return $"{prefix}{queryString}"; } @@ -92,27 +101,20 @@ 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.DeviceOs == BankIdSupportedDeviceOs.Ios - && device.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.Ios, + DeviceBrowser: BankIdSupportedDeviceBrowser.Safari + } + or + { + 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, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { var queryStringParams = new Dictionary(); @@ -126,29 +128,28 @@ 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, customBrowserConfig); 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, BankIdLauncherCustomBrowserConfig? customBrowserConfig) { - // Allow for easy override of callback url - if (customAppCallback != null) - { - var customAppCallbackContext = new BankIdLauncherCustomAppCallbackContext(device, request); - return await customAppCallback.GetCustomAppReturnUrl(customAppCallbackContext); - } - // 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. @@ -171,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/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); + } +} 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 64% rename from src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomAppCallbackContext.cs rename to src/ActiveLogin.Authentication.BankId.Core/Launcher/BankIdLauncherCustomBrowserContext.cs index 3187a906..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 { - internal 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 new file mode 100644 index 00000000..0bcaf496 --- /dev/null +++ b/src/ActiveLogin.Authentication.BankId.Core/Launcher/BrowserReloadBehaviourOnReturnFromBankIdApp.cs @@ -0,0 +1,22 @@ +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 browser will always reload the page. + /// + Always, + + /// + /// 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 b9b77cf3..00000000 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/IBankIdLauncherCustomAppCallback.cs +++ /dev/null @@ -1,10 +0,0 @@ -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; -} 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/src/ActiveLogin.Authentication.BankId.Core/Launcher/ReloadBehaviourOnReturnFromBankIdApp.cs b/src/ActiveLogin.Authentication.BankId.Core/Launcher/ReloadBehaviourOnReturnFromBankIdApp.cs deleted file mode 100644 index f6a0edef..00000000 --- a/src/ActiveLogin.Authentication.BankId.Core/Launcher/ReloadBehaviourOnReturnFromBankIdApp.cs +++ /dev/null @@ -1,22 +0,0 @@ -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 -} diff --git a/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs b/test/ActiveLogin.Authentication.BankId.Core.Test/BankIdLauncher_Tests.cs index 10409079..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,28 +26,26 @@ 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 GetCustomAppReturnUrl(BankIdLauncherCustomAppCallbackContext context) + public Task GetCustomAppCallbackResult(BankIdLauncherCustomBrowserContext context) { - return Task.FromResult("/return"); + return Task.FromResult( + new BankIdLauncherCustomBrowserConfig("/return", BrowserReloadBehaviourOnReturnFromBankIdApp.Always) + ); } - - public ReloadBehaviourOnReturnFromBankIdApp - ReloadPageOnReturnFromBankIdApp(BankIdSupportedDevice detectedDevice) => - ReloadBehaviourOnReturnFromBankIdApp.Always; } private class TestBankIdSupportedDeviceDetector : IBankIdSupportedDeviceDetector