1
0
Files
spring-auth-demo/docs/output/pk-ceremony.txt
Ankur Mhatre f6dd692177 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.
2026-08-25 23:00:27 +05:30

37 lines
2.4 KiB
Plaintext

==============================================================================
Registration and authentication ceremonies, driven without a browser
==============================================================================
Spring Security 7.1.1, Spring Boot 4.1.1, rpId localhost, default settings.
The authenticator is src/main/java/com/ankurm/passkeys/virtual/VirtualAuthenticator.java.
=== Registration ceremony, then authentication ceremony, no browser involved ===
POST /login (password) -> HTTP 302, Location: http://localhost:8080/
$ POST /webauthn/register/options
HTTP 200
{"attestation":"none","authenticatorSelection":{"residentKey":"required","userVerification":"preferred"},"challenge":"cfccFSLkLYqwn_qsRIDEpAa8fUnVtxkAB82NBijQyyA","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":"qJBkbDbHGSVdnYG0VqD0JAN-t7GAejJ3Lw3HDL9bKow","displayName":"user"}}
authenticator produced credentialId lAfNKiLC_virGa8Yrfr4gA and a 178-byte CBOR attestation object
$ POST /webauthn/register
HTTP 200
{"success":true}
$ GET /diag/credentials
HTTP 200
{"principal":"user","principalType":"UsernamePasswordAuthenticationToken","authorities":["FactorGrantedAuthority [authority=FACTOR_PASSWORD, issuedAt=2026-08-25T17:18:48.132461443Z]","ROLE_USER"],"userEntity":{"displayName":"user","name":"user","id":"qJBkbDbHGSVdnYG0VqD0JAN-t7GAejJ3Lw3HDL9bKow"},"credentials":[{"label":"yubikey-on-my-desk","credentialId":"lAfNKiLC_virGa8Yrfr4gA","signatureCount":0,"uvInitialized":true,"backupEligible":true,"backupState":true,"transports":["hybrid","internal"],"attestationObjectBytes":178,"created":"2026-08-25T17:18:48.764625858Z","lastUsed":"2026-08-25T17:18:48.764625858Z"}]}
logged out, cookie jar emptied
=== Session dropped. Authenticating with the passkey alone ===
$ POST /webauthn/authenticate/options
HTTP 200
{"allowCredentials":[],"challenge":"BUu8TaKJn6f43nZk4oL3GpD517F8cDol5XOlc7GULq8","extensions":{},"rpId":"localhost","timeout":300000,"userVerification":"preferred"}
$ POST /login/webauthn
HTTP 200
{"authenticated":true,"redirectUrl":"/"}
$ GET /me
HTTP 200
{"name":"user","authenticationType":"WebAuthnAuthentication","authorities":["FactorGrantedAuthority [authority=FACTOR_WEBAUTHN, issuedAt=2026-08-25T17:18:49.046877669Z]","ROLE_USER"]}