4.9 KiB
Historical provider-based implementation: superseded by local-mail.md and the email login tests. Google/OIDC is no longer part of the application.
OIDC and persistent-login prototype — in progress
The isolated authProbe source set exercises Spring Security without adding a test issuer, test credentials or prototype account admission to the production application. authProbeTest runs automatically before the regular test task and therefore in tools/ci-jvm and Werkator. Reports are under build/reports/tests/authProbeTest.
Implemented checks
- A loopback HTTP provider signs RS256 ID tokens, serves public JWKS and exchanges single-use authorization codes. The Spring Security OAuth2 Login filters perform the actual HTTP token exchange and ID-token decoding. Authorization requests use random state and nonce from Spring Security. The test harness simulates the provider's consent step; it is not a browser or Google integration test.
- The callback binds identity to issuer and subject. Invalid signature, issuer, audience, expiry, nonce and state are rejected. Replaying a consumed authorization request is rejected.
- Forwarded HTTPS scheme and public host produce
https://werkjournal.javagil.de/login/oauth2/code/googleand HTTPS redirects. This uses ForwardedHeaderFilter in MockMvc; the actual Hostsharing proxy and production Tomcat configuration still require verification. Forwarded headers must only be accepted from the trusted proxy. - A valid provider login still needs an admitted, active application account. The probe preprovisions an account; it does not implement invitations or bootstrap.
- An independently generated 256-bit opaque device credential is issued in a Secure, HttpOnly, SameSite=Lax, host-only cookie with Path=/ and a 30-day Max-Age. Only its SHA-256 hash is stored in H2. Provider tokens are not reused as device credentials.
- A recreated Spring web context and reopened H2 file recognize the credential without the previous HTTP session. Every protected HTTP request revalidates it, so an old authenticated HTTP session cannot bypass account disable or revocation. Reactivating an account does not restore revoked credentials.
- Persistent-store tests exercise single-device logout, logout everywhere, unknown identity rejection and a 30-day inactivity boundary. Passive resolution does not extend the deadline; explicitly recorded user activity does.
The initial eight auth-probe tests and eleven existing tests also passed Werkator at commit 7613400 (95 seconds), including production JAR/PWA smoke.
Reauthentication gate
The resolver starts a new Spring Security authorization request with new state/nonce and prompt=select_account. A pending challenge binds state, admitted account and device-credential hash to the current HTTP session for five minutes. The validated callback must return the same issuer/subject identity and the still-valid original device credential. It creates a separate five-minute proof; it does not issue a replacement device login or delete anything.
A CSRF-protected POST with explicit confirmation consumes that proof once. Missing proof, another device, another admitted identity, expired challenge/proof and an invalid OIDC response fail closed. The probe endpoint returns 204 to represent passage through the authorization gate; production deletion remains unimplemented. Proofs intentionally do not survive an application restart.
Four additional protocol tests cover those conditions. Local verification passes: twelve auth-probe tests plus eleven existing tests, and tools/ci-jvm with production JAR/PWA smoke PASS. This proves a new provider round trip, not password entry or a recent Google auth_time; real provider behavior remains an acceptance check.
Still required before completing this node
- Check real Google configuration and actual provider behavior. Google documents
prompt=select_accountand an optional requestedauth_timeclaim; do not promise password re-entry. The test issuer does not prove Google's freshness guarantees. - Verify the production proxy and Flow integration, including short-lived UI sessions and activity classification. The probe deliberately never infers user activity from generic HTTP traffic. Production must renew the cookie only together with accepted user activity, and must exclude Flow heartbeats, polling and push delivery.
- Move the selected design into the production foundation using Liquibase and jOOQ. The prototype's JDBC DDL is confined to the test source set and is not a production migration. Invitation admission, account lifecycle, CSRF-protected logout and push revocation remain their implementation nodes.
References
GraalVM is deferred. These checks provide no native-image compatibility evidence.