Tutorial
NestJS Integration
Protect NestJS controllers and methods with AuthMe guards, custom decorators, and role-based access control.
Installation
Terminal
npm install authme-sdk @nestjs/passport passport passport-jwt AuthMe Module
Create a dedicated NestJS module that initialises the AuthMe client and exposes it for injection.
src/auth/authme.module.ts
import { Module } from '@nestjs/common';
import { AuthmeClient } from 'authme-sdk';
import { ConfigService } from '@nestjs/config';
export const AUTHME_CLIENT = 'AUTHME_CLIENT';
@Module({
providers: [
{
provide: AUTHME_CLIENT,
useFactory: (cfg: ConfigService) =>
new AuthmeClient({
url: cfg.getOrThrow('AUTHME_URL'),
realm: cfg.getOrThrow('AUTHME_REALM'),
}),
inject: [ConfigService],
},
],
exports: [AUTHME_CLIENT],
})
export class AuthmeModule {} AuthMe Guard
Implement a NestJS CanActivate guard that validates the Bearer token and attaches the user payload to the request.
src/auth/auth.guard.ts
import {
CanActivate, ExecutionContext, Inject,
Injectable, UnauthorizedException,
} from '@nestjs/common';
import { AuthmeClient } from 'authme-sdk';
import { AUTHME_CLIENT } from './authme.module';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(@Inject(AUTHME_CLIENT) private readonly authme: AuthmeClient) {}
async canActivate(ctx: ExecutionContext): Promise<boolean> {
const req = ctx.switchToHttp().getRequest();
const token = this.extractToken(req);
if (!token) throw new UnauthorizedException();
try {
req.user = await this.authme.verifyToken(token);
return true;
} catch {
throw new UnauthorizedException('Invalid token');
}
}
private extractToken(req: any): string | undefined {
const [type, token] = req.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : undefined;
}
} CurrentUser Decorator
Create a parameter decorator to cleanly extract the authenticated user inside controller methods.
src/auth/current-user.decorator.ts
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const CurrentUser = createParamDecorator(
(_data: unknown, ctx: ExecutionContext) =>
ctx.switchToHttp().getRequest().user,
); Role-Based Access Control
Use a Roles decorator together with a RolesGuard to restrict controller methods to specific roles.
src/auth/roles.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const ROLES_KEY = 'roles';
export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles); src/auth/roles.guard.ts
import {
CanActivate, ExecutionContext, Injectable,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLES_KEY } from './roles.decorator';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(ctx: ExecutionContext): boolean {
const required = this.reflector.getAllAndOverride<string[]>(ROLES_KEY, [
ctx.getHandler(),
ctx.getClass(),
});
if (!required?.length) return true;
const { user } = ctx.switchToHttp().getRequest();
return required.some((r) => user?.roles?.includes(r));
}
} src/users/users.controller.ts
@Controller('users')
@UseGuards(AuthGuard, RolesGuard)
export class UsersController {
@Get()
@Roles('admin')
findAll() { return this.usersService.findAll(); }
@Get('profile')
// No @Roles — any authenticated user can access
getProfile(@CurrentUser() user: any) {
return user;
}
}