Nest Authbeta

Force password change (temporary passwords)

Make an admin-set temporary password genuinely temporary — the user can do exactly one thing with it: set a new one.

When an admin sets a temporary password for a member, the temp credential must not grant ongoing access — the only thing it should allow is setting a new password. The mustChangePassword flag does that, with two layers:

  • Surfaced flag (always on) — the user's mustChangePassword is returned on the login response and on /auth/me, so the UI can route straight to the change-password screen.
  • Hard-block guard (opt-in) — when enabled, the API itself rejects everything except the change-password flow until the password is rotated. The API is the real gate; the UI redirect is just convenience (and a direct API call can't bypass it).

1. Enable enforcement

NestAuthModule.forRoot({
  // …
  mustChangePassword: { enforce: true }, // hard-block at the guard (default: surface-only)
});

2. Set the flag when an admin assigns a temp password

Set it only on the admin-sets-another-user's-password path — not on self-service set-password or a member's own change (they pick their own there), and not on invites (the member sets their own).

// In your "admin sets a temporary password" handler:
await user.setPassword(tempPassword);              // NestAuthUser.setPassword()
await this.userService.updateUser(user.id, { mustChangePassword: true });
// (revoking the member's existing sessions is also fine, but no longer required —
//  the guard alone makes the temp credential useless beyond changing the password.)

3. What the guard allows while the flag is set

With enforce: true, a flagged user gets 403 MUST_CHANGE_PASSWORD on every guarded route except the allowlist needed to finish signing in and rotate the password:

  • change-password, logout
  • the current-user / session endpoints (/auth/me, /auth/user, verify-session)
  • refresh-token
  • the MFA and email/phone verification routes (so a 2FA user can complete sign-in)

Exempt your own routes that must stay reachable with @SkipMustChangePassword():

import { SkipMustChangePassword, Auth } from '@ackplus/nest-auth';
 
@Auth()
@SkipMustChangePassword()
@Get('terms')
terms() { /* reachable even while a password change is pending */ }

4. It clears itself

A successful change-password (or set-a-new-password via reset-password) clears mustChangePassword automatically — the user resumes normal access.

Client

const { mustChangePassword } = await client.login(dto);   // surfaced on login
// …or read it any time from /auth/me:
const me = await client.getSessionUserData();             // me.mustChangePassword
if (me.mustChangePassword) routeTo('/change-password');
// A 403 with code MUST_CHANGE_PASSWORD on any other call means the same thing.

On this page