@edirect/auth
Authentication and authorization module for eDirect NestJS applications. Supports two auth providers — Keycloak (OIDC/JWT) and a custom Auth Service — with guards, middleware, decorators, and multi-tenant realm support.
Features
- Two provider strategies: Keycloak and custom Auth Service
- NestJS Guards and Middleware for request-level auth enforcement
- Role, Permission, and Resource decorators for fine-grained access control
- Token Exchange middleware for cross-service impersonation flows
- Multi-tenant support: per-realm environment variable overrides
- Token caching via
AuthCacheService
- JWKS-based token validation with OIDC well-known discovery
- Type-safe request interfaces (
AuthenticatedRequestInterface, UserInterface, TokenInterface)
Installation
pnpm add @edirect/auth
npm install @edirect/auth
Provider Options
Option A: Keycloak
import { Module } from '@nestjs/common';
import { KeycloakAuthModule } from '@edirect/auth';
@Module({
imports: [KeycloakAuthModule],
})
export class AppModule {}
import { Controller, Get, UseGuards } from '@nestjs/common';
import { KeycloakAuthGuard, Permissions, Roles } from '@edirect/auth';
@Controller('policies')
export class PoliciesController {
@Get()
@UseGuards(KeycloakAuthGuard)
@Roles('agent', 'admin')
@Permissions('read:policy')
findAll() {
return [];
}
}
Option B: Custom Auth Service
import { Module } from '@nestjs/common';
import { AuthServiceAuthModule } from '@edirect/auth';
@Module({
imports: [AuthServiceAuthModule],
})
export class AppModule {}
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard, Roles } from '@edirect/auth';
@Controller('quotes')
export class QuotesController {
@Get()
@UseGuards(AuthGuard)
@Roles('agent')
findAll() {
return [];
}
}
Decorators
@Roles(...roles) | Require one of the specified roles |
@Permissions(...perms) | Require one of the specified permissions |
@Resources(...resources) | Require access to specific resources |
Middleware
For Express/NestJS middleware usage (without guards):
import { KeycloakAuthMiddleware } from '@edirect/auth';
consumer
.apply(KeycloakAuthMiddleware)
.forRoutes({ path: '/**', method: RequestMethod.ALL });
import { KeycloakAuthTokenExchangeMiddleware } from '@edirect/auth';
consumer
.apply(KeycloakAuthTokenExchangeMiddleware)
.forRoutes({ path: '/internal/**', method: RequestMethod.ALL });
Authenticated Request
Once authentication middleware or guard runs, req.user is populated:
import { AuthenticatedRequestInterface } from '@edirect/auth';
@Get('me')
@UseGuards(KeycloakAuthGuard)
getProfile(@Req() req: AuthenticatedRequestInterface) {
return req.user;
}
Environment Variables
Keycloak
KEYCLOAK_BASE_URL | Keycloak server base URL |
KEYCLOAK_REALM | Realm name |
KEYCLOAK_CLIENT_ID | Client ID |
KEYCLOAK_CLIENT_SECRET | Client secret |
KEYCLOAK_TIMEOUT | Request timeout (ms, optional) |
Multi-Tenant Realm Override
For multi-tenant deployments, override per realm using the pattern KEYCLOAK_<REALM>_<VAR>:
KEYCLOAK_TH_BROKER_CLIENT_ID=my-client-th
KEYCLOAK_TH_BROKER_CLIENT_SECRET=secret-th
KEYCLOAK_TH_BROKER_BASE_URL=https://keycloak.th.example.com
Custom Auth Service
AUTH_SERVICE_URL | Base URL of the auth service |
AUTH_SERVICE_TOKEN | Service token for internal auth |
Exports
export {
AuthModule,
AuthServiceAuthModule,
KeycloakAuthModule,
} from '@edirect/auth';
export { AuthGuard, KeycloakAuthGuard } from '@edirect/auth';
export {
AuthMiddleware,
KeycloakAuthMiddleware,
KeycloakAuthTokenExchangeMiddleware,
} from '@edirect/auth';
export { Permissions, Roles, Resources } from '@edirect/auth';
export { AuthService, ServerAuthService } from '@edirect/auth';
export type {
UserInterface,
TokenInterface,
EntityInterface,
AuthenticatedRequestInterface,
AuthServiceInterface,
ServerAuthServiceInterface,
} from '@edirect/auth';