### Install NestJS Project Dependencies Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/example/README.md Navigate to the project directory, build the project, then install dependencies for the example application. ```bash cd ../ npm run build cd example npm install ``` -------------------------------- ### Install Nest Keycloak Connect with Yarn Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Use this command to install the necessary packages using Yarn. ```bash yarn add nest-keycloak-connect keycloak-connect ``` -------------------------------- ### Install Nest Keycloak Connect with NPM Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Use this command to install the necessary packages using NPM. ```bash npm install nest-keycloak-connect keycloak-connect --save ``` -------------------------------- ### ResourceGuard Example Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Demonstrates the use of ResourceGuard with @Resource and @Scopes decorators to enforce Keycloak Authorization Services policies on controller methods. ```APIDOC ## GET /orders ### Description Retrieves a list of orders. Requires the 'View' scope for the 'orders' resource. ### Method GET ### Endpoint /orders ### Parameters #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - An empty array `[]` is returned. #### Response Example [] ## POST /orders ### Description Creates a new order. Requires the 'Create' scope for the 'orders' resource. ### Method POST ### Endpoint /orders #### Request Body - **dto** (any) - Required - The order data to create. ### Request Example ```json { "example": "request body" } ``` ### Response #### Success Response (200) - Returns the created order data. #### Response Example ```json { "example": "request body" } ``` ## DELETE /orders/:id ### Description Deletes an order by its ID. Requires the 'Delete' scope for the 'orders' resource. ### Method DELETE ### Endpoint /orders/:id #### Parameters ##### Path Parameters - **id** (string) - Required - The ID of the order to delete. ### Request Example None ### Response #### Success Response (200) - Returns an object indicating the deleted status. #### Response Example ```json { "deleted": "order-id" } ``` ``` -------------------------------- ### Run NestJS Application Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/example/README.md Execute the command to start the NestJS application in development mode. ```bash npm run start ``` -------------------------------- ### RoleGuard Example Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Illustrates the usage of RoleGuard with @Roles and @RoleMatchingMode decorators for role-based access control. ```APIDOC ## GET /admin/users ### Description Lists all users. Requires the realm role 'admin'. ### Method GET ### Endpoint /admin/users ### Parameters None ### Request Example None ### Response #### Success Response (200) - An empty array `[]` is returned. #### Response Example [] ## GET /admin/reports ### Description Retrieves reports. Requires both realm roles 'admin' and 'auditor'. ### Method GET ### Endpoint /admin/reports ### Parameters None ### Request Example None ### Response #### Success Response (200) - An empty array `[]` is returned. #### Response Example [] ## GET /admin/dashboard ### Description Retrieves the dashboard. Requires either the 'app:viewer' or 'app:editor' application role. ### Method GET ### Endpoint /admin/dashboard ### Parameters None ### Request Example None ### Response #### Success Response (200) - An empty array `[]` is returned. #### Response Example [] ``` -------------------------------- ### Get Resolved Scopes with @ResolvedScopes() Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt The @ResolvedScopes() parameter decorator injects the list of scopes determined after @ConditionalScopes evaluation. Use this to check for specific permissions within a route handler. ```typescript import { Get } from '@nestjs/common'; import { ConditionalScopes, ResolvedScopes, Resource } from 'nest-keycloak-connect'; @Resource('Report') export class ReportController { @Get() @ConditionalScopes((req, token) => token.hasRealmRole('admin') ? ['Export'] : []) list(@ResolvedScopes() scopes: string[]) { const canExport = scopes.includes('Export'); return { canExport, data: [] }; } } ``` -------------------------------- ### Synchronous Module Registration with Inline Configuration Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Use this method for inline configuration of the Keycloak module. Ensure all necessary imports are present. The order of APP_GUARD providers is important for correct validation. ```typescript import { Module } from '@nestjs/common'; import { APP_GUARD, KeycloakConnectModule, PolicyEnforcementMode, ResourceGuard, RoleGuard, TokenValidation, } from 'nest-keycloak-connect'; @Module({ imports: [ KeycloakConnectModule.register({ authServerUrl: 'http://localhost:8080', realm: 'master', clientId: 'my-nestjs-app', secret: 'my-client-secret', policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // allow routes with no @Resource tokenValidation: TokenValidation.ONLINE, // validate tokens live via Keycloak }), ], providers: [ { provide: APP_GUARD, useClass: AuthGuard }, // 1st: verifies JWT { provide: APP_GUARD, useClass: ResourceGuard }, // 2nd: checks resource/scope { provide: APP_GUARD, useClass: RoleGuard }, // 3rd: checks roles ], }) export class AppModule {} ``` -------------------------------- ### Async Module Registration with KeycloakConfigService Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Register the module asynchronously using a KeycloakConfigService. This approach is useful for managing configuration dynamically. ```typescript KeycloakConnectModule.registerAsync({ useExisting: KeycloakConfigService, imports: [ConfigModule], }); ``` -------------------------------- ### Asynchronous Module Registration with useExisting Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Asynchronously registers the module using an existing configuration service. This pattern is useful when configuration is managed by another module, like ConfigModule. ```typescript // config/keycloak-config.service.ts import { Injectable } from '@nestjs/common'; import { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation, } from 'nest-keycloak-connect'; @Injectable() export class KeycloakConfigService implements KeycloakConnectOptionsFactory { createKeycloakConnectOptions(): KeycloakConnectOptions { return { authServerUrl: process.env.KEYCLOAK_URL ?? 'http://localhost:8080', realm: process.env.KEYCLOAK_REALM ?? 'master', clientId: process.env.KEYCLOAK_CLIENT_ID ?? 'nest-api', secret: process.env.KEYCLOAK_SECRET ?? 'secret', policyEnforcement: PolicyEnforcementMode.PERMISSIVE, tokenValidation: TokenValidation.ONLINE, }; } } // app.module.ts – useExisting import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; // Assuming ConfigModule is used import { KeycloakConnectModule } from 'nest-keycloak-connect'; @Module({ imports: [ KeycloakConnectModule.registerAsync({ useExisting: KeycloakConfigService, imports: [ConfigModule], }), ], }) export class AppModule {} ``` -------------------------------- ### KeycloakConfigService Implementation Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Implement KeycloakConnectOptionsFactory to provide Keycloak connection options. This service allows for centralized configuration management. ```typescript import { Injectable, } from '@nestjs/common'; import { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation, } from 'nest-keycloak-connect'; @Injectable() export class KeycloakConfigService implements KeycloakConnectOptionsFactory { createKeycloakConnectOptions(): KeycloakConnectOptions { return { // http://localhost:8080/auth for older keycloak versions authServerUrl: 'http://localhost:8080', realm: 'master', clientId: 'my-nestjs-app', secret: 'secret', policyEnforcement: PolicyEnforcementMode.PERMISSIVE, tokenValidation: TokenValidation.ONLINE, }; } } ``` -------------------------------- ### Keycloak Connect Module Configuration Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Global configuration for the Keycloak Connect module, controlling policy enforcement mode, token validation, and role merging. ```APIDOC ## Enums and Configuration ### `PolicyEnforcementMode`, `TokenValidation`, `RoleMatch`, `RoleMerge` Core enums that control guard behavior globally via module configuration or per-request. ### Configuration Example ```typescript import { KeycloakConnectModule, PolicyEnforcementMode, RoleMerge, TokenValidation, } from 'nest-keycloak-connect'; KeycloakConnectModule.register({ authServerUrl: 'http://localhost:8080', realm: 'my-realm', clientId: 'nest-api', secret: 'client-secret', // PERMISSIVE: allow requests on routes without @Resource (default) // ENFORCING: deny requests on routes without @Resource policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // ONLINE: validate tokens live via Keycloak introspection endpoint (default) // OFFLINE: validate tokens locally against realm public key // NONE: skip validation entirely (development only) tokenValidation: TokenValidation.ONLINE, // OVERRIDE: handler-level @Roles overrides controller-level @Roles (default) // ALL: merge @Roles from both controller and handler roleMerge: RoleMerge.ALL, cookieKey: 'KEYCLOAK_JWT', // name of the cookie to read the token from }); ``` ``` -------------------------------- ### KeycloakConnectModule.registerAsync Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Asynchronously registers the module, allowing options to be sourced from a config service, factory function, or existing provider. ```APIDOC ## KeycloakConnectModule.registerAsync(opts) ### Description Asynchronously registers the module, allowing options to be sourced from a config service, factory function, or existing provider. Supports `useExisting`, `useClass`, and `useFactory` patterns. ### Method `KeycloakConnectModule.registerAsync(opts)` ### Parameters #### opts - **useExisting** (Type) - Use when the configuration is provided by an existing `KeycloakConnectOptionsFactory` implementation. - **useClass** (Type) - Use when the configuration is provided by a class that implements `KeycloakConnectOptionsFactory`. - **useFactory** (FactoryFunction) - Use when the configuration is provided by a factory function. - **imports** (Module[]) - Optional - An array of modules that provide the necessary dependencies for the `useFactory` or `useClass` providers. - **inject** (any[]) - Optional - An array of providers to inject into the `useFactory` function. ### Request Example ```typescript // config/keycloak-config.service.ts import { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation, } from 'nest-keycloak-connect'; @Injectable() export class KeycloakConfigService implements KeycloakConnectOptionsFactory { createKeycloakConnectOptions(): KeycloakConnectOptions { return { authServerUrl: process.env.KEYCLOAK_URL ?? 'http://localhost:8080', realm: process.env.KEYCLOAK_REALM ?? 'master', clientId: process.env.KEYCLOAK_CLIENT_ID ?? 'nest-api', secret: process.env.KEYCLOAK_SECRET ?? 'secret', policyEnforcement: PolicyEnforcementMode.PERMISSIVE, tokenValidation: TokenValidation.ONLINE, }; } } // app.module.ts – useExisting @Module({ imports: [ KeycloakConnectModule.registerAsync({ useExisting: KeycloakConfigService, imports: [ConfigModule], }), ], }) export class AppModule {} // app.module.ts – useFactory with ConfigService KeycloakConnectModule.registerAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (config: ConfigService): KeycloakConnectOptions => ({ authServerUrl: config.get('KEYCLOAK_URL'), realm: config.get('KEYCLOAK_REALM'), clientId: config.get('KEYCLOAK_CLIENT_ID'), secret: config.get('KEYCLOAK_SECRET'), }), }); ``` ``` -------------------------------- ### KeycloakConnectModule.register Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Synchronously registers the Keycloak module with an inline configuration or a path to a keycloak.json file. ```APIDOC ## KeycloakConnectModule.register(opts, config?) ### Description Synchronously registers the Keycloak module using an inline configuration object or a path to a `keycloak.json` file. Accepts an optional `NestKeycloakConfig` as the second argument when using a file path. ### Method `KeycloakConnectModule.register(opts, config?)` ### Parameters #### opts - **authServerUrl** (string) - Required - The base URL of the Keycloak server. - **realm** (string) - Required - The Keycloak realm name. - **clientId** (string) - Required - The Keycloak client ID for the application. - **secret** (string) - Required - The client secret for authentication. - **policyEnforcement** (PolicyEnforcementMode) - Optional - Sets the policy enforcement mode (PERMISSIVE or ENFORCING). - **tokenValidation** (TokenValidation) - Optional - Sets the token validation strategy (ONLINE, OFFLINE, or NONE). #### config (optional) - **policyEnforcement** (PolicyEnforcementMode) - Optional - Sets the policy enforcement mode when using a file path. - **tokenValidation** (TokenValidation) - Optional - Sets the token validation strategy when using a file path. ### Request Example ```typescript // app.module.ts – inline configuration import { AuthGuard, KeycloakConnectModule, PolicyEnforcementMode, ResourceGuard, RoleGuard, TokenValidation, } from 'nest-keycloak-connect'; @Module({ imports: [ KeycloakConnectModule.register({ authServerUrl: 'http://localhost:8080', realm: 'master', clientId: 'my-nestjs-app', secret: 'my-client-secret', policyEnforcement: PolicyEnforcementMode.PERMISSIVE, tokenValidation: TokenValidation.ONLINE, }), ], providers: [ { provide: APP_GUARD, useClass: AuthGuard }, { provide: APP_GUARD, useClass: ResourceGuard }, { provide: APP_GUARD, useClass: RoleGuard }, ], }) export class AppModule {} // Alternative: register from keycloak.json file KeycloakConnectModule.register('./keycloak.json', { policyEnforcement: PolicyEnforcementMode.ENFORCING, tokenValidation: TokenValidation.OFFLINE, }); ``` ``` -------------------------------- ### Configure Controller with Keycloak Guards Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Use decorators like @Resource, @Roles, @Scopes, and @Public to define access control for controller methods. Ensure proper imports from nest-keycloak-connect. ```typescript import { Resource, Roles, Scopes, Public, RoleMatchingMode, } from 'nest-keycloak-connect'; import { Controller, Get, Delete, Put, Post, Param } from '@nestjs/common'; import { Product } from './product'; import { ProductService } from './product.service'; @Controller() @Resource(Product.name) export class ProductController { constructor(private service: ProductService) {} @Get() @Public() async findAll() { return await this.service.findAll(); } @Get() @Roles({ roles: ['admin', 'other'] }) async findAllBarcodes() { return await this.service.findAllBarcodes(); } @Get(':code') @Scopes('View') async findByCode(@Param('code') code: string) { return await this.service.findByCode(code); } @Post() @Scopes('Create') @ConditionalScopes((request, token) => { if (token.hasRealmRole('sysadmin')) { return ['Overwrite']; } return []; }) async create(@Body() product: Product) { return await this.service.create(product); } @Delete(':code') @Scopes('Delete') @Roles({ roles: ['admin', 'realm:sysadmin'], mode: RoleMatchingMode.ALL }) async deleteByCode(@Param('code') code: string) { return await this.service.deleteByCode(code); } @Put(':code') @Scopes('Edit') async update(@Param('code') code: string, @Body() product: Product) { return await this.service.update(code, product); } } ``` -------------------------------- ### Multi-tenant Configuration for Keycloak Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Configure multi-tenancy by defining realm resolvers and client ID resolvers within the Keycloak options. Ensure the authServerUrl is correctly set, especially for older Keycloak versions. ```typescript { // Add /auth for older keycloak versions authServerUrl: 'http://localhost:8180/', // will be used as fallback clientId: 'nest-api', // will be used as fallback secret: 'fallback', // will be used as fallback multiTenant: { resolveAlways: true, realmResolver: (request) => { return request.get('host').split('.')[0]; }, realmSecretResolver: (realm, request) => { const secrets = { master: 'secret', slave: 'password' }; return secrets[realm]; }, realmClientIdResolver: (realm, request) => { const clientIds = { master: 'angular-app', slave: 'vue-app' }; return clientIds[realm]; }, // note to add /auth for older keycloak versions realmAuthServerUrlResolver: (realm, request) => { const authServerUrls = { master: 'https://master.local/', slave: 'https://slave.local/' }; return authServerUrls[realm]; } } } ``` -------------------------------- ### Synchronous Module Registration from keycloak.json Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Register the Keycloak module by providing a path to the keycloak.json configuration file. This alternative allows for different policy enforcement and token validation settings. ```typescript KeycloakConnectModule.register('./keycloak.json', { policyEnforcement: PolicyEnforcementMode.ENFORCING, tokenValidation: TokenValidation.OFFLINE, }); ``` -------------------------------- ### Implement KeycloakConnectOptionsFactory for Async Configuration Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Implement this interface in a service class to provide Keycloak options asynchronously using `registerAsync`. This integrates cleanly with NestJS `ConfigModule`. ```typescript import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation, } from 'nest-keycloak-connect'; @Injectable() export class KeycloakConfigService implements KeycloakConnectOptionsFactory { constructor(private readonly config: ConfigService) {} createKeycloakConnectOptions(): KeycloakConnectOptions { return { authServerUrl: this.config.getOrThrow('KEYCLOAK_URL'), realm: this.config.getOrThrow('KEYCLOAK_REALM'), clientId: this.config.getOrThrow('KEYCLOAK_CLIENT_ID'), secret: this.config.getOrThrow('KEYCLOAK_SECRET'), policyEnforcement: PolicyEnforcementMode.PERMISSIVE, tokenValidation: TokenValidation.ONLINE, }; } } ``` -------------------------------- ### Global Guard Registration using APP_GUARD Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Register AuthGuard, ResourceGuard, and RoleGuard globally using the APP_GUARD token. Ensure the order is correct for proper guard execution. ```typescript providers: [ { provide: APP_GUARD, useClass: AuthGuard, }, { provide: APP_GUARD, useClass: ResourceGuard, }, { provide: APP_GUARD, useClass: RoleGuard, }, ]; ``` -------------------------------- ### Asynchronous Module Registration with useFactory Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Asynchronously registers the module using a factory function. This allows for dynamic configuration based on environment variables or other services. Ensure the ConfigService is imported and injected. ```typescript import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { KeycloakConnectModule, KeycloakConnectOptions } from 'nest-keycloak-connect'; @Module({ imports: [ KeycloakConnectModule.registerAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (config: ConfigService): KeycloakConnectOptions => ({ authServerUrl: config.get('KEYCLOAK_URL'), realm: config.get('KEYCLOAK_REALM'), clientId: config.get('KEYCLOAK_CLIENT_ID'), secret: config.get('KEYCLOAK_SECRET'), }), }), ], }) export class AppModule {} ``` -------------------------------- ### @Resource Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Marks a controller or route handler with a Keycloak resource name, used by ResourceGuard. ```APIDOC ## GET /invoices ### Description Lists all invoices. This endpoint is associated with the Keycloak resource named 'Invoice'. ### Method GET ### Endpoint /invoices ### Parameters None ### Request Example None ### Response #### Success Response (200) - An empty array `[]` is returned. #### Response Example [] ``` -------------------------------- ### Register Keycloak Module with keycloak.json Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Register the KeycloakConnectModule by providing the path to your keycloak.json file and optional module configuration. ```typescript KeycloakConnectModule.register(`./keycloak.json`, { policyEnforcement: PolicyEnforcementMode.PERMISSIVE, tokenValidation: TokenValidation.ONLINE, }); ``` -------------------------------- ### Configure Multi-Tenant Options in AppModule Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Enables per-request realm resolution for serving multiple Keycloak realms from a single NestJS application. Resolvers can be synchronous or asynchronous. ```typescript import { Module } from '@nestjs/common'; import { APP_GUARD } from '@nestjs/core'; import { AuthGuard, KeycloakConnectModule, ResourceGuard, RoleGuard } from 'nest-keycloak-connect'; @Module({ imports: [ KeycloakConnectModule.register({ authServerUrl: 'http://localhost:8080', // fallback URL clientId: 'nest-api', // fallback client-id secret: 'fallback-secret', // fallback secret multiTenant: { // Always re-resolve realm/secret on each request (default: false = cache instances) resolveAlways: false, // Derive realm from subdomain: tenant-a.example.com → "tenant-a" realmResolver: (request) => request.get('host').split('.')[0], // Return different secrets per realm realmSecretResolver: async (realm) => { const secrets: Record = { 'tenant-a': 'secret-a', 'tenant-b': 'secret-b', }; return secrets[realm] ?? 'fallback-secret'; }, // Return different client IDs per realm (required) realmClientIdResolver: (realm) => { const clients: Record = { 'tenant-a': 'app-tenant-a', 'tenant-b': 'app-tenant-b', }; return clients[realm] ?? 'nest-api'; }, // Return different Keycloak server URLs per realm (optional) realmAuthServerUrlResolver: (realm) => { const urls: Record = { 'tenant-a': 'https://keycloak-a.internal/', 'tenant-b': 'https://keycloak-b.internal/', }; return urls[realm] ?? 'http://localhost:8080'; }, }, }), ], providers: [ { provide: APP_GUARD, useClass: AuthGuard }, { provide: APP_GUARD, useClass: ResourceGuard }, { provide: APP_GUARD, useClass: RoleGuard }, ], }) export class AppModule {} ``` -------------------------------- ### Configure Keycloak Module with Enums Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Configure the KeycloakConnectModule globally using options like policyEnforcement, tokenValidation, and roleMerge. These enums control guard behavior and token processing. ```typescript import { KeycloakConnectModule, PolicyEnforcementMode, RoleMerge, TokenValidation, } from 'nest-keycloak-connect'; KeycloakConnectModule.register({ authServerUrl: 'http://localhost:8080', realm: 'my-realm', clientId: 'nest-api', secret: 'client-secret', // PERMISSIVE: allow requests on routes without @Resource (default) // ENFORCING: deny requests on routes without @Resource policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // ONLINE: validate tokens live via Keycloak introspection endpoint (default) // OFFLINE: validate tokens locally against realm public key // NONE: skip validation entirely (development only) tokenValidation: TokenValidation.ONLINE, // OVERRIDE: handler-level @Roles overrides controller-level @Roles (default) // ALL: merge @Roles from both controller and handler roleMerge: RoleMerge.ALL, cookieKey: 'KEYCLOAK_JWT', // name of the cookie to read the token from }); ``` -------------------------------- ### @EnforcerOptions(opts) Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Passes custom `keycloak-connect` enforcer options to `ResourceGuard` for a specific controller or route handler. Useful for customizing claims sent to the Keycloak authorization endpoint. ```APIDOC ## @EnforcerOptions(opts) ### Description Passes custom `keycloak-connect` enforcer options to `ResourceGuard` for a specific controller or route handler. Useful for customizing claims sent to the Keycloak authorization endpoint. ### Usage ```typescript import { Get } from '@nestjs/common'; import { EnforcerOptions, Resource, Scopes } from 'nest-keycloak-connect'; @Resource('Document') export class DocumentController { @Get(':id') @Scopes('View') @EnforcerOptions({ claims: (request: any) => ({ 'document.owner': [request.params.id], 'user.department': [request.headers['x-department']], }), }) findOne() { return {}; } } ``` ``` -------------------------------- ### Register Keycloak Connect Module Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Register the KeycloakConnectModule with your application configuration. Ensure to adjust the authServerUrl for older Keycloak versions. ```typescript KeycloakConnectModule.register({ authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions realm: 'master', clientId: 'my-nestjs-app', secret: 'secret', policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // optional tokenValidation: TokenValidation.ONLINE, // optional }); ``` -------------------------------- ### @Roles Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Specifies realm or application roles required for route access, with options for matching mode. ```APIDOC ## GET /users ### Description Lists users. Requires either the realm role 'user' or 'admin'. ### Method GET ### Endpoint /users ### Parameters None ### Request Example None ### Response #### Success Response (200) - An empty array `[]` is returned. #### Response Example [] ## DELETE /users/:id ### Description Deletes a user by ID. Requires both the realm role 'admin' and 'sysadmin'. ### Method DELETE ### Endpoint /users/:id #### Parameters ##### Path Parameters - **id** (string) - Required - The ID of the user to delete. ### Request Example None ### Response #### Success Response (200) - An empty object `{}` is returned. #### Response Example {} ``` -------------------------------- ### @AccessToken() Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Parameter decorator that injects the raw JWT access token string extracted from the `Authorization: Bearer` header or configured cookie. ```APIDOC ## @AccessToken() ### Description Parameter decorator that injects the raw JWT access token string extracted from the `Authorization: Bearer` header or configured cookie. ### Usage ```typescript import { Controller, Get } from '@nestjs/common'; import { AccessToken } from 'nest-keycloak-connect'; @Controller('token-info') export class TokenController { @Get() getToken(@AccessToken() token: string) { // token is the raw JWT string: "eyJhbGci..." return { token }; } } ``` ``` -------------------------------- ### Resource Decorator for Keycloak Resource Naming Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Use the @Resource decorator to mark controllers or route handlers with a Keycloak resource name. This is used by ResourceGuard to match Keycloak Authorization Services resources. ```typescript import { Controller, Get } from '@nestjs/common'; import { Resource, Scopes } from 'nest-keycloak-connect'; @Controller('invoices') @Resource('Invoice') // resource "Invoice" must exist in Keycloak export class InvoiceController { @Get() @Scopes('View') findAll() { return []; } } ``` -------------------------------- ### @ConditionalScopes Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Dynamically resolves required scopes at request time based on the request object and Keycloak token. ```APIDOC ## GET /products ### Description Retrieves products. Dynamically resolves scopes based on user roles (admin, basic) or defaults to an empty array. The resolved scopes are returned in the response. ### Method GET ### Endpoint /products ### Parameters #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - Returns an object containing the resolved scopes for the request. #### Response Example ```json { "scopes": ["View.All"] } ``` ``` -------------------------------- ### Inject Raw Access Token with @AccessToken() Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Use the @AccessToken() parameter decorator to inject the raw JWT access token string. The token is extracted from the 'Authorization: Bearer' header or a configured cookie. ```typescript import { Controller, Get } from '@nestjs/common'; import { AccessToken } from 'nest-keycloak-connect'; @Controller('token-info') export class TokenController { @Get() getToken(@AccessToken() token: string) { // token is the raw JWT string: "eyJhbGci..." return { token }; } } ``` -------------------------------- ### Scoped Guard Registration in Controller Source: https://github.com/ferrerojosh/nest-keycloak-connect/blob/master/README.md Apply guards like AuthGuard and ResourceGuard directly to a controller using the @UseGuards decorator for scoped protection. ```typescript @Controller('cats') @UseGuards(AuthGuard, ResourceGuard) export class CatsController {} ``` -------------------------------- ### ResourceGuard for Controller-Level Authorization Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Use ResourceGuard with AuthGuard to enforce Keycloak Authorization Services policies on controllers and methods annotated with @Resource and @Scopes. Falls back to PolicyEnforcementMode when no resource or scope annotations are present. ```typescript import { Controller, Get, Post, Delete, Body, Param, UseGuards } from '@nestjs/common'; import { AuthGuard, Resource, ResourceGuard, Scopes } from 'nest-keycloak-connect'; @Controller('orders') @UseGuards(AuthGuard, ResourceGuard) @Resource('orders') // matches Keycloak resource named "orders" export class OrderController { @Get() @Scopes('View') // requires orders:View permission in Keycloak findAll() { return []; } @Post() @Scopes('Create') // requires orders:Create permission create(@Body() dto: any) { return dto; } @Delete(':id') @Scopes('Delete') // requires orders:Delete permission remove(@Param('id') id: string) { return { deleted: id }; } } ``` -------------------------------- ### Customize Enforcer Options with @EnforcerOptions() Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Pass custom Keycloak enforcer options to ResourceGuard for specific routes using the @EnforcerOptions() decorator. This is useful for customizing claims sent to the Keycloak authorization endpoint. ```typescript import { Get } from '@nestjs/common'; import { EnforcerOptions, Resource, Scopes } from 'nest-keycloak-connect'; @Resource('Document') export class DocumentController { @Get(':id') @Scopes('View') @EnforcerOptions({ claims: (request: any) => ({ 'document.owner': [request.params.id], 'user.department': [request.headers['x-department']], }), }) findOne() { return {}; } } ``` -------------------------------- ### Applying AuthGuard to a Controller Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Use the AuthGuard decorator to protect all routes within a specific controller. This guard validates the JWT token in the Authorization header or cookies, returning 401 if invalid or missing. ```typescript import { Controller, Get, UseGuards } from '@nestjs/common'; import { AuthGuard } from 'nest-keycloak-connect'; @Controller('profile') @UseGuards(AuthGuard) export class ProfileController { @Get() getProfile() { return { message: 'Authenticated users only' }; } } ``` -------------------------------- ### @Public() Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Marks a controller or route handler as publicly accessible, bypassing authentication and authorization checks. JWT validation is still attempted but failures are non-blocking. ```APIDOC ## @Public() ### Description Marks a controller or route handler as publicly accessible, bypassing authentication and authorization checks entirely. When a JWT is provided on a public route, validation is still attempted but failures are non-blocking. ### Usage ```typescript import { Controller, Get } from '@nestjs/common'; import { Public } from 'nest-keycloak-connect'; @Controller('health') export class HealthController { @Get() @Public() // no JWT required check() { return { status: 'ok' }; } } ``` ``` -------------------------------- ### Roles Decorator for Realm and Application Role Checks Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Specify required realm or application roles using the @Roles decorator. Roles prefixed with 'realm:' target realm roles, while unprefixed roles target client/application roles. Use @RoleMatchingMode to specify ALL or ANY role matching. ```typescript import { Get, Delete } from '@nestjs/common'; import { Roles, RoleMatchingMode, RoleMatch } from 'nest-keycloak-connect'; export class UserController { @Get() @Roles('realm:user', 'realm:admin') // any of these roles grants access list() { return []; } @Delete(':id') @Roles('realm:admin', 'realm:sysadmin') @RoleMatchingMode(RoleMatch.ALL) // must have both roles remove() { return {}; } } ``` -------------------------------- ### @KeycloakUser() Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Parameter decorator that injects the decoded Keycloak user object (JWT payload) from the current request. Must be used per-method unless the controller is request-scoped. ```APIDOC ## @KeycloakUser() ### Description Parameter decorator that injects the decoded Keycloak user object (JWT payload) from the current request. Must be used per-method unless the controller is request-scoped. ### Usage ```typescript import { Controller, Get } from '@nestjs/common'; import { KeycloakUser } from 'nest-keycloak-connect'; @Controller('me') export class MeController { @Get() getMe(@KeycloakUser() user: any) { // user contains: sub, preferred_username, email, realm_access, etc. return { id: user.sub, username: user.preferred_username, email: user.email, roles: user.realm_access?.roles ?? [], }; } } ``` ``` -------------------------------- ### RoleGuard for Realm/Application Role Checks Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt RoleGuard checks for required Keycloak roles using @Roles. It can be used with AuthGuard for role-only authorization or in conjunction with ResourceGuard under PERMISSIVE mode. ```typescript import { Controller, Get, Param, UseGuards } from '@nestjs/common'; import { AuthGuard, RoleGuard, Roles, RoleMatchingMode, RoleMatch } from 'nest-keycloak-connect'; @Controller('admin') @UseGuards(AuthGuard, RoleGuard) export class AdminController { @Get('users') @Roles('realm:admin') // realm role "admin" listUsers() { return []; } @Get('reports') @Roles('realm:admin', 'realm:auditor') @RoleMatchingMode(RoleMatch.ALL) // user must have BOTH roles getReports() { return []; } @Get('dashboard') @Roles('app:viewer', 'app:editor') @RoleMatchingMode(RoleMatch.ANY) // user needs ANY of the roles (default) getDashboard() { return []; } } ``` -------------------------------- ### AuthGuard Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Validates the bearer JWT token in the Authorization header or a cookie. Returns HTTP 401 when the token is missing or fails validation. ```APIDOC ## AuthGuard ### Description Validates the bearer JWT token in the `Authorization` header (or a cookie). Returns HTTP 401 when the token is missing on a protected route or fails validation. Must be registered before `ResourceGuard` and `RoleGuard`. ### Method `AuthGuard` ### Usage Can be applied globally via `APP_GUARD` or scoped to individual controllers or route handlers using the `@UseGuards()` decorator. ### Request Example ```typescript // Scoped on a single controller (alternative to global APP_GUARD) import { Controller, Get, UseGuards } from '@nestjs/common'; import { AuthGuard } from 'nest-keycloak-connect'; @Controller('profile') @UseGuards(AuthGuard) export class ProfileController { @Get() getProfile() { return { message: 'Authenticated users only' }; } } ``` ``` -------------------------------- ### Mark Controller/Route as Public with @Public() Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Use the @Public() decorator to bypass authentication and authorization for specific controllers or route handlers. JWT validation is still attempted but failures are non-blocking. ```typescript import { Controller, Get } from '@nestjs/common'; import { Public } from 'nest-keycloak-connect'; @Controller('health') export class HealthController { @Get() @Public() // no JWT required check() { return { status: 'ok' }; } } ``` -------------------------------- ### Inject Keycloak User with @KeycloakUser() Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt The @KeycloakUser() parameter decorator injects the decoded Keycloak user object (JWT payload) into a method. Ensure it's used per-method if the controller is not request-scoped. ```typescript import { Controller, Get } from '@nestjs/common'; import { KeycloakUser } from 'nest-keycloak-connect'; @Controller('me') export class MeController { @Get() getMe(@KeycloakUser() user: any) { // user contains: sub, preferred_username, email, realm_access, etc. return { id: user.sub, username: user.preferred_username, email: user.email, roles: user.realm_access?.roles ?? [], }; } } ``` -------------------------------- ### @Scopes Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Declares the authorization scopes required for a route, evaluated by ResourceGuard. ```APIDOC ## GET /articles ### Description Lists articles. Requires the 'Read' scope for the 'Article' resource. ### Method GET ### Endpoint /articles ### Response #### Success Response (200) - An empty array `[]` is returned. ## POST /articles ### Description Creates an article. Requires the 'Create' scope for the 'Article' resource. ### Method POST ### Endpoint /articles ### Response #### Success Response (200) - An empty object `{}` is returned. ## PUT /articles ### Description Updates an article. Requires the 'Update' scope for the 'Article' resource. ### Method PUT ### Endpoint /articles ### Response #### Success Response (200) - An empty object `{}` is returned. ## DELETE /articles ### Description Deletes an article. Requires the 'Delete' scope for the 'Article' resource. ### Method DELETE ### Endpoint /articles ### Response #### Success Response (200) - An empty object `{}` is returned. ``` -------------------------------- ### ConditionalScopes Decorator for Dynamic Scope Resolution Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Dynamically resolve required scopes at request time using @ConditionalScopes. This decorator takes a function that receives the request and token, allowing for logic-based scope determination. Results are merged with static @Scopes. ```typescript import { Get } from '@nestjs/common'; import { ConditionalScopes, Resource, ResolvedScopes } from 'nest-keycloak-connect'; import * as KeycloakConnect from 'keycloak-connect'; @Resource('Product') export class ProductController { @Get() @ConditionalScopes((request: any, token: KeycloakConnect.Token) => { if (token.hasRealmRole('admin')) return ['View.All']; if (token.hasRealmRole('basic')) return ['View']; return []; }) findAll(@ResolvedScopes() scopes: string[]) { // scopes contains the dynamically resolved scopes for this request return { scopes }; } } ``` -------------------------------- ### @ResolvedScopes() Decorator Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Parameter decorator that injects the list of scopes resolved for the current request after `@ConditionalScopes` evaluation. ```APIDOC ## @ResolvedScopes() ### Description Parameter decorator that injects the list of scopes resolved for the current request after `@ConditionalScopes` evaluation. ### Usage ```typescript import { Get } from '@nestjs/common'; import { ConditionalScopes, ResolvedScopes, Resource } from 'nest-keycloak-connect'; @Resource('Report') export class ReportController { @Get() @ConditionalScopes((req, token) => token.hasRealmRole('admin') ? ['Export'] : []) list(@ResolvedScopes() scopes: string[]) { const canExport = scopes.includes('Export'); return { canExport, data: [] }; } } ``` ``` -------------------------------- ### Scopes Decorator for Route Authorization Source: https://context7.com/ferrerojosh/nest-keycloak-connect/llms.txt Declare required authorization scopes for a route using the @Scopes decorator. This is evaluated by ResourceGuard in conjunction with the @Resource decorator on the controller. ```typescript import { Get, Post, Put, Delete } from '@nestjs/common'; import { Resource, Scopes } from 'nest-keycloak-connect'; @Resource('Article') export class ArticleController { @Get() @Scopes('Read') list() { return []; } @Post() @Scopes('Create') create() { return {}; } @Put() @Scopes('Update') update() { return {}; } @Delete() @Scopes('Delete') remove() { return {}; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.