NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Every failure extends RoundlyConsulting\Passkeys\Exceptions\PasskeyException (a RuntimeException). Catch the base for a uniform response, or a child for finer control:

use RoundlyConsulting\Passkeys\Exceptions\PasskeyException;

try {
    $passkey = Passkeys::authenticate($response);
} catch (PasskeyException $e) {
    // Return a uniform failure to the client; log $e server-side.
    return response()->json(['message' => 'Sign-in failed.'], 422);
}

Ceremony failures

ExceptionThrown when
InvalidClientDataclientData.type is wrong, the response payload is malformed, the attestation fmt is not a well-formed format identifier, or a user handle is not base64url of random bytes.
ChallengeExpiredNo challenge exists for the ceremony ID — expired or already used.
ChallengeMismatchThe challenge differs, was minted for another user, or for the other ceremony type.
OriginMismatchThe origin is not allow-listed, or a cross-origin ceremony is not allowed.
RpIdMismatchThe RP ID hash in the authenticator data doesn’t match.
InvalidAuthenticatorDataBad authenticator data, no user-presence flag, inconsistent backup flags, a backup eligibility that differs from the one registered, or missing attested credential data.
UserVerificationRequiredUser verification was required but the authenticator didn’t verify the user.
UnsupportedAlgorithmThe credential’s algorithm isn’t in the offered list.
SignatureInvalidThe assertion signature failed verification.
SignCountRegressionThe counter didn’t advance and sign_count_policy is reject.
CredentialAlreadyRegisteredThe credential ID is already stored, revoked ones included.
CredentialNotFoundThe uniform miss: an unknown credential, one a user-bound ceremony didn’t offer, a usernameless assertion without a userHandle, a failed expectation, a credential revoked mid-assertion, or a rename/revoke of a passkey that isn’t this account’s.
InvalidExpectationAuthenticationExpectation::owner() got an unsaved model — a programming error, never a ceremony outcome.

Configuration, decoding and attestation

ExceptionThrown when
InvalidConfigurationAt boot: a config value of the wrong shape, naming the key (table only when first read), an unvetted algorithm, trust stricter than ignore with attestation none, or clock skew outside 0–3600. At the first ceremony: missing rp.id or origins. At first use: an unreadable trust anchor.
MalformedCborThe CBOR data is malformed.
InvalidCoseKeyThe COSE public key is invalid.
InvalidAttestationThe attestation statement’s maths failed.
AttestationUntrustedThe statement is sound but policy refused it — unanchored root, no anchors configured, self-attestation under basic, an invalid certification path, an expired certificate or a disallowed AAGUID.
AttestationRequiredThe trust tier demands a statement and the authenticator sent none.
UnsupportedAttestationFormatThe format has no verifier (none, packed and apple are supported).
PasskeyAssertionFailedA Passkeys::fake() assertion failed.

Messages resolve through the passkeys::errors.* translation namespace — publish passkeys-translations to localise them.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.