Package com.mcawful
Class PasskeyVerifier
java.lang.Object
com.mcawful.PasskeyVerifier
Server-side checks for passkey (WebAuthn) registration and sign-in on the panel.
Attestation is not requested, so the browser hands over the public key in SubjectPublicKeyInfo form and no CBOR parsing is needed. Only ES256 (P-256) and RS256 keys are accepted.
This class holds no bot state. Every verify method throws
IllegalArgumentException with the reason when a check fails.
- Author:
- mcawful
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longHow long a challenge stays valid, in millisecondsstatic final intLargest accepted authenticator data, in bytesstatic final intLargest acceptedclientDataJSON, in bytesstatic final intLargest credential ID allowed by WebAuthn, in bytesstatic final intLargest accepted public key or signature, in bytes. -
Method Summary
Modifier and TypeMethodDescriptionstatic StringCreates a challenge which carries its own expiry and an HMAC, so the server does not have to remember challenges it has handed out to unauthenticated clientsstatic byte[]Decodes a base64url stringstatic Stringencode(byte[] data) Encodes bytes as base64url without padding, the encoding WebAuthn uses in JSONstatic byte[]randomBytes(int length) Generates cryptographically secure random bytesstatic longverifyAssertion(byte[] clientDataJSON, byte[] authData, byte[] signature, byte[] publicKey, String origin, long signCount) Verifies the response tonavigator.credentials.get()static longverifyRegistration(byte[] clientDataJSON, byte[] authData, byte[] publicKey, byte[] credentialId, String challenge, String origin) Verifies the response tonavigator.credentials.create()
-
Field Details
-
CHALLENGE_TTL_MILLIS
public static final long CHALLENGE_TTL_MILLISHow long a challenge stays valid, in milliseconds- See Also:
-
MAX_CLIENT_DATA
public static final int MAX_CLIENT_DATALargest acceptedclientDataJSON, in bytes- See Also:
-
MAX_AUTH_DATA
public static final int MAX_AUTH_DATALargest accepted authenticator data, in bytes- See Also:
-
MAX_KEY
public static final int MAX_KEYLargest accepted public key or signature, in bytes. A key of this size still fits the column it is stored in- See Also:
-
MAX_CREDENTIAL_ID
public static final int MAX_CREDENTIAL_IDLargest credential ID allowed by WebAuthn, in bytes- See Also:
-
-
Method Details
-
randomBytes
public static byte[] randomBytes(int length) Generates cryptographically secure random bytes- Parameters:
length- the number of bytes- Returns:
- the random bytes
-
encode
Encodes bytes as base64url without padding, the encoding WebAuthn uses in JSON- Parameters:
data- the bytes to encode- Returns:
- the encoded string
-
decode
Decodes a base64url string- Parameters:
data- the string to decodemaxBytes- the largest decoded size to accept- Returns:
- the decoded bytes
- Throws:
IllegalArgumentException- if the string is missing, not base64url, or too large
-
createChallenge
Creates a challenge which carries its own expiry and an HMAC, so the server does not have to remember challenges it has handed out to unauthenticated clients- Returns:
- the challenge, base64url encoded
-
verifyRegistration
public static long verifyRegistration(byte[] clientDataJSON, byte[] authData, byte[] publicKey, byte[] credentialId, String challenge, String origin) Verifies the response tonavigator.credentials.create()- Parameters:
clientDataJSON- the rawclientDataJSONauthData- the raw authenticator datapublicKey- the public key in SubjectPublicKeyInfo formcredentialId- the credential ID reported by the browserchallenge- the challenge that was issued for this registration, as returned bycreateChallenge()origin- the origin the browser must have performed the registration on- Returns:
- the initial signature counter
- Throws:
IllegalArgumentException- if any check fails
-
verifyAssertion
public static long verifyAssertion(byte[] clientDataJSON, byte[] authData, byte[] signature, byte[] publicKey, String origin, long signCount) Verifies the response tonavigator.credentials.get()- Parameters:
clientDataJSON- the rawclientDataJSONauthData- the raw authenticator datasignature- the signaturepublicKey- the stored public key in SubjectPublicKeyInfo formorigin- the origin the passkey was registered onsignCount- the stored signature counter- Returns:
- the new signature counter
- Throws:
IllegalArgumentException- if any check fails
-