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}"); }
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); }
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; }
private static MessageShortName GetInitialStatusMessage(BankIdLoginOptions loginOptions) { if (loginOptions.AutoLaunch) { return(MessageShortName.RFA13); } if (loginOptions.UseQrCode) { return(MessageShortName.RFA1QR); } return(MessageShortName.RFA1); }
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); }
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); }
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); }
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)); }
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); }
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))); }
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)); }
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))); }
private string GetLoginUrl(BankIdLoginOptions loginOptions) { return($"{Options.LoginPath}" + $"?returnUrl={UrlEncoder.Encode(Options.CallbackPath)}" + $"&loginOptions={UrlEncoder.Encode(_loginOptionsProtector.Protect(loginOptions))}"); }
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; }
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)); }
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; }
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))); }
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 )); }