Stability | experimental |
---|---|
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This module implements assertion of the received authenticator response. See the WebAuthn specification for the algorithm implemented in this module. Assertion is typically represented as a "login" or "authentication" action in the front-end. Section 7 of the specification describes when the relying party must perform assertion. Another relevant section is Section 1.3.3 which is a high level overview of the authentication procedure.
Synopsis
- verifyAuthenticationResponse :: NonEmpty Origin -> RpIdHash -> Maybe UserHandle -> CredentialEntry -> CredentialOptions 'Authentication -> Credential 'Authentication 'True -> Validation (NonEmpty AuthenticationError) AuthenticationResult
- data AuthenticationError
- = AuthenticationCredentialDisallowed { }
- | AuthenticationIdentifiedUserHandleMismatch { }
- | AuthenticationCredentialUserHandleMismatch { }
- | AuthenticationCannotVerifyUserHandle
- | AuthenticationChallengeMismatch { }
- | AuthenticationOriginMismatch { }
- | AuthenticationRpIdHashMismatch { }
- | AuthenticationUserNotPresent
- | AuthenticationUserNotVerified
- | AuthenticationSignatureDecodingError DeserialiseFailure
- | AuthenticationSignatureInvalid Text
- newtype AuthenticationResult = AuthenticationResult {}
- data SignatureCounterResult
Documentation
verifyAuthenticationResponse Source #
:: NonEmpty Origin | The list of allowed origins for the ceremony |
-> RpIdHash | The hash of the relying party id |
-> Maybe UserHandle | The user handle, in case the user is identified already TODO: Mention that this would be empty for username-less authentication |
-> CredentialEntry | The database entry for the credential, as created in the initial attestation and optionally updated in subsequent assertions |
-> CredentialOptions 'Authentication | The options that were passed to the get() method |
-> Credential 'Authentication 'True | The credential returned from get() |
-> Validation (NonEmpty AuthenticationError) AuthenticationResult | Either a non-empty list of validation errors in case of the assertion being invalid Or in case of success a signature counter result, which should be dealt with |
(spec) Verifies a Credential
response for an authentication ceremony.
The arSignatureCounterResult
field of the result should be inspected to
enforce Relying Party policy regarding potentially cloned authenticators.
Though this library implements the WebAuthn L2 spec, for origin validation we
follow the L3 draft. This is because allowing multiple origins is often
needed in the wild. See Validating the origin of a credential
more details.
In the simplest case, just a single origin is allowed and this is the RpId
with https://
prepended:
verifyAuthenticationResponse (NE.singleton (M.Origin "https://example.org")) ...
In the more complex case, multiple origins are allowed:
verifyAuthenticationResponse (M.Origin <$> "https://example.org" :| ["https://signin.example.org"]) ...
One might also allow native apps to authenticate:
verifyAuthenticationResponse (M.Origin <$> "https://example.org" :| ["ios:bundle-id:org.example.ourapp"]) ...
See Apple's documentation on associated domains and Google's documentation on Digital Asset Links for more information on how to link app origins to your Relying Party ID.
data AuthenticationError Source #
Errors that may occur during assertion
AuthenticationCredentialDisallowed | The provided Credential was not one explicitly allowed by the server |
| |
AuthenticationIdentifiedUserHandleMismatch | The received credential does not match the currently identified user |
| |
AuthenticationCredentialUserHandleMismatch | The stored credential does not match the user specified in the response |
| |
AuthenticationCannotVerifyUserHandle | No user was identified and the response did not specify a user |
AuthenticationChallengeMismatch | The received challenge does not match the originally created challenge |
| |
AuthenticationOriginMismatch | The origin derived by the client does match any of the assumed origins |
| |
AuthenticationRpIdHashMismatch | The rpIdHash in the authData is not a valid hash over the RpId expected by the Relying party |
| |
AuthenticationUserNotPresent | The UserPresent bit was not set in the authData |
AuthenticationUserNotVerified | The UserVerified bit was not set in the authData while user verification was required |
AuthenticationSignatureDecodingError DeserialiseFailure | The public key provided in the |
AuthenticationSignatureInvalid Text | The public key doesn't verify the signature over the authData |
Instances
Exception AuthenticationError Source # | |
Show AuthenticationError Source # | |
Defined in Crypto.WebAuthn.Operation.Authentication showsPrec :: Int -> AuthenticationError -> ShowS # show :: AuthenticationError -> String # showList :: [AuthenticationError] -> ShowS # |
newtype AuthenticationResult Source #
A successful result of verifyAuthenticationResponse
, it should be inspected by the Relying Party to enforce its policy regarding logins.
AuthenticationResult | |
|
Instances
Show AuthenticationResult Source # | |
Defined in Crypto.WebAuthn.Operation.Authentication showsPrec :: Int -> AuthenticationResult -> ShowS # show :: AuthenticationResult -> String # showList :: [AuthenticationResult] -> ShowS # | |
Eq AuthenticationResult Source # | |
Defined in Crypto.WebAuthn.Operation.Authentication (==) :: AuthenticationResult -> AuthenticationResult -> Bool # (/=) :: AuthenticationResult -> AuthenticationResult -> Bool # |
data SignatureCounterResult Source #
Section 6.1.1 of the specification describes the use of the signature counter, and describes what the relying part must do with them. In particular:
The signature counter 's purpose is to aid Relying Parties in detecting cloned authenticators. Clone detection is more important for authenticators with limited protection measures.
A Relying Party stores the signature counter of the most recent authenticatorGetAssertion operation. (Or the counter from the authenticatorMakeCredential operation if no authenticatorGetAssertion has ever been performed on a credential.) In subsequent authenticatorGetAssertion operations, the Relying Party compares the stored signature counter value with the new `signCount` value returned in the assertion’s authenticator data. If either is non-zero, and the new `signCount` value is less than or equal to the stored value, a cloned authenticator may exist, or the authenticator may be malfunctioning.
SignatureCounterZero | There is no signature counter being used, the database entry doesn't need to be updated, but we also have no guarantees about the authenticator not being cloned |
SignatureCounterUpdated SignatureCounter | The signature counter needs to be updated in the database |
SignatureCounterPotentiallyCloned | The signature counter decreased, the authenticator was potentially cloned and the relying party may want to e.g. lock this credential |
Instances
Show SignatureCounterResult Source # | |
Defined in Crypto.WebAuthn.Operation.Authentication showsPrec :: Int -> SignatureCounterResult -> ShowS # show :: SignatureCounterResult -> String # showList :: [SignatureCounterResult] -> ShowS # | |
Eq SignatureCounterResult Source # | |
Defined in Crypto.WebAuthn.Operation.Authentication |