Nest Authbeta

Email + Password

Classic email and password sign-up and sign-in.

The default. Users sign up with an email and a password, then log in with the same.

Server config

import { NestAuthModule } from '@ackplus/nest-auth';
 
NestAuthModule.forRoot({
  appName: 'My App',
  emailAuth: { enabled: true },          // on by default
  registration: { enabled: true },
});

To disable email signup but keep email login: leave emailAuth.enabled: true and set registration.enabled: false (or registration.requireInvitation: true).

Endpoints

MethodPathPurpose
POST/auth/signupCreate a user with { email, password, … }
POST/auth/loginLogin with { providerName: 'email', credentials: { email, password } }

Client call

import { AuthClient } from '@ackplus/nest-auth-client';
 
const client = new AuthClient({ baseUrl: '/api' });
 
await client.signup({
  email: 'alice@example.com',
  password: 'correct horse battery staple',
  // any extra fields land on the UserRegisteredEvent payload
  firstName: 'Alice',
  referralCode: 'ABC123',
});
 
await client.login({
  credentials: { email: 'alice@example.com', password: 'correct horse battery staple' },
});

React hook

import { useNestAuth } from '@ackplus/nest-auth-react';
 
function SignInForm() {
  const { login, error, isLoading } = useNestAuth();
 
  return (
    <form onSubmit={async (e) => {
      e.preventDefault();
      await login({ credentials: { email, password } });
    }}>

    </form>
  );
}

Password hashing

The library hashes with argon2id. Change the cost via password.argon2. Replace the algorithm entirely via password.hash / password.verify hooks (see Hooks Reference).

Password policy

Opt in to a built-in strength policy via password.policy. It's enforced uniformly at every password-set path — signup, change-password, reset-password, and admin-set (and admin-console passwords) — because it runs inside the entity's setPassword, so it can't be bypassed:

NestAuthModule.forRoot({
  password: {
    policy: {
      enabled: true,               // opt-in; default off (no behavior change until you turn it on)
      minLength: 8,                // NIST favors length; bump to 12+ if you like
      maxLength: 128,              // also guards against unbounded-input hashing
      blockCommonPasswords: true,  // built-in small common-password list
      blocklist: ['MyApp2024'],    // your own additions (case-insensitive)
      blockContainsIdentifier: true, // reject a password containing the email local-part
      checkBreached: true,         // Have I Been Pwned (see below)
      hibp: { timeoutMs: 2000, failOpen: true },
    },
  },
});

Failures return 400 with a specific code: PASSWORD_TOO_SHORT, PASSWORD_TOO_LONG, PASSWORD_TOO_COMMON, PASSWORD_CONTAINS_IDENTIFIER, or PASSWORD_BREACHED.

Breached-password check (Have I Been Pwned)

With checkBreached: true, passwords are checked against HIBP's ~1B leaked-password corpus using k-anonymity: the password is SHA-1'd and only the first 5 hex chars of the hash are sent — the password (and its full hash) never leave your server. The check is fail-open by default (an HIBP outage won't block password changes); set hibp.failOpen: false to fail closed. hibp.baseUrl can point at an enterprise proxy.

Prefer this policy over a registrationHooks.beforeSignup password check — the hook only covers signup, whereas the policy also covers change/reset/admin-set.

Forgot password

Three endpoints chain together:

  1. POST /auth/forgot-password { email } → emits PasswordResetRequestedEvent (your listener sends the OTP/link).
  2. POST /auth/verify-forgot-password-otp { email, code } → returns a resetToken.
  3. POST /auth/reset-password { token, newPassword } → emits PasswordResetEvent.

See Sending Emails for the listener wiring.

Requiring a verified email

By default a user is signed in immediately at signup, even before verifying their email. To hard-block unverified users from protected routes, set registration.requireVerifiedEmail:

NestAuthModule.forRoot({
  registration: { requireVerifiedEmail: true },
});

A signed-in but unverified user then gets 403 EMAIL_NOT_VERIFIED on every guarded route except the library's own verification / logout / current-user / session / refresh / MFA routes (so they can still verify their email or sign out). Mark any of your own routes that must stay reachable with @SkipEmailVerification(). The check re-reads the user's verified state on each request, so it clears the moment they verify — no re-login needed. (This mirrors the mustChangePassword hard-block.)

Wire the actual verification email off your verification event — see Sending Emails.

Blocking disposable email domains

Reject sign-ups from throwaway/disposable email providers. The blocklist lives in the DB and is managed from the admin console (the "Blocked Email Domains" page), seedable from a built-in ~8k default list. Opt in:

NestAuthModule.forRoot({
  emailAuth: {
    enabled: true,
    disposable: {
      enabled: true,
      mode: 'block',                 // 'block' (reject, default) or 'flag' (allow + emit an event)
      allowlist: ['mycompany.com'],  // always allow these, even if listed
    },
  },
});

A sign-up whose email domain is on the list gets 403 EMAIL_DOMAIN_NOT_ALLOWED (or, in flag mode, is allowed but emits a disposable_email_detected event you can log). Manage the list in the dashboard — search, add, remove, and Import defaults to seed the built-in list. (API: <admin base>/api/blocked-email-domains.)

On this page