Skip to content

Latest commit

 

History

History
144 lines (111 loc) · 7.22 KB

File metadata and controls

144 lines (111 loc) · 7.22 KB

NestJS Auth API

A production-oriented authentication and authorization API built with NestJS, TypeScript, PostgreSQL, Prisma, JWT, Auth0, and OpenAPI. It keeps the same REST contract and database model as the sibling Express implementation while using Nest modules, providers, guards, pipes, filters, and dependency injection.

Features

  • Local registration and login with bcrypt and signed JWTs
  • Auth0 RS256 access-token validation through remote JWKS
  • Database-backed permissions evaluated on every protected request
  • Direct and group-derived role assignments
  • Immutable built-in USER and ADMIN invariants
  • Serializable final-administrator protection
  • Transactional access-control audit logs
  • Cursor pagination and DTO validation
  • English, French, and Spanish problem details
  • Global and authentication-specific rate limits
  • Liveness and PostgreSQL readiness probes
  • Swagger UI, ReDoc, and raw OpenAPI JSON

Dependency injection design

Nest owns the application object graph. Controllers inject services, services inject repository abstractions, repositories inject PrismaService, and guards inject authentication services.

TypeScript interfaces do not exist at runtime, so repository and password abstractions use Symbol tokens:

@Injectable()
export class AuthService {
  constructor(
    @Inject(USER_REPOSITORY) private readonly users: UserRepository,
    @Inject(PASSWORD_HASHER) private readonly passwords: PasswordHasher,
    private readonly jwt: JwtService,
  ) {}
}

The module selects the production implementations:

providers: [
  { provide: USER_REPOSITORY, useClass: PrismaUserRepository },
  { provide: PASSWORD_HASHER, useClass: BcryptPasswordHasher },
];

Tests replace these providers with fakes through Test.createTestingModule().

Run locally

Requires Node.js 24 and PostgreSQL 14 or newer. Node 20 and 22 releases covered by the engines range are also supported.

nvm install
nvm use
cp .env.example .env
npm ci
npm run db:deploy
npm run db:seed
npm run start:dev

Set a strong JWT_SECRET and review all values in .env first. The seed uses ADMIN_SEED_NAME, ADMIN_SEED_EMAIL, and ADMIN_SEED_PASSWORD to create or update the initial administrator.

To run PostgreSQL with Docker instead, start the included service:

docker compose up -d postgres

The Compose service publishes PostgreSQL on host port 5433, so set DATABASE_URL=postgresql://postgres:postgres@localhost:5433/nestjs_auth_api when using it from the host.

The API defaults to http://localhost:3001. ReDoc is available at /redoc, Swagger UI at /docs, and OpenAPI JSON at /openapi.json when DOCS_ENABLED=true.

Authorization model

Permissions are stable, code-managed capabilities. Roles bundle permissions, groups receive roles, and users receive roles directly or through group membership. New local accounts always receive USER. Effective permissions are read from the database for authorization decisions, so revocation does not wait for a JWT to expire.

The built-in ADMIN role retains the full permission catalog, the built-in USER role cannot be removed from an account, and the final effective administrator cannot be removed. Access-control mutations and their audit records share one transaction.

API routes

Method Route Requirement
GET /health/live Public
GET /health/ready Public
GET /api/v1/locales Public
POST /api/v1/auth/register Public
POST /api/v1/auth/login Public
GET /api/v1/auth/me Local JWT
GET /api/v1/auth0/me Auth0 token
GET /api/v1/users users:read
PUT/DELETE /api/v1/users/:userId/roles/:roleId users:roles:manage; admins:manage when changing ADMIN
GET /api/v1/permissions roles:read
GET/POST /api/v1/roles roles:read / roles:manage
GET /api/v1/roles/:roleId roles:read
PUT/DELETE /api/v1/roles/:roleId/permissions/:permissionId roles:manage
GET/POST /api/v1/groups groups:read / groups:manage
GET /api/v1/groups/:groupId groups:read
PUT/DELETE /api/v1/groups/:groupId/roles/:roleId groups:manage; admins:manage when changing ADMIN
PUT/DELETE /api/v1/groups/:groupId/users/:userId groups:manage; admins:manage for an ADMIN group
GET /api/v1/audit-logs audit:read

Collections accept ?limit=25&cursor=UUID. Audit logs additionally accept actor, action, target, and date-range filters.

Errors use application/problem+json and include a stable code and request trace ID. Authentication responses are marked no-store.

Example

curl -X POST http://localhost:3001/api/v1/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"name":"Ada Lovelace","email":"ada@example.com","password":"correct-horse-42"}'

Use the returned access token as Authorization: Bearer YOUR_ACCESS_TOKEN for local-JWT routes.

Project structure

src/
  access-control/  RBAC controllers, services, DTOs, and repository
  auth/            Local JWT authentication and permission guard
  auth0/           Auth0 access-token integration
  common/          Request context, localization, errors, and problem filter
  config/          Environment validation
  database/        Prisma service and administrator seed
  docs/            ReDoc integration
  health/          Liveness and readiness endpoints
  locales/         Supported-locale endpoint
prisma/             Schema and migrations
test/               Unit and controller tests

Verification

npm run typecheck
npm run lint
npm test
npm run build
npx prisma validate

Do not commit .env, generated Prisma output, dist, coverage, or dependencies. Commit schema changes together with their migration and updated lockfile.