Auth: wire Spring Security + Spring Session JDBC end to end - #47
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
| .orElseGet(() -> { | ||
| invalidateSession(httpRequest); | ||
| return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponder.failure("Not signed in")); |
There was a problem hiding this comment.
Missing SecurityContextHolder.clearContext() call when member not found. If a member is deleted from the database while their session is still active, the session gets invalidated but the SecurityContext remains in the thread-local for the duration of this request. This could allow subsequent code in the same request to still see an authenticated principal that should no longer exist.
.orElseGet(() -> {
invalidateSession(httpRequest);
SecurityContextHolder.clearContext(); // Add this line
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponder.failure("Not signed in"));
});Note that the logout() method at line 86 correctly clears the context after invalidation.
| .orElseGet(() -> { | |
| invalidateSession(httpRequest); | |
| return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponder.failure("Not signed in")); | |
| .orElseGet(() -> { | |
| invalidateSession(httpRequest); | |
| SecurityContextHolder.clearContext(); | |
| return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponder.failure("Not signed in")); | |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
| /** Answers unauthenticated requests to protected endpoints with a 401 in the standard JSON envelope. */ | ||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class ApiAuthenticationEntryPoint implements AuthenticationEntryPoint { |
There was a problem hiding this comment.
Would be good to add an example of how to protect an endpoint.
37bcb7f to
81d33d2
Compare
9ebd548 to
2a9e88a
Compare
Graphite Automations"Request reviewers once CI passes" took an action on this PR • (07/31/26)2 reviewers were added to this PR based on Henry Chen's automation. |
- AuthController: POST /api/auth/request-link|verify|logout and GET /api/session; verify performs programmatic login (session id rotation + SecurityContextRepository save), session reads the member fresh so profile completion is never stale - SecurityConfig moved to auth/security and rewired: patchats_session cookie (HttpOnly, SameSite=Lax, Secure per profile, 30d) via DefaultCookieSerializer; dev/prod chains share CSRF-off posture documented in the javadoc; prod email rule kept fail-closed - ApiAuthenticationEntryPoint answers 401s in the ApiResponder envelope - AuthenticatedMember principal is Serializable (persisted by Spring Session) and exposes email as the indexed principal name - SecurityWiringTest exercises the real filter chain: anonymous 401, session-carried auth across requests, logout invalidation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
81d33d2 to
3c0452c
Compare
2a9e88a to
04a095e
Compare
|




GET /api/session; verify performs programmatic login (session id
rotation + SecurityContextRepository save), session reads the member
fresh so profile completion is never stale
cookie (HttpOnly, SameSite=Lax, Secure per profile, 30d) via
DefaultCookieSerializer; dev/prod chains share CSRF-off posture
documented in the javadoc; prod email rule kept fail-closed
Session) and exposes email as the indexed principal name
session-carried auth across requests, logout invalidation
Co-Authored-By: Claude Fable 5 noreply@anthropic.com