NestJS module for Keycloak authentication and administration. Provides multi-realm JWT authentication, 100+ admin REST API methods, route protection decorators, JWKS key caching, and comprehensive testing utilities.
- Multi-Realm JWT Authentication - Validate JWT tokens from any realm on a Keycloak instance with automatic JWKS key resolution and caching
- Comprehensive Admin API - 100+ methods for realm, user, group, role, session, and event management
- Route Protection Decorators -
@Public(),@CurrentUser(), and@Permissions()for fine-grained access control - JWKS Caching - Automatic signing key caching with configurable refresh intervals to minimize Keycloak calls
- Testing Utilities - Mock JWT tokens and strategies for integration testing without a running Keycloak instance
npm install @azerothian/keycloak-apinpm install @nestjs/common @nestjs/core @nestjs/config @nestjs/passport rxjsImport the auth module and configure your Keycloak instance:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { PassportModule } from '@nestjs/passport';
import { KeycloakStrategy, JwtAuthGuard } from '@azerothian/keycloak-api/auth';
@Module({
imports: [
ConfigModule.forRoot(),
PassportModule.register({ defaultStrategy: 'keycloak' }),
],
providers: [KeycloakStrategy, JwtAuthGuard],
})
export class AppModule {}Set environment variables:
KEYCLOAK_URL=https://keycloak.example.com
KEYCLOAK_REALM=your-realmProtect routes with the guard:
// users.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { JwtAuthGuard, CurrentUser, Public } from '@azerothian/keycloak-api/auth';
import { AuthenticatedUser } from '@azerothian/keycloak-api/types';
@Controller('users')
@UseGuards(JwtAuthGuard)
export class UsersController {
@Get('profile')
getProfile(@CurrentUser() user: AuthenticatedUser) {
return {
keycloakId: user.keycloakId,
username: user.username,
roles: user.roles,
};
}
@Get('health')
@Public()
healthCheck() {
return { status: 'ok' };
}
}Import the admin module to manage realms, users, groups, and roles:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { KeycloakAdminModule } from '@azerothian/keycloak-api/admin';
@Module({
imports: [
ConfigModule.forRoot(),
KeycloakAdminModule,
],
})
export class AppModule {}Set admin credentials in environment:
KEYCLOAK_URL=https://keycloak.example.com
KEYCLOAK_ADMIN_USERNAME=admin
KEYCLOAK_ADMIN_PASSWORD=password
KEYCLOAK_ADMIN_CLIENT_ID=admin-cli
KEYCLOAK_ADMIN_CLIENT_SECRET=your-client-secretUse the service in your application:
// realms.service.ts
import { Injectable } from '@nestjs/common';
import { KeycloakAdminService } from '@azerothian/keycloak-api/admin';
@Injectable()
export class RealmsService {
constructor(private kcAdmin: KeycloakAdminService) {}
async getAllRealms() {
return this.kcAdmin.getRealms();
}
async getRealmUsers(realmName: string) {
return this.kcAdmin.getUsers(realmName, { max: 100 });
}
async createUser(realmName: string, user: any) {
return this.kcAdmin.createUser(realmName, user);
}
}Control access with decorators:
import { Controller, Post, UseGuards } from '@nestjs/common';
import { JwtAuthGuard, Permissions, CurrentUser } from '@azerothian/keycloak-api';
import { AuthenticatedUser } from '@azerothian/keycloak-api/types';
@Controller('networks')
@UseGuards(JwtAuthGuard)
export class NetworksController {
@Post()
@Permissions('networks:create')
createNetwork(@CurrentUser() user: AuthenticatedUser, @Body() dto: CreateNetworkDto) {
return {
createdBy: user.keycloakId,
...dto,
};
}
}| Variable | Description | Example |
|---|---|---|
KEYCLOAK_URL |
Base URL of Keycloak instance | https://keycloak.example.com |
KEYCLOAK_REALM |
Primary realm for authentication | wirenet |
KEYCLOAK_ADMIN_USERNAME |
Admin account username (for admin API) | admin |
KEYCLOAK_ADMIN_PASSWORD |
Admin account password (for admin API) | password |
KEYCLOAK_ADMIN_CLIENT_ID |
Client ID for admin API authentication | admin-cli |
KEYCLOAK_ADMIN_CLIENT_SECRET |
Client secret for admin API (if using client credentials flow) | secret-key |
This package exports specialized modules. Import only what you need:
| Import Path | Exports | Purpose |
|---|---|---|
@azerothian/keycloak-api |
All exports | Root barrel - re-exports everything |
@azerothian/keycloak-api/admin |
KeycloakAdminService, KeycloakAdminModule |
Keycloak Admin REST API |
@azerothian/keycloak-api/auth |
KeycloakStrategy, JwtAuthGuard |
JWT authentication via Passport |
@azerothian/keycloak-api/decorators |
CurrentUser(), Public(), Permissions(), constants |
Route protection decorators |
@azerothian/keycloak-api/types |
KeycloakTokenPayload, AuthenticatedUser, session/event types, SERVICE_PERMISSIONS |
Type definitions |
@azerothian/keycloak-api/testing |
TestJwtStrategy, mock token factories |
Integration testing utilities |
Create mock JWT tokens for integration tests without a running Keycloak instance:
import { Test } from '@nestjs/testing';
import {
TestJwtStrategy,
createAdminToken,
createUserToken,
} from '@azerothian/keycloak-api/testing';
describe('UsersController (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture = await Test.createTestingModule({
controllers: [UsersController],
providers: [UsersService, TestJwtStrategy],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('should allow admin to access protected route', async () => {
const adminToken = createAdminToken('user-id-123', 'realm-id-456');
return request(app.getHttpServer())
.get('/users/profile')
.set('Authorization', `Bearer ${adminToken}`)
.expect(200);
});
it('should allow regular user with limited permissions', async () => {
const userToken = createUserToken('user-id-789', 'realm-id-456');
return request(app.getHttpServer())
.get('/users/profile')
.set('Authorization', `Bearer ${userToken}`)
.expect(200);
});
});Mock token factories create tokens with predefined roles and permissions:
createAdminToken()- Full system access (admin role with all permissions)createUserToken()- Regular user access (limited permissions)createPowerUserToken()- Elevated permissionscreateServiceAccountToken()- For service-to-service authenticationcreateSuperadminToken()- Maximum privileges (superadmin + admin roles)createMockJwtToken(payload, secret)- Custom token with arbitrary payload
MIT