1.10.0 • Published 2 months ago

nest-keycloak-connect v1.10.0

Weekly downloads
989
License
MIT
Repository
github
Last release
2 months ago

Nest Keycloak Connect

GitHub npm npm peer dependency version npm peer dependency version Verify Build npm npm

Support via PayPal

An adapter for keycloak-nodejs-connect.

Features

Installation

Yarn

yarn add nest-keycloak-connect keycloak-connect

NPM

npm install nest-keycloak-connect keycloak-connect --save

Getting Started

Module registration

Registering the module:

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
});

Async registration is also available:

KeycloakConnectModule.registerAsync({
  useExisting: KeycloakConfigService,
  imports: [ConfigModule],
});

KeycloakConfigService

import { Injectable } from '@nestjs/common';
import {
  KeycloakConnectOptions,
  KeycloakConnectOptionsFactory,
  PolicyEnforcementMode,
  TokenValidation,
} from 'nest-keycloak-connect';

@Injectable()
export class KeycloakConfigService implements KeycloakConnectOptionsFactory {
  createKeycloakConnectOptions(): KeycloakConnectOptions {
    return {
      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,
      tokenValidation: TokenValidation.ONLINE,
    };
  }
}

You can also register by just providing the keycloak.json path and an optional module configuration:

KeycloakConnectModule.register(`./keycloak.json`, {
  policyEnforcement: PolicyEnforcementMode.PERMISSIVE,
  tokenValidation: TokenValidation.ONLINE,
});

Guards

Register any of the guards either globally, or scoped in your controller.

Global registration using APP_GUARD token

NOTE: These are in order, see https://docs.nestjs.com/guards#binding-guards for more information.

providers: [
  {
    provide: APP_GUARD,
    useClass: AuthGuard,
  },
  {
    provide: APP_GUARD,
    useClass: ResourceGuard,
  },
  {
    provide: APP_GUARD,
    useClass: RoleGuard,
  },
];

Scoped registration

@Controller('cats')
@UseGuards(AuthGuard, ResourceGuard)
export class CatsController {}

What does these providers do ?

AuthGuard

Adds an authentication guard, you can also have it scoped if you like (using regular @UseGuards(AuthGuard) in your controllers). By default, it will throw a 401 unauthorized when it is unable to verify the JWT token or Bearer header is missing.

ResourceGuard

Adds a resource guard, which is permissive by default (can be configured see options). Only controllers annotated with @Resource and methods with @Scopes are handled by this guard.

NOTE: This guard is not necessary if you are using role-based authorization exclusively. You can use role guard exclusively for that.

RoleGuard

Adds a role guard, can only be used in conjunction with resource guard when enforcement policy is PERMISSIVE, unless you only use role guard exclusively. Permissive by default. Used by controller methods annotated with @Roles (matching can be configured)

Configuring controllers

In your controllers, simply do:

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')
  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);
  }
}

Decorators

Here is the decorators you can use in your controllers.

DecoratorDescription
@AuthenticatedUserRetrieves the current Keycloak logged-in user. (must be per method, unless controller is request scoped.)
@EnforcerOptionsKeycloak enforcer options.
@PublicAllow any user to use the route.
@ResourceKeycloak application resource name.
@ScopesKeycloak application scope name.
@RolesKeycloak realm/application roles.

Multi tenant configuration

Setting up for multi-tenant is configured as an option in your configuration:

{
  authServerUrl: 'http://localhost:8180/auth',
  clientId: 'nest-api',
  secret: 'fallback', // will be used as fallback when resolver returns null
  multiTenant: {
    realmResolver: (request) => {
      return request.get('host').split('.')[0];
    },
    realmSecretResolver: (realm, request) => {
      const secrets = { master: 'secret', slave: 'password' };
      return secrets[realm];
    },
    realmAuthServerUrlResolver: (realm, request) => {
      const authServerUrls = { master: 'https://master.local/auth', slave: 'https://slave.local/auth' };
      return authServerUrls[realm];
    }
  }
}

Configuration options

Keycloak Options

For Keycloak options, refer to the official keycloak-connect library.

Nest Keycloak Options

OptionDescriptionRequiredDefault
cookieKeyCookie KeynoKEYCLOAK_JWT
logLevelsBuilt-in logger level (deprecated, will be removed in 2.0)nolog
useNestLoggerUse the nest logger (deprecated, will be removed in 2.0)notrue
policyEnforcementSets the policy enforcement modenoPERMISSIVE
tokenValidationSets the token validation methodnoONLINE
multiTenantSets the options for multi-tenant configurationno-
roleMergeSets the merge mode for @Role decoratornoOVERRIDE

Multi Tenant Options

OptionDescriptionRequiredDefault
resolveAlwaysOption to always resolve the realm and secret. Disabled by default.nofalse
realmResolverA function that passes a request (from respective platform i.e express or fastify) and returns a stringyes-
realmSecretResolverA function that passes the realm string, and an optional request and returns the secret stringno-
realmAuthServerUrlResolverA function that passes the realm string, and an optional request and returns the auth server url stringno-

Example app

An example application is provided in the source code with both Keycloak Realm and Postman requests for you to experiment with.

1.10.0

2 months ago

1.9.5

4 months ago

1.9.4

6 months ago

1.9.3

6 months ago

1.9.2

10 months ago

1.9.1

1 year ago

1.9.0

2 years ago

1.8.3

2 years ago

1.8.2

2 years ago

1.8.3-alpha.0

2 years ago

1.8.1

2 years ago

1.8.0

2 years ago

1.8.0-alpha.2

2 years ago

1.8.0-alpha.3

2 years ago

1.8.0-alpha.0

3 years ago

1.8.0-alpha.1

3 years ago

1.7.6

3 years ago

1.7.5

3 years ago

1.7.4

3 years ago

1.7.3

3 years ago

1.7.2

3 years ago

1.7.1

3 years ago

1.7.0

3 years ago

1.7.0-alpha01

3 years ago

1.6.1

3 years ago

1.6.0

3 years ago

1.5.3

3 years ago

1.5.2

3 years ago

1.5.1

3 years ago

1.5.0

3 years ago

1.4.3

3 years ago

1.4.2

3 years ago

1.4.1

3 years ago

1.4.0

3 years ago

1.3.1

3 years ago

1.3.0

3 years ago

1.3.0-alpha.3

4 years ago

1.3.0-alpha.2

4 years ago

1.3.0-alpha.1

4 years ago

1.2.1

4 years ago

1.2.0

4 years ago

1.1.1

4 years ago

1.1.2

4 years ago

1.1.0

4 years ago

1.0.10-alpha.3

4 years ago

1.0.10-alpha.4

4 years ago

1.0.10-alpha.1

4 years ago

1.0.10-alpha.2

4 years ago

1.0.10

4 years ago

1.0.9

4 years ago

1.0.8

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago