public async Task ValidateAsync(ExtensionGrantValidationContext context) { var parameters = context.Request.Raw; var deviceId = parameters.Get(RegistrationRequestParameters.DeviceId); if (string.IsNullOrWhiteSpace(deviceId)) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, $"Parameter '{RegistrationRequestParameters.DeviceId}' is not specified."); return; } // Load device. var device = await UserDeviceStore.GetByDeviceId(deviceId); if (device == null) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Device is unknown."); return; } // If a code is present we are heading towards fingerprint login. var code = parameters.Get(RegistrationRequestParameters.Code); if (!string.IsNullOrWhiteSpace(code)) { // Retrieve authorization code from the store. var authorizationCode = await CodeChallengeStore.GetAuthorizationCode(code); if (authorizationCode == null) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Authorization code is invalid."); return; } // Validate that the consumer specified all required parameters. var parametersToValidate = new List <string> { RegistrationRequestParameters.CodeSignature, RegistrationRequestParameters.CodeVerifier }; foreach (var parameter in parametersToValidate) { var parameterValue = parameters.Get(parameter); if (string.IsNullOrWhiteSpace(parameterValue)) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, $"Parameter '{parameter}' is not specified."); return; } } // Validate authorization code against code verifier given by the client. var codeVerifier = parameters.Get(RegistrationRequestParameters.CodeVerifier); var authorizationCodeValidationResult = await ValidateAuthorizationCode(code, authorizationCode, codeVerifier, deviceId, context.Request.Client); if (authorizationCodeValidationResult.IsError) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, authorizationCodeValidationResult.ErrorDescription); return; } // Validate given public key against signature for fingerprint. var publicKey = parameters.Get(RegistrationRequestParameters.PublicKey); var codeSignature = parameters.Get(RegistrationRequestParameters.CodeSignature); var publicKeyValidationResult = ValidateSignature(publicKey, code, codeSignature); if (publicKeyValidationResult.IsError) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, publicKeyValidationResult.ErrorDescription); return; } await UserDeviceStore.UpdateDevicePublicKey(device, publicKey); // Grant access token. context.Result = new GrantValidationResult(authorizationCode.Subject.GetSubjectId(), GrantType); await UserDeviceStore.UpdateLastSignInDate(device); } var pin = parameters.Get(RegistrationRequestParameters.Pin); if (!string.IsNullOrWhiteSpace(pin)) { var result = DevicePasswordHasher.VerifyHashedPassword(device, device.Password, pin); if (result == PasswordVerificationResult.Failed) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Wrong pin."); return; } context.Result = new GrantValidationResult(device.UserId, GrantType); await UserDeviceStore.UpdateLastSignInDate(device); } }