コード例 #1
0
        MakeAssertionAsync(AnonymousAuthenticatorAssertionRawResponse clientResponse, string deviceName)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                if (string.IsNullOrWhiteSpace(clientResponse.RequestId))
                {
                    _logger.LogError("Attempted to make assertion without request id");
                    return(Result.Failure <(User, string, string), (bool, string)>((false, "No user id or request id provided")));
                }
                var cacheKey = $"AssertionOptions:{clientResponse.RequestId}";

                if (!_cache.TryGetValue(cacheKey, out AssertionOptions options))
                {
                    _logger.LogError($"Failed to find assertion options for key '{cacheKey}'");
                    return(Result.Failure <(User, string, string), (bool, string)>((true, "No assertion found")));
                }
                _cache.Remove(cacheKey);

                // 2. Get registered credential from database
                var authorization = await _db.DeviceAuthorizations
                                    .Include(x => x.User)
                                    //todo In .net 5, ef-core 5 will support using SequenceEqual, for now we'll use normal equality and just remember that it will be properly translated into sql for real databases, see https://github.com/dotnet/efcore/issues/10582
                                    //.FirstOrDefaultAsync(x => x.CredentialId.SequenceEqual(clientResponse.Id));
                                    .FirstOrDefaultAsync(x => x.CredentialId == clientResponse.Id);

                if (authorization is null)
                {
                    _logger.LogError("Failed to find credentials");
                    return(Result.Failure <(User, string, string), (bool, string)>((true, "No credentials found")));
                }

                // 3. Make the assertion
                var avr = await _fido2.MakeAssertionAsync(clientResponse, options, authorization.PublicKey, authorization.SignatureCounter, x => Task.FromResult(true));

                // 4. Store the updated counter
                authorization.SignatureCounter = avr.Counter;

                var login = _userService.GenerateAndSaveLogin(authorization.User, deviceName, authorization.Id);
                return(Result.Success <(User user, string accessToken, string refreshToken), (bool unauthorized, string message)>(login));
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Failed to make assertion for user");
                return(Result.Failure <(User, string, string), (bool, string)>((false, "Error making assertion")));
            }
        }
コード例 #2
0
        public async Task <IActionResult> CompleteDeviceAssertion([FromBody] AnonymousAuthenticatorAssertionRawResponse response)
        {
            var(_, isFailure, (user, accessToken, refreshToken), (unauthorized, errorMessage)) =
                await _webAuthnService.MakeAssertionAsync(response, Request.GetDeviceName());

            if (!isFailure)
            {
                return(Ok(new AuthenticatedUser(user, accessToken, refreshToken)));
            }

            if (unauthorized)
            {
                return(Unauthorized());
            }

            return(BadRequest(errorMessage));
        }