Esempio n. 1
0
        public async Task <JsonResult> SignIn([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            try
            {
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                var user = await GetUserByCredentials(clientResponse.Id);

                var credential = JsonConvert.DeserializeObject <StoredCredential>(user.Profile["PasswordlessPublicKey"].ToString());

                var result = await fido2.MakeAssertionAsync(clientResponse, options, credential.PublicKey, credential.SignatureCounter,
                                                            args => Task.FromResult(credential.UserHandle.SequenceEqual(args.UserHandle)));

                await UpdateCounter(user, credential, result.Counter);

                var claims = new List <Claim>
                {
                    new Claim(ClaimTypes.Name, user.Profile.Email)
                };

                var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));

                return(Json(result));
            }
            catch (Exception e)
            {
                return(Json(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = e.Message
                }));
            }
        }
Esempio n. 2
0
        public async Task <JsonResult> MakeAssertionTest([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            // 1. Get the assertion options we sent the client
            var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
            var options     = AssertionOptions.FromJson(jsonOptions);

            // 2. Get registered credential from database
            var creds = DemoStorage.GetCredentialById(clientResponse.Id);

            // 3. Get credential counter from database
            var storedCounter = creds.SignatureCounter;

            // 4. Create callback to check if userhandle owns the credentialId
            IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
            {
                var storedCreds = await DemoStorage.GetCredentialsByUserHandleAsync(args.UserHandle);

                return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
            };

            // 5. Make the assertion
            var res = await _lib.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter, callback);

            // 6. Store the updated counter
            DemoStorage.UpdateCounter(res.CredentialId, res.Counter);

            var testRes = new
            {
                status       = "ok",
                errorMessage = ""
            };

            // 7. return OK to client
            return(Json(testRes));
        }
Esempio n. 3
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                //var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var jsonOptions = await _distributedCache.GetStringAsync(UniqueId);

                if (string.IsNullOrEmpty(jsonOptions))
                {
                    throw new Exception("Can't get AssertionOptions from cache");
                }
                var options = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = await _fido2Storage.GetCredentialById(clientResponse.Id);

                if (creds == null)
                {
                    throw new Exception("Unknown credentials");
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = await _fido2Storage.GetCredentialsByUserHandleAsync(args.UserHandle);

                    return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _lib.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter, callback);

                // 6. Store the updated counter
                await _fido2Storage.UpdateCounter(res.CredentialId, res.Counter);

                // complete sign-in
                var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();

                if (user == null)
                {
                    throw new InvalidOperationException($"Unable to load two-factor authentication user.");
                }

                var result = await _signInManager.TwoFactorSignInAsync("FIDO2", string.Empty, false, false);

                // 7. return OK to client
                return(Json(res));
            }
            catch (Exception e)
            {
                return(Json(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
Esempio n. 4
0
        public async Task <IActionResult> Fido2LoginCallback([FromBody] AuthenticatorAssertionRawResponse clientResponse, [FromHeader] string returnUrl)
        {
            var info = await HttpContext.AuthenticateAsync(_fido2AuthenticationScheme);

            var tempUser = info?.Principal;

            if (tempUser == null)
            {
                return(Json(new { success = false }));
            }
            var user = await _users.FindByIdAsync(tempUser.GetSubjectId());

            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = _authenticationContext.FidoLogins.FirstOrDefault(x => x.PublicKeyIdBytes.SequenceEqual(clientResponse.Id));
                //DemoStorage.GetCredentialById(clientResponse.Id);

                if (creds == null)
                {
                    throw new Exception("Unknown credentials");
                }

                if (creds.UserId != user.Id)
                {
                    throw new Exception("User is not owner of credentials.");
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    return(_authenticationContext.FidoLogins.FirstOrDefault(x => x.UserHandle.SequenceEqual(args.UserHandle) && x.PublicKeyIdBytes.SequenceEqual(args.CredentialId)) != null);
                };

                // 5. Make the assertion
                var res = await _lib.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter, callback);


                // 6. Store the updated counter
                creds.SignatureCounter = res.Counter;
                _authenticationContext.SaveChanges();

                // 7. return OK to client
                return(Json(new { success = true }));
            }
            catch (Exception e)
            {
                return(Json(new { success = false }));
            }
        }
Esempio n. 5
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database

                var signInUser = await _signInManager.GetTwoFactorAuthenticationUserAsync();

                var applicationUser = await _userManager.FindByNameAsync(signInUser.UserName);

                var creds = _fido2CredentialService.GetCredentialByUser(applicationUser);



                if (creds == null)
                {
                    throw new Exception("Unknown credentials");
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = await _fido2CredentialService.GetCredentialsByUserHandleAsync(args.UserHandle);

                    return(storedCreds.Exists(c => new PublicKeyCredentialDescriptor(c.Descriptor).Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _fido2.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter, callback);

                // 6. Store the updated counter
                var code = await _fido2CredentialService.UpdateCounter(res.CredentialId, res.Counter);

                // TODO Fix counter
                // TODO Allow more than one key to work

                // var result = await _signInManager.TwoFactorSignInAsync("Fido2", string.Empty, false, false);
                await _signInManager.SignInAsync(applicationUser, false);

                // 7. return OK to client
                return(Json(res));
            }
            catch (Exception e)
            {
                return(Json(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
Esempio n. 6
0
        // Only API call
        public async Task <AuthorizationResponse> SignInAsync(SecurityKeySignInModel parameters)
        {
            var assertionRawResponse = parameters.AuthenticatorAssertionRawResponse;

            // Get the assertion options we sent the client
            var jsonOptions = _memoryCache.Get <string>(Convert.ToBase64String(assertionRawResponse.Id));
            var options     = AssertionOptions.FromJson(jsonOptions);

            // Get registered credential from database
            var creds = await GetCredentialById(assertionRawResponse.Id);

            if (creds == null)
            {
                throw new Exception("Unknown credentials");
            }

            // Get credential counter from database
            var storedCounter = creds.SignatureCounter;

            // Create callback to check if userhandle owns the credentialId
            IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
            {
                var storedCreds = await GetCredentialsByUserHandleAsync(args.UserHandle);

                return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
            };

            // Make the assertion
            var res = await _lib.MakeAssertionAsync(assertionRawResponse, options, creds.PublicKey, storedCounter, callback);

            // Store the updated counter
            await UpdateCounter(res.CredentialId, res.Counter);

            // Get authenticator flags
            var authData = new AuthenticatorData(assertionRawResponse.Response.AuthenticatorData);

            if (authData.UserPresent && authData.UserVerified)
            {
                var user = await _userManager.FindByNameAsync(creds.Username);

                if (user == null)
                {
                    throw new HESException(HESCode.UserNotFound);
                }

                await _signInManager.SignInAsync(user, parameters.RememberMe);

                return(AuthorizationResponse.Success(user));
            }

            return(AuthorizationResponse.Error(HESCode.AuthenticatorNotFIDO2));
        }
Esempio n. 7
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = await _fido2Storage.GetCredentialById(clientResponse.Id);

                if (creds == null)
                {
                    throw new Exception("Unknown credentials");
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = await _fido2Storage.GetCredentialsByUserHandleAsync(args.UserHandle);

                    return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _lib.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter, callback);

                // 6. Store the updated counter
                await _fido2Storage.UpdateCounter(res.CredentialId, res.Counter);

                var identityUser = await _userManager.FindByNameAsync(creds.Username);

                if (identityUser == null)
                {
                    throw new InvalidOperationException($"Unable to load user.");
                }

                await _signInManager.SignInAsync(identityUser, isPersistent : false);

                // 7. return OK to client
                return(Json(res));
            }
            catch (Exception e)
            {
                return(Json(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
Esempio n. 8
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = DemoStorage.GetCredentialById(clientResponse.Id);

                if (creds == null)
                {
                    throw new Exception("Unknown credentials");
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = await DemoStorage.GetCredentialsByUserHandleAsync(args.UserHandle);

                    return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _lib.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter, callback);

                // 6. Store the updated counter
                DemoStorage.UpdateCounter(res.CredentialId, res.Counter);

                // Begin customization - Krishna
                // 7. At this point, the user has been authenticated successfully.
                // Set auth cookie through standard ASP.NET core's identity methods, using creds.userHandle as the UPN claim.
                var userHandleStr = Encoding.UTF8.GetString(creds.UserHandle);
                await SetClaimsPrincipalAsync(userHandleStr);

                // End customization - Krishna

                // 8. return OK to client
                return(Json(res));
            }
            catch (Exception e)
            {
                return(Json(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
Esempio n. 9
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse authenticatorAssertionRawResponse)
        {
            try
            {
                var jsonOptions = await _distributedCache.GetStringAsync(UniqueId);

                if (string.IsNullOrEmpty(jsonOptions))
                {
                    throw new Exception("Cant get Credential options from cache.");
                }
                var assertionOptions     = AssertionOptions.FromJson(jsonOptions);
                var fidoStoredCredential = await _fido2Service.GetFido2StoredCredentialsByCredentialIdAsync(authenticatorAssertionRawResponse.Id);

                if (fidoStoredCredential == null)
                {
                    throw new Exception("Unkown credentials.");
                }

                IsUserHandleOwnerOfCredentialIdAsync isUserHandleOwnerOfCredentialIdAsync = async(args) =>
                {
                    var storedCreds = await _fido2Service.GetFido2StoredCredentialsByUserHandleAsync(args.UserHandle);

                    var storedCredExsist = storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId));
                    return(storedCredExsist);
                };

                var response = await _fido2.MakeAssertionAsync(authenticatorAssertionRawResponse, assertionOptions, fidoStoredCredential.PublicKey, fidoStoredCredential.SignatureCounter, isUserHandleOwnerOfCredentialIdAsync);

                if (response.Status != "ok")
                {
                    throw new Exception("Failed to assertion.");
                }

                await _fido2Service.UpdateFido2StoredCredentialCounter(response.CredentialId, response.Counter);

                var identityUser = _applicationDbContext.Users.Where(c => c.UserName == fidoStoredCredential.UserName).FirstOrDefault();
                if (identityUser == null)
                {
                    throw new Exception($"Unable to load two factor authentication user.");
                }
                await _signInManager.SignInAsync(identityUser, true);

                return(Json(response));
            }
            catch (Exception exception)
            {
                return(Json(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = CommonFunctions.FormatException(exception)
                }));
            }
        }
Esempio n. 10
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = PasswordlessStore.GetCredentialById(clientResponse.Id);

                if (creds == null)
                {
                    throw new Exception("Unknown credentials");
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = await PasswordlessStore.GetCredentialsByUserHandleAsync(args.UserHandle);

                    return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _fido2.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter,
                                                          callback);

                // 6. Store the updated counter
                PasswordlessStore.UpdateCounter(res.CredentialId, res.Counter);

                if (res.Status == "ok")
                {
                    var username = System.Text.Encoding.UTF8.GetString(creds.UserId);
                    await SignInOidc(username);
                }
                // 7. return OK to client
                return(Json(res));
            }
            catch (Exception e)
            {
                return(Json(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
Esempio n. 11
0
        public async Task <bool> ValidateAsync(string purpose, string token, UserManager <User> manager, User user)
        {
            var userService = _serviceProvider.GetRequiredService <IUserService>();

            if (!(await userService.CanAccessPremium(user)) || string.IsNullOrWhiteSpace(token))
            {
                return(false);
            }

            var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
            var keys     = LoadKeys(provider);

            if (!provider.MetaData.ContainsKey("login"))
            {
                return(false);
            }

            var clientResponse = JsonSerializer.Deserialize <AuthenticatorAssertionRawResponse>(token,
                                                                                                new JsonSerializerOptions {
                PropertyNameCaseInsensitive = true
            });

            var jsonOptions = provider.MetaData["login"].ToString();
            var options     = AssertionOptions.FromJson(jsonOptions);

            var webAuthCred = keys.Find(k => k.Item2.Descriptor.Id.SequenceEqual(clientResponse.Id));

            if (webAuthCred == null)
            {
                return(false);
            }

            IsUserHandleOwnerOfCredentialIdAsync callback = (args) => Task.FromResult(true);

            var res = await _fido2.MakeAssertionAsync(clientResponse, options, webAuthCred.Item2.PublicKey, webAuthCred.Item2.SignatureCounter, callback);

            provider.MetaData.Remove("login");

            // Update SignatureCounter
            webAuthCred.Item2.SignatureCounter = res.Counter;

            var providers = user.GetTwoFactorProviders();

            providers[TwoFactorProviderType.WebAuthn].MetaData[webAuthCred.Item1] = webAuthCred.Item2;
            user.SetTwoFactorProviders(providers);
            await userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn, logEvent : false);

            return(res.Status == "ok");
        }
        public async Task <IActionResult> MakeAssertion(AuthenticatorAssertionRawResponse clientResponse)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var credentialIdString = Base64Url.Encode(clientResponse.Id);
                var cred = await context.StoredCredentials.Where(x => x.DescriptorJson.Contains(credentialIdString)).FirstOrDefaultAsync();

                if (cred == null)
                {
                    throw new Exception("Unknown credentials");
                }

                // 3. Get credential counter from database
                var storedCounter = cred.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = await context.StoredCredentials.Where(x => x.UserHandle == args.UserHandle).ToListAsync();

                    return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _fido2.MakeAssertionAsync(clientResponse, options, cred.PublicKey, storedCounter, callback);

                // 6. Store the updated counter
                cred.SignatureCounter = res.Counter;
                await context.SaveChangesAsync();

                // 7. return OK to client
                return(Ok(res));
            }
            catch (Exception e)
            {
                return(BadRequest(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
Esempio n. 13
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            // 1. Get the assertion options we sent the client
            var jsonOptions = this.TempData["fido2.assertionOptions"] as string;
            var options     = AssertionOptions.FromJson(jsonOptions);

            var result = await this._mediator.Send(new ValidateAuthenticatorDeviceCommand(clientResponse, options));

            if (result.IsSuccess)
            {
                await this._authenticationService.SignInFromPartial();

                return(this.Json(result.Value.AssertionVerificationResult));
            }

            return(this.Json(new AssertionVerificationResult {
                Status = "error"
            }));
        }
Esempio n. 14
0
        /// <summary>
        /// 断言:验证断言响应
        /// <para>当客户端返回响应时,我们对其进行验证并接受登录。</para>
        /// </summary>
        public async Task <AssertionVerificationResult> MakeAssertionAsync(User user, AuthenticatorAssertionRawResponse clientRespons)
        {
            if (user == null)
            {
                return(new AssertionVerificationResult()
                {
                    Status = "bad"
                });
            }
            // 1. Get the assertion options we sent the client
            var jsonOptions = distributedCache.GetString(user.UserId.ToString() + "assertionOptions");

            if (string.IsNullOrEmpty(jsonOptions))
            {
                return(new AssertionVerificationResult()
                {
                    Status = "fail",
                    ErrorMessage = "time out"
                });
            }
            var options = AssertionOptions.FromJson(jsonOptions);
            // 2. Get registered credential from database
            var storedCredential = this.GetFIDO2ItemByUserId(user.UserId);
            // 3. Get credential counter from database

            var creds = user.FIDO2Items.Where(b => b.CredentialId.SequenceEqual(clientRespons.Id)).FirstOrDefault();

            var storedCounter = creds.SignatureCounter;
            // 4. Create callback to check if userhandle owns the credentialId

            IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
            {
                return(storedCredential.Exists(c => c.CredentialId.SequenceEqual(args.CredentialId)));
            };
            // 5. Make the assertion
            var res = await _fido2.MakeAssertionAsync(clientRespons, options, creds.PublicKey, storedCounter, callback);

            // 6. Store the updated counter
            creds.SignatureCounter = res.Counter;
            dataContext.SaveChanges();
            return(res);
        }
Esempio n. 15
0
        public async Task <LoginResponse> MakeAssertion([FromBody][Required] MakeAssertionRequest request)
        {
            using (AuthLogic.Disable())
                using (Transaction tr = new Transaction())
                {
                    var assertionOptions = Database.Retrieve <WebAuthnAssertionOptionsEntity>(request.AssertionOptionsId);
                    var options          = AssertionOptions.FromJson(assertionOptions.Json);

                    var cred = Database.Query <WebAuthnCredentialEntity>().SingleEx(cred => cred.CredentialId == request.AssertionRawResponse.Id);

                    var res = await fido2.MakeAssertionAsync(request.AssertionRawResponse, options, cred.PublicKey, (uint)cred.Counter, (args) =>
                    {
                        if (!MemoryExtensions.SequenceEqual <byte>(cred.CredentialId, args.CredentialId))
                        {
                            return(Task.FromResult(false));
                        }

                        var userId = Encoding.UTF8.GetBytes(cred.User.Id.ToString());
                        if (!MemoryExtensions.SequenceEqual <byte>(userId, args.UserHandle))
                        {
                            return(Task.FromResult(false));
                        }

                        return(Task.FromResult(true));
                    });

                    cred.Counter++;
                    cred.Save();

                    var user = cred.User.RetrieveAndForget();

                    AuthServer.OnUserPreLogin(ControllerContext, user);

                    AuthServer.AddUserSession(ControllerContext, user);

                    var token = AuthTokenServer.CreateToken(user);

                    return(tr.Commit(new LoginResponse {
                        userEntity = user, token = token, authenticationType = "webauthn"
                    }));
                }
        }
Esempio n. 16
0
        public async Task <JsonResult> MakeAssertion([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            var jsonOptions = this.TempData["fido2.assertionOptions"] as string;
            var options     = AssertionOptions.FromJson(jsonOptions);

            var result =
                await this._mediator.Send(new ValidateDeviceMfaAgainstCurrentUserCommand(clientResponse, options));

            if (!result.IsSuccess)
            {
                return(this.Json(new AssertionVerificationResult {
                    Status = "error"
                }));
            }

            var url = await this._authenticationService.SignInUserFromPartialStateAsync(result.Value.UserId);

            return(this.Json(new
            {
                url = string.IsNullOrWhiteSpace(url) ? this.Url.Page(PageLocations.AppDashboard) : this.LocalRedirect(url).Url,
                assertionVerificationResult = result.Value.AssertionVerificationResult,
            }));
        }
Esempio n. 17
0
        public async Task <ActionResult> MakeAssertion([ModelBinder(typeof(NewtonsoftJsonAdapter.Binder))] MakeAssertionRequest request)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = TestUsers.FidoAttestationOptions[request.SessionId];
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = TestUsers.FidoCredentials.Where(c => c.Descriptor.Id.SequenceEqual(request.RawResponse.Id)).FirstOrDefault();
                if (creds == null)
                {
                    return(BadRequest("unknown credentials"));
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = TestUsers.FidoCredentials.Where(c => c.UserHandle.SequenceEqual(args.UserHandle));
                    return(storedCreds.Any(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _lib.MakeAssertionAsync(
                    assertionResponse : request.RawResponse,
                    originalOptions : options,
                    storedPublicKey : creds.PublicKey,
                    storedSignatureCounter : storedCounter,
                    isUserHandleOwnerOfCredentialIdCallback : callback);

                // 6. Store the updated counter
                TestUsers.FidoCredentials.Where(c => c.Descriptor.Id.SequenceEqual(res.CredentialId)).FirstOrDefault().SignatureCounter = res.Counter;

                // 7. return OK to client
                if (string.Equals(res.Status, "ok", StringComparison.InvariantCultureIgnoreCase))
                {
                    //actually loging the user in
                    var context = await _interaction.GetAuthorizationContextAsync(request.ReturnUrl);

                    var dbUser = TestUsers.Users.FirstOrDefault(u => string.Equals(u.SubjectId, creds.SubjectId, StringComparison.InvariantCultureIgnoreCase));
                    AuthenticationProperties props = null;
                    if (AccountOptions.AllowRememberLogin && request.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                        };
                    }
                    ;
                    var isuser = new IdentityServerUser(dbUser.SubjectId)
                    {
                        DisplayName = dbUser.Username
                    };
                    await HttpContext.SignInAsync(isuser, props);

                    if (context != null)
                    {
                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return(this.NewtonsoftJsonResult(new MakeAssertionResponse {
                            Status = "ok", Response = res, ReturnUrl = request.ReturnUrl
                        }));
                    }

                    // request for a local page
                    if (Url.IsLocalUrl(request.ReturnUrl))
                    {
                        return(this.NewtonsoftJsonResult(new MakeAssertionResponse {
                            Status = "ok", Response = res, ReturnUrl = request.ReturnUrl
                        }));
                    }
                    else if (string.IsNullOrEmpty(request.ReturnUrl))
                    {
                        return(this.NewtonsoftJsonResult(new MakeAssertionResponse {
                            Status = "ok", Response = res, ReturnUrl = "~/"
                        }));
                    }
                    else
                    {
                        // user might have clicked on a malicious link - should be logged
                        throw new Exception("invalid return URL");
                    }
                }
                else
                {
                    return(BadRequest("not ok"));
                }
            }
            catch (Exception e)
            {
                return(BadRequest(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
Esempio n. 18
0
        public async Task <IActionResult> AssertDigitalSignatureResult([FromBody] AuthenticatorAssertionRawResponse clientResponse)
        {
            var sub = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "sub")?.Value;

            if (string.IsNullOrEmpty(sub))
            {
                return(Json(new { success = false }));
            }
            var user = await _users.FindByIdAsync(sub);

            if (user == null)
            {
                return(Json(new { success = false }));
            }
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = _authContext.FidoLogins.FirstOrDefault(x => x.PublicKeyIdBytes.SequenceEqual(clientResponse.Id) && x.UserId == user.Id);
                //DemoStorage.GetCredentialById(clientResponse.Id);

                if (creds == null)
                {
                    return(Json(new { success = false }));
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    return(_authContext.FidoLogins.FirstOrDefault(x => x.UserHandle.SequenceEqual(args.UserHandle) && x.PublicKeyIdBytes.SequenceEqual(args.CredentialId)) != null);
                };

                // 5. Make the assertion
                var res = await _lib.MakeAssertionAsync(clientResponse, options, creds.PublicKey, storedCounter, callback);

                if (!string.IsNullOrEmpty(res.ErrorMessage))
                {
                    return(Json(new { success = false, error = res.ErrorMessage }));
                }

                var paymentId = HttpContext.Session.GetString("fido2.paymentId");
                var payment   = _authContext.Payments.First(x => x.Id == paymentId);
                var signature = Fido2NetLib.Base64Url.Encode(clientResponse.Response.Signature);

                var paymentAuthorization = new PaymentAuthorization()
                {
                    Payment               = payment,
                    PublicKeyId           = creds.PublicKeyId,
                    Signature             = signature,
                    Type                  = (int)DeviceType.FIDO2,
                    AuthorizationDateTime = DateTime.Now,
                    ClientData            = Fido2NetLib.Base64Url.Encode(clientResponse.Response.ClientDataJson),
                    AuthenticatorData     = Fido2NetLib.Base64Url.Encode(clientResponse.Response.AuthenticatorData)
                };

                _authContext.PaymentAuthorizations.Add(paymentAuthorization);
                payment.Status = "authorized";

                // 6. Store the updated counter
                creds.SignatureCounter = res.Counter;
                _authContext.SaveChanges();

                // 7. return OK to client
                return(Json(new { signature, success = true }));
            }
            catch (Exception e)
            {
                return(Json(new { success = false }));
            }
        }