From 463c6348b3deed51d2ae010d0b35e088a71439b0 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:04:02 +0200 Subject: [PATCH] docs(handoff): logout-hardening verification notes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records the automated outcomes (4/4 ITs pass, typecheck + build green) and lists the three manual smoke tests still required from the SaaS team — local-user, OIDC-user against Logto, stolen-token. The OIDC test depends on Logto-side post_logout_redirect_uri registration; the others can be exercised against any cameleer-server deployment. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/handoff/2026-04-27-logout-hardening.md | 23 +++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/handoff/2026-04-27-logout-hardening.md b/docs/handoff/2026-04-27-logout-hardening.md index 20aa2e3e..4ba78dcf 100644 --- a/docs/handoff/2026-04-27-logout-hardening.md +++ b/docs/handoff/2026-04-27-logout-hardening.md @@ -72,6 +72,25 @@ If silent re-auth still happens after step 4, the most likely cause is that `pro - Server ITs: `JwtRevocationIT`, `LogoutControllerIT` (both in `cameleer-server-app/src/test/java/com/cameleer/server/app/security/`) - SaaS reference implementation: `cameleer-saas/ui/src/auth/useAuth.ts` (`@logto/react` `signOut(redirectUri)` + `cameleer:signed_out` sessionStorage flag pattern, mirrored here) -## Verification (filled in during Task 8) +## Verification -_Pending — see Task 8 of `docs/superpowers/plans/2026-04-27-logout-hardening.md` for the smoke-test results._ +### Automated (run on `feature/logout-hardening` HEAD `7837272a`, 2026-04-27) + +| Check | Outcome | +|---|---| +| `JwtRevocationIT` (2 tests — revoked-token rejected, unrevoked-token accepted) | ✅ PASS | +| `LogoutControllerIT` (2 tests — authenticated logout revokes+audits+rejects subsequent calls; unauthenticated logout 204 no-op) | ✅ PASS | +| Reactor build | ✅ BUILD SUCCESS | +| `ui/ npm run typecheck` | ✅ 0 errors | +| `ui/ npm run build` | ✅ built in 1.21s (pre-existing chunk-size warning unchanged, unrelated) | + +The pre-existing revocation-bug regression (token still works after logout) is now covered by `JwtRevocationIT.revokedTokenIsRejectedOnAuthenticatedRequest` and the end-to-end logout flow by `LogoutControllerIT.logoutRevokesTokensAuditsAndRejectsSubsequentCalls`. Both depend on the `JwtAuthenticationFilter` prefix-strip fix in commit `7066795c`. + +### Manual — required from the SaaS team + +- [ ] Register `https:///login` as a `post_logout_redirect_uri` on the Logto application for each cameleer-server tenant (per the table above). +- [ ] Local-user smoke (in a browser): sign in → sign out → confirm 204 from `/api/v1/auth/logout` in DevTools Network tab → confirm "Signed out successfully" splash → "Sign in again" → confirm local form re-renders cleanly. +- [ ] OIDC-user smoke (in a browser, against Logto): sign in via SSO as user A → sign out → confirm top-level navigation through Logto's `end_session_endpoint` → land on splash → "Sign in again" → "Sign in with SSO" → confirm Logto **shows its login screen** (not silent re-auth) → sign in as user B → confirm dashboard reflects B (not A). +- [ ] Stolen-token smoke: copy `cameleer-access-token` from localStorage → sign out → confirm `curl -H "Authorization: Bearer " .../api/v1/auth/me` returns 401. + +The automated coverage proves the server-side revocation works. The manual checks prove the IdP-side session is also cleared and the UX flow is correct end-to-end.