Skip to content

[RFC] Remove DB query from AuthGuard — embed role in JWT payload #3

@Khoa-Dam

Description

@Khoa-Dam

Problem

auth.guard.ts canActivate() fires a userRepository.findOne() on every authenticated request to read the user's role. This adds a DB roundtrip to every API call, even read-only endpoints.

crime-reports.gateway.ts already reads payload.role directly from the JWT (line ~40) — the guard is inconsistent with its own codebase.

Proposed Solution — Embed role in JWT payload

What changes

auth.service.tsgenerateUserTokens():

// Before
jwtService.sign({ userId: user.id })

// After
jwtService.sign({ userId: user.id, role: user.role })

auth.guard.tscanActivate():

  • Remove @InjectRepository(User) injection
  • Remove userRepository.findOne() call
  • Read role from payload.role (already decoded from JWT)

Security note

Role changes take up to 1 × access token TTL (typically 1h) to propagate — this is acceptable. If a user is deleted or demoted urgently, invalidate their refresh token to block re-authentication.

Files to modify

File Action
src/auth/auth.service.ts Add role: user.role to jwtService.sign() call
src/auth/guards/auth.guard.ts Remove @InjectRepository(User), remove findOne(), read payload.role

Benefits

  • Eliminates 1 DB query per authenticated request
  • Consistent with gateway's existing approach
  • AuthGuard no longer depends on TypeOrmModule — cleaner module graph

References

Architecture RFC session — 2026-04-12

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFCRequest for Comments — architecture proposals

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions