Skip to content

feat(auth): Two-Factor Authentication (TOTP) + Refresh Token Session Management - #130

Merged
Akash29g merged 3 commits into
mainfrom
feat/2fa-and-session-management
Jul 28, 2026
Merged

feat(auth): Two-Factor Authentication (TOTP) + Refresh Token Session Management#130
Akash29g merged 3 commits into
mainfrom
feat/2fa-and-session-management

Conversation

@Akash29g

Copy link
Copy Markdown
Owner

Summary

Adds TOTP-based two-factor authentication and multi-session management
(refresh token rotation + a user-facing "Active sessions" page) to
DocAnalytics auth.

What's included

Backend

  • User entity: two_factor_enabled, two_factor_secret
  • New TwoFactorRecoveryCode entity + table (BCrypt-hashed, single-use)
  • RefreshToken: added user_agent, ip_address, last_used_at for
    session visibility
  • ITwoFactorService / TwoFactorService (Otp.NET) — TOTP generation,
    validation, recovery code hashing/verification
  • IRefreshTokenService / RefreshTokenService — rotation now records
    device info per issue/rotate
  • AuthController — 6 new endpoints: 2fa/setup, 2fa/confirm,
    2fa/disable, login/2fa, sessions (GET), sessions/{id} (revoke),
    sessions/revoke-others
  • Rate limiting added on auth endpoints via RateLimitingExtensions
  • Migration: AddTwoFactorAuth

Frontend

  • Login flow now branches on requires_two_factor from /auth/login
    into an MFA-challenge step
  • TwoFactorSetupComponent — QR + manual key display, confirm flow,
    one-time recovery code reveal
  • SessionsComponent — active session table, per-row revoke, revoke-all
  • Shell nav updated to link to the new Security section

Known issue / follow-up needed

Recovery code redemption on POST /auth/login/2fa currently returns 401
even for freshly-generated, unused codes, despite TwoFactorService's
hash/verify logic being correct in isolation. Suspect the bug is one
layer up in AuthService's login-with-2FA method (likely comparing a
freshly computed hash directly instead of calling VerifyRecoveryCode,
which won't work against salted BCrypt hashes). Needs a fix before
recovery codes can be relied on
— tracked as a follow-up, not blocking
this PR since TOTP login itself works end-to-end.

Testing done

  • Backend build clean (dotnet build), all production projects compile
  • Test suite updated for new AuthService/AuthController constructor
    signatures (18 pre-existing failures fixed)
  • Frontend build clean (ng build), no errors
  • Manual smoke test: login → 2FA setup → confirm → logout → login with
    TOTP code → sessions page shows session → revoke works
  • Recovery code login — reproducibly fails, see known issue above
  • Docker Compose full stack (rebuild.ps1) — verified via container logs

How to test locally

  1. dotnet ef database update (migration AddTwoFactorAuth)
  2. ./rebuild.ps1
  3. Log in, visit Security → Set up two-factor authentication
  4. Scan QR with an authenticator app, confirm, save recovery codes
  5. Log out, log back in — should prompt for a 6-digit code

@Akash29g
Akash29g requested a review from sumitgupta-cse July 27, 2026 10:47
@Akash29g
Akash29g requested a review from g9shubh as a code owner July 27, 2026 10:47
@Akash29g
Akash29g merged commit 4d82c17 into main Jul 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant