Skip to content

Replace JWT Authentication with Secure Session-Based Authentication #2138

Description

@SB2318

Overview

The current authentication system relies on JWT tokens for user authentication. While JWTs are stateless and scalable, they make session revocation, forced logout, multi-device management, and auditing more difficult.

This issue proposes replacing JWT authentication with a secure server-side session token architecture to improve security, provide better session management, and support advanced authentication features.


Why?

Current JWT Limitations

  • Cannot immediately revoke issued tokens
  • Logout is primarily client-side unless a token blacklist is maintained
  • Difficult to manage multiple active devices
  • Hard to track active sessions
  • More complex refresh token implementation
  • Limited ability to detect suspicious logins

Benefits of Session Tokens

  • Immediate session revocation
  • Logout from individual devices
  • Logout from all devices
  • Active device management
  • Better audit logging
  • Improved security and compliance
  • Simpler authentication lifecycle

Proposed Authentication Flow

User Login
      │
      ▼
Validate Credentials
      │
      ▼
Generate Secure Random Session Token
      │
      ▼
Hash Token (SHA-256)
      │
      ▼
Store Token Hash in Database
      │
      ▼
Return Raw Session Token to Client
      │
      ▼
Client sends:
Authorization: Bearer <session_token>
      │
      ▼
Server hashes incoming token
      │
      ▼
Find matching session
      │
      ▼
Validate session
      │
      ▼
Authenticate user

Database Changes

Create Session Model

model Session {
  id            String   @id @default(cuid())

  tokenHash     String   @unique

  userId        String

  deviceName    String?
  deviceType    String?
  platform      String?
  appVersion    String?

  ipAddress     String?
  userAgent     String?
  location      String?

  createdAt     DateTime @default(now())
  expiresAt     DateTime
  lastUsedAt    DateTime @default(now())

  revokedAt     DateTime?
  isRevoked     Boolean @default(false)

  refreshCount  Int @default(0)

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId])
  @@index([tokenHash])
  @@index([expiresAt])
}

Login Flow

  1. Validate email/password.
  2. Generate a cryptographically secure random token (crypto.randomBytes(32)).
  3. Hash the token using SHA-256.
  4. Store the hash in the database.
  5. Return the raw token to the client.
  6. Client securely stores the session token.

Authentication Middleware

Current

Verify JWT
↓

Decode Payload
↓

Load User

New

Read Authorization Header
↓

Extract Session Token
↓

Hash Token
↓

Find Session
↓

Check Revocation
↓

Check Expiration
↓

Update lastUsedAt
↓

Load User

Session Rotation

Rotate session tokens when:

  • User logs in
  • Password changes
  • Suspicious activity detected
  • Periodic rotation (optional)

Device Management APIs

GET    /auth/sessions

DELETE /auth/sessions/:id

DELETE /auth/logout-all

These APIs allow users to:

  • View active devices
  • Logout from a specific device
  • Logout from all devices

Middleware Responsibilities

  • Validate session token
  • Hash incoming token
  • Find session
  • Check expiration
  • Check revocation
  • Update lastUsedAt
  • Attach authenticated user to the request

Security Enhancements

  • Store only SHA-256 hashes of session tokens
  • Generate 256-bit random session tokens
  • Use constant-time hash comparison
  • Support sliding expiration (optional)
  • Automatically clean expired sessions
  • Track IP address and User-Agent
  • Rate-limit login attempts
  • Detect suspicious logins

Migration Plan

Phase 1 – Database

  • Create Session model
  • Generate Prisma migration
  • Add indexes

Phase 2 – Authentication Service

  • Replace JWT generation
  • Generate secure random session tokens
  • Store hashed tokens
  • Return raw session token

Phase 3 – Authentication Middleware

  • Replace JWT verification middleware
  • Validate sessions
  • Check expiration
  • Check revocation
  • Update lastUsedAt

Phase 4 – Login & Logout

  • Update login endpoint
  • Update logout endpoint
  • Implement logout from all devices

Phase 5 – Session Management

Implement:

GET /auth/sessions

DELETE /auth/sessions/:id

DELETE /auth/logout-all

Phase 6 – Client Updates

Continue using:

Authorization: Bearer <session_token>

This minimizes frontend changes while replacing JWT internally.


Phase 7 – Cleanup

  • Remove JWT dependencies
  • Remove JWT middleware
  • Remove JWT utilities
  • Update documentation
  • Update automated tests

Acceptance Criteria

  • JWT authentication removed
  • Secure session tokens generated on login
  • Only hashed session tokens stored
  • Session authentication middleware implemented
  • Session expiration enforced
  • Individual logout supported
  • Logout from all devices supported
  • Active session management API available
  • Automatic cleanup for expired sessions
  • Documentation updated
  • Tests updated

Estimated Effort

Phase Estimate
Database Migration 0.5 day
Authentication Service 1 day
Middleware 1 day
Session APIs 1 day
Client Integration 0.5–1 day
Testing & Documentation 1 day

Total Estimated Effort: 5–6 developer days


Notes

  • This is a breaking authentication change and should be released behind a feature flag or as part of a major release.
  • Existing clients must update to the new authentication flow.
  • A scheduled cleanup job should periodically delete expired and revoked sessions to maintain database performance.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions