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:
@@ -74,6 +74,28 @@ func (r *SessionRepo) Create(ctx context.Context, s *domain.Session) (*domain.Se
|
||||
return &created, nil
|
||||
}
|
||||
|
||||
func (r *SessionRepo) GetByID(ctx context.Context, id int) (*domain.Session, error) {
|
||||
const sql = `
|
||||
SELECT id, token_hash, user_id, user_agent, started_at, expires_at, last_activity
|
||||
FROM activity.sessions
|
||||
WHERE id = $1 AND is_active = true`
|
||||
|
||||
q := connOrTx(ctx, r.pool)
|
||||
rows, err := q.Query(ctx, sql, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SessionRepo.GetByID: %w", err)
|
||||
}
|
||||
row, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[sessionRow])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, domain.ErrNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("SessionRepo.GetByID scan: %w", err)
|
||||
}
|
||||
s := toSession(row)
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
func (r *SessionRepo) GetByTokenHash(ctx context.Context, hash string) (*domain.Session, error) {
|
||||
const sql = `
|
||||
SELECT id, token_hash, user_id, user_agent, started_at, expires_at, last_activity
|
||||
|
||||
Reference in New Issue
Block a user