fix(backend): make access tokens revocable via session validation
The auth middleware trusted any unexpired, well-signed access token, so logout, session termination and admin blocks had no effect until the 15-minute token expired. The middleware now validates that the token's session is still active on every request (SessionRepo.GetByID), and blocking a user deactivates all of their sessions, immediately revoking their outstanding access tokens. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -214,9 +214,12 @@ func (s *AuthService) TerminateSession(ctx context.Context, callerID int16, isAd
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseAccessToken parses and validates an access token, returning its claims.
|
||||
// A refresh token presented here is rejected (wrong token type).
|
||||
func (s *AuthService) ParseAccessToken(tokenStr string) (*Claims, error) {
|
||||
// ValidateAccessToken parses and validates an access token, returning its
|
||||
// claims. A refresh token is rejected (wrong type), and the token's session
|
||||
// must still be active — so logout, session termination, an admin block, or a
|
||||
// refresh rotation revoke any outstanding access tokens immediately rather than
|
||||
// only at expiry.
|
||||
func (s *AuthService) ValidateAccessToken(ctx context.Context, tokenStr string) (*Claims, error) {
|
||||
claims, err := s.parseToken(tokenStr)
|
||||
if err != nil {
|
||||
return nil, domain.ErrUnauthorized
|
||||
@@ -224,6 +227,9 @@ func (s *AuthService) ParseAccessToken(tokenStr string) (*Claims, error) {
|
||||
if claims.TokenType != tokenTypeAccess {
|
||||
return nil, domain.ErrUnauthorized
|
||||
}
|
||||
if _, err := s.sessions.GetByID(ctx, claims.SessionID); err != nil {
|
||||
return nil, domain.ErrUnauthorized
|
||||
}
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user