private static bool VerifySignature(WebAuthenticationSignInRequest request, IPublicKey publicKey) { var hash = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(request.clientDataJSON)); var assertion = Convert.FromBase64String(request.Base64CborAssertion); var data = assertion.Concat(hash).ToArray(); var signature = Convert.FromBase64String(request.Signature); var sigProvider = new CryptoProviderFactory().CreateForVerifying(publicKey.GetSecurityKey(), publicKey.Algorithum); return(sigProvider.Verify(data, signature)); }
public async Task <AuthenticationResult> Authenticate(WebAuthenticationSignInRequest request) { var(user, credentials, signCount, publicKey) = Users .Select(x => { var credentials = x.Attestations.SingleOrDefault(x => x.Id == request.Id); return( user: x, credentials, signCount: credentials?.Attestation?.AuthData?.SignCount, publicKey: credentials?.Attestation?.AuthData?.PublicKey ); }) .Single(x => x.publicKey != null); if (user is null) { return new AuthenticationResult { Success = false } } ; if (!ValidateClientData(request.clientDataJSON, "webauthn.get")) { return new AuthenticationResult { Success = false } } ; if (!VerifySignature(request, publicKey)) { return new AuthenticationResult { Success = false } } ; var assertion = _authDataParser.Parse(Convert.FromBase64String(request.Base64CborAssertion)); if (!ValidateRpIdHash(assertion.RpIdHash)) { return new AuthenticationResult { Success = false } } ; if (!assertion.Flags.HasFlag(AuthDataFlags.UserPresent)) { return new AuthenticationResult { Success = false } } ; if (!assertion.Flags.HasFlag(AuthDataFlags.UserVerified)) { return new AuthenticationResult { Success = false } } ; if (assertion.SignCount != 0 && assertion.SignCount < signCount) { return new AuthenticationResult { Success = false } } ; // update last sign count to avoid replays credentials.Attestation.AuthData.SignCount = assertion.SignCount; return(new AuthenticationResult { Success = true, Token = GenerateJWTToken(user), Email = user.Email, Id = user.Id.ToString(), Name = user.Name }); }