示例#1
0
        private string GetLoginUrl(BankIdLoginOptions loginOptions)
        {
            var pathBase         = Context.Request.PathBase;
            var loginUrl         = pathBase.Add(Options.LoginPath);
            var returnUrl        = UrlEncoder.Encode(pathBase.Add(Options.CallbackPath));
            var protectedOptions = UrlEncoder.Encode(_loginOptionsProtector.Protect(loginOptions));

            return($"{loginUrl}" +
                   $"?returnUrl={returnUrl}" +
                   $"&loginOptions={protectedOptions}");
        }
示例#2
0
        private string GetStatusMessage(CollectResponse collectResponse, BankIdLoginOptions unprotectedLoginOptions, HttpRequest request)
        {
            var authPersonalIdentityNumberProvided = PersonalIdentityNumberProvided(unprotectedLoginOptions);
            var detectedDevice           = _bankIdSupportedDeviceDetector.Detect(request.Headers["User-Agent"]);
            var accessedFromMobileDevice = detectedDevice.IsMobile;

            var messageShortName = _bankIdUserMessage.GetMessageShortNameForCollectResponse(collectResponse.GetCollectStatus(), collectResponse.GetCollectHintCode(), authPersonalIdentityNumberProvided, accessedFromMobileDevice);
            var statusMessage    = _bankIdUserMessageLocalizer.GetLocalizedString(messageShortName);

            return(statusMessage);
        }
示例#3
0
 internal BankIdLoginViewModel(string returnUrl, string cancelReturnUrl, bool autoLogin, string personalIdentityNumber, string loginOptions, BankIdLoginOptions unprotectedLoginOptions, BankIdLoginScriptOptions loginScriptOptions, string loginScriptOptionsJson, string antiXsrfRequestToken)
 {
     ReturnUrl               = returnUrl;
     CancelReturnUrl         = cancelReturnUrl;
     AutoLogin               = autoLogin;
     PersonalIdentityNumber  = personalIdentityNumber;
     LoginOptions            = loginOptions;
     UnprotectedLoginOptions = unprotectedLoginOptions;
     LoginScriptOptions      = loginScriptOptions;
     LoginScriptOptionsJson  = loginScriptOptionsJson;
     AntiXsrfRequestToken    = antiXsrfRequestToken;
 }
示例#4
0
        private static MessageShortName GetInitialStatusMessage(BankIdLoginOptions loginOptions)
        {
            if (loginOptions.AutoLaunch)
            {
                return(MessageShortName.RFA13);
            }

            if (loginOptions.UseQrCode)
            {
                return(MessageShortName.RFA1QR);
            }

            return(MessageShortName.RFA1);
        }
示例#5
0
        public async Task Api_Always_Returns_CamelCase_Json_For_Http200Ok()
        {
            // Arrange mocks
            var autoLaunchOptions = new BankIdLoginOptions(new List <string>(), null, false, true, false, false, string.Empty);
            var mockProtector     = new Mock <IBankIdLoginOptionsProtector>();

            mockProtector
            .Setup(protector => protector.Unprotect(It.IsAny <string>()))
            .Returns(autoLaunchOptions);

            using var client = CreateServer(
                      o =>
            {
                o.UseSimulatedEnvironment().AddSameDevice();
                o.AuthenticationBuilder.Services.AddTransient <IBankIdLauncher, TestBankIdLauncher>();
            },
                      DefaultAppConfiguration(async context =>
            {
                await context.ChallengeAsync(BankIdDefaults.SameDeviceAuthenticationScheme);
            }),
                      services =>
            {
                services.AddTransient(s => mockProtector.Object);
                services.AddMvc().AddJsonOptions(configure =>
                {
                    configure.JsonSerializerOptions.PropertyNamingPolicy = null;
                });
            })
                               .CreateClient();


            // Arrange acting request
            var testReturnUrl         = "/TestReturnUrl";
            var testOptions           = "TestOptions";
            var initializeRequestBody = new { returnUrl = testReturnUrl, loginOptions = testOptions };

            //Act
            var initializeTransaction = await GetInitializeResponse(client, initializeRequestBody);

            // Assert
            Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode);

            var responseContent = await initializeTransaction.Content.ReadAsStringAsync();

            Assert.Contains("redirectUri", responseContent);
            Assert.Contains("orderRef", responseContent);
            Assert.Contains("isAutoLaunch", responseContent);
        }
示例#6
0
        public async Task AutoLaunch_Sets_Correct_RedirectUri()
        {
            // Arrange mocks
            var autoLaunchOptions = new BankIdLoginOptions(new List <string>(), null, false, true, false, false, string.Empty);
            var mockProtector     = new Mock <IBankIdLoginOptionsProtector>();

            mockProtector
            .Setup(protector => protector.Unprotect(It.IsAny <string>()))
            .Returns(autoLaunchOptions);

            using var client = CreateServer(
                      o =>
            {
                o.UseSimulatedEnvironment().AddSameDevice();
                o.AuthenticationBuilder.Services.AddTransient <IBankIdLauncher, TestBankIdLauncher>();
            },
                      DefaultAppConfiguration(async context =>
            {
                await context.ChallengeAsync(BankIdDefaults.SameDeviceAuthenticationScheme);
            }),
                      services =>
            {
                services.AddTransient(s => mockProtector.Object);
            })
                               .CreateClient();

            // Arrange acting request
            var testReturnUrl         = "/TestReturnUrl";
            var testOptions           = "TestOptions";
            var initializeRequestBody = new { returnUrl = testReturnUrl, loginOptions = testOptions };

            // Act
            var initializeTransaction = await GetInitializeResponse(client, initializeRequestBody);

            // Assert
            Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode);

            var responseContent = await initializeTransaction.Content.ReadAsStringAsync();

            var responseObject = JsonConvert.DeserializeAnonymousType(responseContent, new { RedirectUri = "", OrderRef = "", IsAutoLaunch = false });

            Assert.True(responseObject.IsAutoLaunch);

            var encodedReturnParam = UrlEncoder.Default.Encode(testReturnUrl);
            var expectedUrl        = $"http://localhost/BankIdAuthentication/Login?returnUrl={encodedReturnParam}&loginOptions={testOptions}";

            Assert.Equal(expectedUrl, responseObject.RedirectUri);
        }
示例#7
0
        private string GetStatusMessage(CollectResponse collectResponse, BankIdLoginOptions unprotectedLoginOptions, BankIdSupportedDevice detectedDevice)
        {
            var authPersonalIdentityNumberProvided = PersonalIdentityNumberProvided(unprotectedLoginOptions);
            var accessedFromMobileDevice           = detectedDevice.DeviceType == BankIdSupportedDeviceType.Mobile;
            var usingQrCode = unprotectedLoginOptions.UseQrCode;

            var messageShortName = _bankIdUserMessage.GetMessageShortNameForCollectResponse(
                collectResponse.GetCollectStatus(),
                collectResponse.GetCollectHintCode(),
                authPersonalIdentityNumberProvided,
                accessedFromMobileDevice,
                usingQrCode);
            var statusMessage = _bankIdUserMessageLocalizer.GetLocalizedString(messageShortName);

            return(statusMessage);
        }
        protected override Task HandleChallengeAsync(AuthenticationProperties properties)
        {
            AppendStateCookie(properties);

            var loginOptions = new BankIdLoginOptions(
                Options.BankIdCertificatePolicies,
                GetSwedishPersonalIdentityNumber(properties),
                Options.BankIdAllowChangingPersonalIdentityNumber,
                Options.BankIdAutoLaunch,
                Options.BankIdAllowBiometric
                );
            var loginUrl = GetLoginUrl(loginOptions);

            Response.Redirect(loginUrl);

            return(Task.CompletedTask);
        }
示例#9
0
        protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
        {
            AppendStateCookie(properties);

            var loginOptions = new BankIdLoginOptions(
                Options.BankIdCertificatePolicies,
                GetSwedishPersonalIdentityNumber(properties),
                Options.BankIdAllowChangingPersonalIdentityNumber,
                Options.BankIdAutoLaunch,
                Options.BankIdAllowBiometric,
                Options.BankIdUseQrCode,
                GetCancelReturnUrl(properties)
                );
            var loginUrl = GetLoginUrl(loginOptions);

            Response.Redirect(loginUrl);

            await _bankIdEventTrigger.TriggerAsync(new BankIdAspNetChallengeSuccessEvent(loginOptions));
        }
 public string Protect(BankIdLoginOptions loginOptions)
 {
     return(_secureDataFormat.Protect(loginOptions));
 }
示例#11
0
        public async Task AutoLaunch_Sets_Correct_RedirectUri()
        {
            // Arrange mocks
            var autoLaunchOptions = new BankIdLoginOptions(new List <string>(), null, false, true, false, false, string.Empty);
            var mockProtector     = new Mock <IBankIdLoginOptionsProtector>();

            mockProtector
            .Setup(protector => protector.Unprotect(It.IsAny <string>()))
            .Returns(autoLaunchOptions);

            using var client = CreateServer(
                      o =>
            {
                o.AuthenticationBuilder.Services.TryAddTransient <IBankIdLauncher, TestBankIdLauncher>();
                o.UseSimulatedEnvironment().AddSameDevice();
            },
                      DefaultAppConfiguration(async context =>
            {
                await context.ChallengeAsync(BankIdDefaults.SameDeviceAuthenticationScheme);
            }),
                      services =>
            {
                services.AddTransient(s => mockProtector.Object);
            })
                               .CreateClient();

            // Arrange csrf info
            var loginResponse = await client.GetAsync("/BankIdAuthentication/Login?returnUrl=%2F&loginOptions=X&orderRef=Y");

            var loginCookies = loginResponse.Headers.GetValues("set-cookie");
            var loginContent = await loginResponse.Content.ReadAsStringAsync();

            var document = await HtmlDocumentHelper.FromContent(loginResponse.Content);

            var csrfToken = document.GetRequestVerificationToken();

            // Arrange acting request
            var testReturnUrl     = "/TestReturnUrl";
            var testOptions       = "TestOptions";
            var initializeRequest = new JsonContent(new { returnUrl = testReturnUrl, loginOptions = testOptions });

            initializeRequest.Headers.Add("Cookie", loginCookies);
            initializeRequest.Headers.Add("RequestVerificationToken", csrfToken);

            // Act
            var transaction = await client.PostAsync("/BankIdAuthentication/Api/Initialize", initializeRequest);

            // Assert
            Assert.Equal(HttpStatusCode.OK, transaction.StatusCode);

            var responseContent = await transaction.Content.ReadAsStringAsync();

            var responseObject = JsonConvert.DeserializeAnonymousType(responseContent, new { RedirectUri = "", OrderRef = "", IsAutoLaunch = false });

            Assert.True(responseObject.IsAutoLaunch);

            var encodedReturnParam = UrlEncoder.Default.Encode(testReturnUrl);
            var expectedUrl        = $"http://localhost/BankIdAuthentication/Login?returnUrl={encodedReturnParam}&loginOptions={testOptions}";

            Assert.Equal(expectedUrl, responseObject.RedirectUri);
        }
 internal BankIdCollectCompletedEvent(string orderRef, CompletionData completionData, BankIdSupportedDevice detectedUserDevice, BankIdLoginOptions idOptions)
     : base(BankIdEventTypes.CollectCompletedId, BankIdEventTypes.CollectCompletedName, BankIdEventSeverity.Success)
 {
     OrderRef           = orderRef;
     CompletionData     = completionData;
     DetectedUserDevice = detectedUserDevice;
     BankIdOptions      = idOptions;
 }
 internal BankIdCollectFailureEvent(string orderRef, CollectHintCode hintCode, BankIdSupportedDevice detectedUserDevice, BankIdLoginOptions idOptions)
     : base(BankIdEventTypes.CollectFailureId, BankIdEventTypes.CollectFailureName, BankIdEventSeverity.Failure)
 {
     OrderRef           = orderRef;
     HintCode           = hintCode;
     DetectedUserDevice = detectedUserDevice;
     BankIdOptions      = idOptions;
 }
 internal BankIdAuthErrorEvent(PersonalIdentityNumber?personalIdentityNumber, BankIdApiException bankIdApiException, BankIdSupportedDevice detectedUserDevice, BankIdLoginOptions idOptions)
     : base(BankIdEventTypes.AuthErrorEventId, BankIdEventTypes.AuthErrorEventName, BankIdEventSeverity.Error)
 {
     PersonalIdentityNumber = personalIdentityNumber;
     BankIdApiException     = bankIdApiException;
     DetectedUserDevice     = detectedUserDevice;
     BankIdOptions          = idOptions;
 }
 public static bool IsAutoLogin(this BankIdLoginOptions bankIdLoginOptions)
 {
     return(!bankIdLoginOptions.AllowChangingPersonalIdentityNumber ||
            bankIdLoginOptions.UseQrCode);
 }
示例#16
0
        private async Task <ActionResult> CollectPending(CollectResponse collectResponse, string statusMessage, BankIdSupportedDevice detectedDevice, BankIdLoginOptions loginOptions)
        {
            await _bankIdEventTrigger.TriggerAsync(new BankIdCollectPendingEvent(collectResponse.OrderRef, collectResponse.GetCollectHintCode(), detectedDevice, loginOptions));

            return(OkJsonResult(BankIdLoginApiStatusResponse.Pending(statusMessage)));
        }
示例#17
0
        private AuthRequest GetAuthRequest(SwedishPersonalIdentityNumber personalIdentityNumber, BankIdLoginOptions loginOptions)
        {
            var endUserIp                    = GetEndUserIp();
            var certificatePolicies          = loginOptions.CertificatePolicies?.Any() ?? false ? loginOptions.CertificatePolicies : null;
            var personalIdentityNumberString = personalIdentityNumber?.To12DigitString();
            var autoStartTokenRequired       = string.IsNullOrEmpty(personalIdentityNumberString) ? true : (bool?)null;

            var authRequestRequirement = new Requirement(certificatePolicies, autoStartTokenRequired, loginOptions.AllowBiometric);

            return(new AuthRequest(endUserIp, personalIdentityNumberString, authRequestRequirement));
        }
示例#18
0
        private async Task <ActionResult> CollectFailure(CollectResponse collectResponse, string statusMessage, BankIdSupportedDevice detectedDevice, BankIdLoginOptions loginOptions)
        {
            await _bankIdEventTrigger.TriggerAsync(new BankIdCollectFailureEvent(collectResponse.OrderRef, collectResponse.GetCollectHintCode(), detectedDevice, loginOptions));

            return(BadRequestJsonResult(new BankIdLoginApiErrorResponse(statusMessage)));
        }
示例#19
0
 private string GetLoginUrl(BankIdLoginOptions loginOptions)
 {
     return($"{Options.LoginPath}" +
            $"?returnUrl={UrlEncoder.Encode(Options.CallbackPath)}" +
            $"&loginOptions={UrlEncoder.Encode(_loginOptionsProtector.Protect(loginOptions))}");
 }
示例#20
0
        private async Task <AuthRequest> GetAuthRequest(PersonalIdentityNumber?personalIdentityNumber, BankIdLoginOptions loginOptions)
        {
            var endUserIp = _bankIdEndUserIpResolver.GetEndUserIp(HttpContext);
            var personalIdentityNumberString = personalIdentityNumber?.To12DigitString();
            var tokenStartRequired           = string.IsNullOrEmpty(personalIdentityNumberString) ? true : (bool?)null;

            List <string>?certificatePolicies = null;

            if (loginOptions.CertificatePolicies != null && loginOptions.CertificatePolicies.Any())
            {
                certificatePolicies = loginOptions.CertificatePolicies;
            }

            var authRequestRequirement = new Requirement(certificatePolicies, tokenStartRequired, loginOptions.AllowBiometric);

            var authRequestContext = new BankIdAuthRequestContext(endUserIp, personalIdentityNumberString, authRequestRequirement);
            var userData           = await _bankIdAuthUserDataResolver.GetUserDataAsync(authRequestContext, HttpContext);

            return(new AuthRequest(endUserIp, personalIdentityNumberString, authRequestRequirement, userData.UserVisibleData, userData.UserNonVisibleData, userData.UserVisibleDataFormat));
        }
 internal BankIdCollectErrorEvent(string orderRef, BankIdApiException bankIdApiException, BankIdSupportedDevice detectedUserDevice, BankIdLoginOptions idOptions)
     : base(BankIdEventTypes.CollectErrorId, BankIdEventTypes.CollectErrorName, BankIdEventSeverity.Error)
 {
     OrderRef           = orderRef;
     BankIdApiException = bankIdApiException;
     DetectedUserDevice = detectedUserDevice;
     BankIdOptions      = idOptions;
 }
        public async Task Cancel_Calls_CancelApi()
        {
            // Arrange mocks
            var autoLaunchOptions = new BankIdLoginOptions(new List <string>(), null, false, true, false, false, string.Empty, DefaultStateCookieName);
            var mockProtector     = new Mock <IBankIdLoginOptionsProtector>();

            mockProtector
            .Setup(protector => protector.Unprotect(It.IsAny <string>()))
            .Returns(autoLaunchOptions);
            var testBankIdApi = new TestBankIdApi(new BankIdSimulatedApiClient());

            using var server = CreateServer(
                      o =>
            {
                o.UseSimulatedEnvironment().AddSameDevice();
                o.AuthenticationBuilder.Services.AddTransient <IBankIdLauncher, TestBankIdLauncher>();
            },
                      DefaultAppConfiguration(async context =>
            {
                await context.ChallengeAsync(BankIdDefaults.SameDeviceAuthenticationScheme);
            }),
                      services =>
            {
                services.AddTransient(s => mockProtector.Object);
                services.AddSingleton <IBankIdApiClient>(s => testBankIdApi);
            });

            // Arrange csrf info
            var loginRequest  = CreateRequestWithStateCookie(server, "/BankIdAuthentication/Login?returnUrl=%2F&loginOptions=X&orderRef=Y");
            var loginResponse = await loginRequest.GetAsync();

            var loginCookies = loginResponse.Headers.GetValues("set-cookie");
            var document     = await HtmlDocumentHelper.FromContent(loginResponse.Content);

            var csrfToken = document.GetRequestVerificationToken();

            // Arrange acting request
            var testReturnUrl     = "/TestReturnUrl";
            var testOptions       = "TestOptions";
            var initializeRequest = new JsonContent(new { returnUrl = testReturnUrl, loginOptions = testOptions });

            initializeRequest.Headers.Add("Cookie", loginCookies);
            initializeRequest.Headers.Add("RequestVerificationToken", csrfToken);

            // Act
            var client = server.CreateClient();
            var initializeTransaction = await client.PostAsync("/BankIdAuthentication/Api/Initialize", initializeRequest);

            var initializeResponseContent = await initializeTransaction.Content.ReadAsStringAsync();

            var initializeObject = JsonConvert.DeserializeAnonymousType(initializeResponseContent, new { RedirectUri = "", OrderRef = "", IsAutoLaunch = false });

            var cancelRequest = new JsonContent(new
            {
                orderRef        = initializeObject.OrderRef,
                loginOptions    = "TestOptions",
                cancelReturnUrl = "/"
            });

            cancelRequest.Headers.Add("Cookie", loginCookies);
            cancelRequest.Headers.Add("RequestVerificationToken", csrfToken);

            // Act
            var cancelTransaction = await client.PostAsync("/BankIdAuthentication/Api/Cancel", cancelRequest);

            // Assert
            Assert.Equal(HttpStatusCode.OK, cancelTransaction.StatusCode);
            Assert.True(testBankIdApi.CancelAsyncIsCalled);
        }
 private void AddLoginOptionsProperties(Dictionary <string, string> properties, BankIdLoginOptions loginOptions)
 {
     properties.Add(PropertyName_LoginOptionsLaunchType, GetLaunchType(loginOptions.SameDevice));
     properties.Add(PropertyName_LoginOptionsUseQrCode, GetBooleanProperty(loginOptions.UseQrCode));
 }
 internal BankIdCollectPendingEvent(string orderRef, CollectHintCode hintCode, BankIdSupportedDevice detectedUserDevice, BankIdLoginOptions idOptions)
     : base(BankIdEventTypes.CollectPendingId, BankIdEventTypes.CollectPendingName, BankIdEventSeverity.Information)
 {
     OrderRef           = orderRef;
     HintCode           = hintCode;
     DetectedUserDevice = detectedUserDevice;
     BankIdOptions      = idOptions;
 }
示例#25
0
        private BankIdLoginViewModel GetLoginViewModel(string returnUrl, string loginOptions, BankIdLoginOptions unprotectedLoginOptions, AntiforgeryTokenSet antiforgeryTokens)
        {
            var loginScriptOptions = new BankIdLoginScriptOptions
            {
                RefreshIntervalMs = BankIdAuthenticationDefaults.StatusRefreshIntervalMs,

                InitialStatusMessage = _bankIdUserMessageLocalizer.GetLocalizedString(MessageShortName.RFA13),
                UnknownErrorMessage  = _bankIdUserMessageLocalizer.GetLocalizedString(MessageShortName.RFA22),

                UnsupportedBrowserErrorMessage = _localizer["UnsupportedBrowser_ErrorMessage"],

                BankIdInitializeApiUrl = Url.Action(nameof(BankIdApiController.InitializeAsync), "BankIdApi"),
                BankIdStatusApiUrl     = Url.Action(nameof(BankIdApiController.StatusAsync), "BankIdApi")
            };

            return(new BankIdLoginViewModel
            {
                ReturnUrl = returnUrl,

                AutoLogin = unprotectedLoginOptions.IsAutoLogin(),
                PersonalIdentityNumber = unprotectedLoginOptions.PersonalIdentityNumber?.To12DigitString() ?? string.Empty,

                LoginOptions = loginOptions,
                UnprotectedLoginOptions = unprotectedLoginOptions,

                AntiXsrfRequestToken = antiforgeryTokens.RequestToken,
                LoginScriptOptions = loginScriptOptions,
                LoginScriptOptionsJson = SystemRuntimeJsonSerializer.Serialize(loginScriptOptions)
            });
        }
        private AuthRequest GetAuthRequest(SwedishPersonalIdentityNumber?personalIdentityNumber, BankIdLoginOptions loginOptions)
        {
            var endUserIp = _endUserIpResolver.GetEndUserIp(HttpContext);
            var personalIdentityNumberString = personalIdentityNumber?.To12DigitString();
            var autoStartTokenRequired       = string.IsNullOrEmpty(personalIdentityNumberString) ? true : (bool?)null;

            List <string>?certificatePolicies = null;

            if (loginOptions.CertificatePolicies != null && loginOptions.CertificatePolicies.Any())
            {
                certificatePolicies = loginOptions.CertificatePolicies;
            }

            var authRequestRequirement = new Requirement(certificatePolicies, autoStartTokenRequired, loginOptions.AllowBiometric);

            return(new AuthRequest(endUserIp, personalIdentityNumberString, authRequestRequirement));
        }
示例#27
0
 private static bool PersonalIdentityNumberProvided(BankIdLoginOptions unprotectedLoginOptions)
 {
     return(unprotectedLoginOptions.AllowChangingPersonalIdentityNumber ||
            unprotectedLoginOptions.PersonalIdentityNumber != null);
 }
 internal BankIdAuthSuccessEvent(PersonalIdentityNumber?personalIdentityNumber, string orderRef, BankIdSupportedDevice detectedUserDevice, BankIdLoginOptions idOptions)
     : base(BankIdEventTypes.AuthSuccessId, BankIdEventTypes.AuthSuccessName, BankIdEventSeverity.Success)
 {
     PersonalIdentityNumber = personalIdentityNumber;
     OrderRef           = orderRef;
     DetectedUserDevice = detectedUserDevice;
     BankIdOptions      = idOptions;
 }
示例#29
0
        private async Task <ActionResult> CollectComplete(BankIdLoginApiStatusRequest request, CollectResponse collectResponse, BankIdSupportedDevice detectedDevice, BankIdLoginOptions loginOptions)
        {
            if (collectResponse.CompletionData == null)
            {
                throw new ArgumentNullException(nameof(collectResponse.CompletionData));
            }

            if (request.ReturnUrl == null)
            {
                throw new ArgumentNullException(nameof(request.ReturnUrl));
            }

            await _bankIdEventTrigger.TriggerAsync(new BankIdCollectCompletedEvent(collectResponse.OrderRef, collectResponse.CompletionData, detectedDevice, loginOptions));

            var returnUri = GetSuccessReturnUri(collectResponse.OrderRef, collectResponse.CompletionData.User, request.ReturnUrl);

            if (!Url.IsLocalUrl(returnUri))
            {
                throw new Exception(BankIdConstants.InvalidReturnUrlErrorMessage);
            }

            return(OkJsonResult(BankIdLoginApiStatusResponse.Finished(returnUri)));
        }
示例#30
0
        private BankIdLoginViewModel GetLoginViewModel(string returnUrl, string loginOptions, BankIdLoginOptions unprotectedLoginOptions, AntiforgeryTokenSet antiforgeryTokens)
        {
            var initialStatusMessage = GetInitialStatusMessage(unprotectedLoginOptions);
            var loginScriptOptions   = new BankIdLoginScriptOptions(
                Url.Action("Initialize", "BankIdApi"),
                Url.Action("Status", "BankIdApi"),
                Url.Action("Cancel", "BankIdApi")
                )
            {
                RefreshIntervalMs = BankIdDefaults.StatusRefreshIntervalMs,

                InitialStatusMessage = _bankIdUserMessageLocalizer.GetLocalizedString(initialStatusMessage),
                UnknownErrorMessage  = _bankIdUserMessageLocalizer.GetLocalizedString(MessageShortName.RFA22),

                UnsupportedBrowserErrorMessage = _localizer["UnsupportedBrowser_ErrorMessage"]
            };

            return(new BankIdLoginViewModel(
                       returnUrl,
                       Url.Content(unprotectedLoginOptions.CancelReturnUrl),
                       unprotectedLoginOptions.IsAutoLogin(),
                       unprotectedLoginOptions.PersonalIdentityNumber?.To12DigitString() ?? string.Empty,
                       loginOptions,
                       unprotectedLoginOptions,
                       loginScriptOptions,
                       SystemRuntimeJsonSerializer.Serialize(loginScriptOptions),
                       antiforgeryTokens.RequestToken
                       ));
        }