Add passkeys project: WebAuthn ceremonies, a software authenticator and the one-time-token fallback
Fourth Maven project in the repository. Registration and authentication run end to end with no browser and no hardware key: VirtualAuthenticator emits real CBOR attestation objects and real ES256 assertion signatures, and tools/PasskeyCeremony.java drives the live HTTP endpoints with them. Profiles cover userVerification REQUIRED, DIRECT attestation, a disallowed origin and JDBC persistence. Eleven doc chapters and twelve captured transcripts under docs/passkeys and docs/output/pk-*.txt, all regenerated by passkeys/scripts/run-all.sh.
This commit is contained in:
41
docs/output/pk-step-up.txt
Normal file
41
docs/output/pk-step-up.txt
Normal file
@@ -0,0 +1,41 @@
|
||||
==============================================================================
|
||||
FactorGrantedAuthority - password, magic link and passkey are not interchangeable
|
||||
==============================================================================
|
||||
|
||||
=== An endpoint guarded by hasAuthority("FACTOR_WEBAUTHN") ===
|
||||
POST /login (password) -> HTTP 302, Location: http://localhost:8080/
|
||||
|
||||
$ POST /webauthn/register/options
|
||||
HTTP 200
|
||||
{"attestation":"none","authenticatorSelection":{"residentKey":"required","userVerification":"preferred"},"challenge":"2LH6xjc9-LwKl-KldFIox5EkCGBVuDXps87yofG4piA","excludeCredentials":[],"extensions":{"credProps":true},"pubKeyCredParams":[{"alg":-8,"type":"public-key"},{"alg":-7,"type":"public-key"},{"alg":-257,"type":"public-key"}],"rp":{"id":"localhost","name":"ankurm passkeys demo"},"timeout":300000,"user":{"name":"user","id":"p6EhVt4x7b3PsL3M94Vuczh2BQyWCSurlu1YBG6lAvs","displayName":"user"}}
|
||||
authenticator produced credentialId AkXU5KRzDgeoY4RFXG0mqg and a 178-byte CBOR attestation object
|
||||
|
||||
$ POST /webauthn/register
|
||||
HTTP 200
|
||||
{"success":true}
|
||||
|
||||
password session -> GET /passkey-only: HTTP 302, Location: http://localhost:8080/login?factor.type=webauthn&factor.reason=missing
|
||||
logged out, cookie jar emptied
|
||||
|
||||
=== One-time token: the way in when there is no passkey yet, and the way back ===
|
||||
POST /ott/generate -> HTTP 302, Location: http://localhost:8080/login/ott
|
||||
token delivered out of band (the handler wrote it to a file): 9ae7d90d-74fe-49ec-9502-fe857fe8972a
|
||||
POST /login/ott -> HTTP 302, Location: http://localhost:8080/
|
||||
|
||||
$ GET /me
|
||||
HTTP 200
|
||||
{"name":"user","authenticationType":"OneTimeTokenAuthentication","authorities":["FactorGrantedAuthority [authority=FACTOR_OTT, issuedAt=2026-08-25T17:20:54.745020051Z]","ROLE_USER"]}
|
||||
|
||||
=== The same token, a second time ===
|
||||
POST /login/ott -> HTTP 302, Location: http://localhost:8080/login?error
|
||||
|
||||
one-time-token session -> GET /passkey-only: HTTP 302, Location: http://localhost:8080/login?factor.type=webauthn&factor.reason=missing
|
||||
logged out, cookie jar emptied
|
||||
|
||||
$ POST /login/webauthn
|
||||
HTTP 200
|
||||
{"authenticated":true,"redirectUrl":"/"}
|
||||
|
||||
$ passkey session -> GET /passkey-only
|
||||
HTTP 200
|
||||
{"ok":"this endpoint required FACTOR_WEBAUTHN"}
|
||||
Reference in New Issue
Block a user