-
Notifications
You must be signed in to change notification settings - Fork 2
PasskeyAuth
Pair\Services\PasskeyAuth implements Passkey/WebAuthn registration and authentication flows.
It manages challenge lifecycle, verifies WebAuthn payloads, persists credentials, and finalizes login.
new \Pair\Services\PasskeyAuth(
?string $rpId = null,
?string $rpName = null,
?array $allowedOrigins = null,
int $challengeTtl = 300,
?bool $requireUserVerification = null
);Resolution order:
-
rpId: constructor arg ->PASSKEY_RP_ID-> host fromBASE_HREF/HTTP_HOST -
rpName: constructor arg ->PASSKEY_RP_NAME->APP_NAME->"Pair App" -
allowedOrigins: constructor arg ->PASSKEY_ALLOWED_ORIGINS->BASE_HREF -
requireUserVerification: constructor override ->PASSKEY_REQUIRE_USER_VERIFICATION
If RP ID or allowed origins are missing, it throws PairException(MISSING_CONFIGURATION).
Creates publicKey options for navigator.credentials.get(...).
If $user is passed and no allow-list is provided, active user passkeys are loaded automatically.
beginRegistration(User $user, ?string $userDisplayName = null, array $excludeCredentialIds = [], array $options = []): array
Creates publicKey options for navigator.credentials.create(...).
By default excludes already active credentials of the same user.
Consumes challenge, validates assertion (type, challenge, origin, RP ID hash, signature, counter), then returns the output of User::doLoginById(...).
On failure it returns a standard failed-login object (error=true, message, userId=null, sessionId=null) and logs failed attempts via Audit::loginFailed(...).
Consumes and verifies an assertion like completeAuthentication(), but returns the verified user ID without creating a PHP session. Native clients use this before issuing a bearer session.
Consumes registration challenge, validates payload, extracts/stores public key and metadata, and persists a UserPasskey. Native CBOR attestation objects using ES256 or RS256 keys are normalized automatically; browser payloads with an extracted DER public key remain supported.
- Challenges are session-based (
SESSION_KEY = "__pair_passkey_challenges") and single-use. - Challenge expiration defaults to 300 seconds.
- Client data origin must match configured HTTPS origins or an explicitly allowed Android
android:apk-key-hash:<base64url SHA-256 certificate hash>origin. - Signature verification requires OpenSSL (
openssl_verify/openssl_pkey_get_public). - Counter rollback is rejected during authentication.
- Optional user verification enforcement is driven by
PASSKEY_REQUIRE_USER_VERIFICATION.
Authentication:
-
idorrawId response.clientDataJSONresponse.authenticatorDataresponse.signature
Registration:
-
idorrawId response.clientDataJSON-
response.publicKeyPemorresponse.publicKey(base64url DER SPKI)
PASSKEY_RP_IDPASSKEY_RP_NAME-
PASSKEY_ALLOWED_ORIGINS(comma-separated) PASSKEY_REQUIRE_USER_VERIFICATION
See also: PasskeyController, UserPasskey, User, Session, Audit, PairPasskey.js.