@5stones/nest-oidc

中文文档
2.2.1发布于 2026/06/10MITTypeScriptCommonJS近 30 天下载 1.6万

An OIDC authentication module for NestJS APIs

原始使用文档
文档目录9 节
  1. Install
  2. Basic Setup & Usage
  3. Guards
  4. Current User
  5. Roles
  6. Role Evaluators
  7. JWT Mapper
  8. Advanced
  9. Release

NestJS OIDC

A configurable OIDC library for NestJS and GraphQL or REST.

Install

Install nest-oidc:

npm i @5stones/nest-oidc

Install it's peer dependencies:

npm i @nestjs/jwt @nestjs/passport passport passport-jwt

:warning: Note: If you're using this package for GraphQL you'll need the corresponding GQL libraries installed. Please follow the NestJS documentation first.

Basic Setup & Usage

You'll need to import and configure the AuthModule in your application. This package contains a JWT authentication strategy which will validate a JWT against the issuer's public key. You must pass configure a value for the oidcAuthority.

import { Module } from '@nestjs/common';
import { AuthModule } from '@5stones/nest-oidc';

@Module({
  imports: [
    ...
    AuthModule.forRoot({
      oidcAuthority: 'http://iam.app.com/auth/realms/app',
    }),
  ],
})
export class AppModule {}

This will add the JWT validation strategy, and will verify any incoming JWT's against the OIDC authorities public keys.

Finally, you should decorate your endpoints with the provided guards.

Guards

This package exports two basic guards:

  • JwtAuthGuard - for use in REST contexts.
  • JwtAuthGuardGraphQL - for use in GQL contexts.

REST Guard

Applying the guard will require a valid JWT to be passed in order to access any of the controller endpoints:

import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles, JwtAuthGuard } from '@5stones/nest-oidc';

@UseGuards(JwtAuthGuard)
@Controller('cats')
export class CatsController {
  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}

You can also use it on specific endpoints:

import { Controller, Get, Post, UseGuards } from '@nestjs/common';
import { Roles, JwtAuthGuard } from '@5stones/nest-oidc';

@Controller('cats')
export class CatsController {
  @UseGuards(JwtAuthGuard)
  @Post()
  create(): string {
    return 'This action adds a new cat';
  }

  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}

GraphQL Guard

Applying the guard will require a valid JWT to be passed in order to access any of the controller endpoints:

import { UseGuards } from '@nestjs/common';
import { Resolver } from '@nestjs/graphql';
import { JwtAuthGuardGraphQL } from '@5stones/nest-oidc';

@UseGuards(JwtAuthGuardGraphQL)
@Resolver(() => Cat)
export class CatResolver {
  ...
}

You can also use it on specific endpoints:

import { UseGuards } from '@nestjs/common';
import { Resolver, Query, Mutation } from '@nestjs/graphql';
import { JwtAuthGuardGraphQL } from '@5stones/nest-oidc';

@Resolver(() => Cat)
export class CatResolver {

  @Query(() => [Cat], { name: 'allCats' })
  async findAll() {
    ...
  }

  @UseGuards(JwtAuthGuardGraphQL)
  @Mutation(() => Cat, { name: 'createCat' })
  async create() {
    ...
  }
}

Current User

This package exports two basic user decorators:

  • CurrentUser - for use in REST contexts.
  • CurrentUserGraphQL - for use in GQL contexts.

REST User

import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles, JwtAuthGuard, CurrentUser } from '@5stones/nest-oidc';

@UseGuards(JwtAuthGuard)
@Controller('cats')
export class CatsController {
  @Get()
  findAll(@CurrentUser() user: any): string {
    return 'This action returns all cats';
  }
}

GraphQL User

import { UseGuards } from '@nestjs/common';
import { Resolver, Query } from '@nestjs/graphql';
import { JwtAuthGuardGraphQL, CurrentUserGraphQL } from '@5stones/nest-oidc';

@UseGuards(JwtAuthGuardGraphQL)
@Resolver(() => Cat)
export class CatResolver {

  @Query(() => [Cat], { name: 'allCats' })
  async findAll(@CurrentUserGraphQL() user: any) {
    ...
  }
}

Roles

If you want to permission different endpoints based on properties of the JWT you can do so using the Roles decorator in conjunction with the Auth Guards (both REST & GQL). The Roles decorator will accept a list of strings and will check if the user object accessing that endpoint has any of those strings in the user.roles property. It expects the user.roles property to be a flat array of strings.

Example

import { UseGuards } from '@nestjs/common';
import { Resolver, Query, Mutation, Args, ID } from '@nestjs/graphql';
import { JwtAuthGuardGraphQL, Roles } from '@5stones/nest-oidc';

@UseGuards(JwtAuthGuardGraphQL)
@Resolver(() => Cat)
export class CatResolver {

  @Query(() => [Cat], { name: 'allCats' })
  async findAll(): Promise<Cat[]> {
    ...
  }

  @Roles()
  @Query(() => Cat, { name: 'Cat' })
  async findOne(@Args('id', { type: () => ID }) id: number): Promise<Cat> {
    ...
  }

  @Roles('ADMIN', 'SUPER_ADMIN')
  @Mutation(() => Cat, { name: 'createCat' })
  async create(): Promise<Cat> {
    ...
  }
}

In this scenario, the mutation can only be executed by an ADMIN or SUPER_ADMIN but the query can be executed by any user with a valid JWT.

:warning: Note: if you do not pass any roles parameters to the Roles decorator (i.e. @Roles()) it is the same as not adding the decorator at all. That is to say, any scenario above the findAll and the findOne queries behave identically.

Role Evaluators

If your JWT doesn't natively have a .roles property of strings on it, you can use evaluators to map properties of the JWT to a role. You can do so by configuring roleEvaluators. roleEvaluators are an array of RoleEvaluator objects which consist of an expression, and the access role that that particular expression grants upon evaluating to true.

An expression can be any valid jexl expression.

Example

Suppose you have a JWT with the following structure:

{
  roles: [
     { name: "SUPER_USER", id: 1 },
     ...
     { name: "PREMIUM", id: 2 },
  ],
}

You could then configure an evaluator like the following, which would map a user that has a role of with the name of SUPER_USER to the ADMIN role in your application.

import { Module } from '@nestjs/common';
import { AuthModule } from '@5stones/nest-oidc';

@Module({
  imports: [
    ...
    AuthModule.forRoot({
      oidcAuthority: 'http://iam.app.com/auth/realms/app',
      roleEvaluators: [
        {
          expression: 'jwt.roles[.name == "SUPER_USER"]|length > 0',
          role: 'ADMIN',
        },
      ],
    }),
  ],
})
export class AppModule {}

The user object within your application will now have the following:

{
  ...
  roles: [
    "ADMIN",
  ],
}

Then you would simply decorate your endpoint with the @Roles('ADMIN') annotation in order to lock it down to users of that role.

JWT Mapper

By default, the JWT payload is passed as the user into the application. However, if you need to map the JWT payload to different structure you can pass the jwtMapper option:

import { Module } from '@nestjs/common';
import { AuthModule } from '@5stones/nest-oidc';

@Module({
  imports: [
    ...
    AuthModule.forRoot({
      oidcAuthority: 'http://iam.app.com/auth/realms/app',
      jwtMapper: async (payload: any) => ({
        id: payload.sub,
        email: payload.email,
        ...
      }),
    }),
  ],
})
export class AppModule {}

Advanced

Authenticating GraphQL Subscriptions

The websocket spec doesn't support headers, so if you want to authenticate a GraphQL Subscription via the standard Guard & Role decorators you can do so, but you'll need to modify your GraphQLModule configuration. The below example will walk you through how to do it with the graphql-ws library.

The first step is to make sure that you're passing the Auth token as a parameter through your websocket request. Read more in the graphql-ws docs

Next you'll need to modify the GraphQLModule's onConnect and context functions to map the token and the request. You can read the NestJS documentation on generally how to do this, but that documentation only deals with the validation of the token directly in the onConnect function. However to allow it to be done by the Guards you'll need to map the token into a header on a request object and then ensure that you're always returning a request to be processed by the JwtStrategy. See the example below:

// app.module.ts
...
import type { Context } from 'graphql-ws';

...
@Module({
  imports: [
    GraphQLModule.forRoot({
      ...
      subscriptions: {
        'graphql-ws': {
          onConnect: (context: Context<any>) => {
            const { connectionParams, extra } = context;
            const authToken = connectionParams?.Authorization;

            if (authToken) {
              // Add the auth token to the request object provided by `graphql-ws`
              // NOTE: headers are lowercased in express. Using `Authorization`
              // will result in a failure to authenticate.
              extra.request.headers.authorization = authToken;
            }
          },
        }
      },
      context: (context) => {
        if (context?.req === undefined) {
          // The jwt strategy requires a request with headers to perform jwt
          // validation. If no request exists in the context object then we're
          // dealing with a websocket connection. In that case pass along the
          // request object provided by the `graphql-ws` context for validation.
          context.req = context.extra.request;
        }

        // return the context object.
        return context;
      },
    }),
    ...
  ],
})
export class AppModule implements NestModule {
  ...
}

Once this has been configured you'll be able to apply the JwtAuthGuardGraphQL and Roles decorators as you would on any other resolver, query, or mutation.

Optional Authentication

You can use the IsAuthenticationOptional decorator on an endpoint or resolver in conjunction with an auth guard. If this is done so, then JWTs will populate user object as expected. If an invalid JWT is passed or no JWT is passed at all, then no user will be populated on the request.

Release

The standard release command for this project is:

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]

This command will:

  1. Generate/update the Changelog
  2. Bump the package version
  3. Tag & pushing the commit

e.g.

npm version 1.2.17
npm version patch // 1.2.17 -> 1.2.18

版本与发布记录

@5stones/nest-oidc 共发布 15 个版本,首次发布于 2021/06/04;过去 12 个月发布了 2 个版本。

版本发布日期距今
2.2.1latest2026/06/104 个月前
2.2.02025/11/2111 个月前
2.1.02025/04/171.6 年前
2.0.12024/11/202 年前
2.0.02024/03/082 年前
2.0.0-rc.02023/01/113 年前

关于 @5stones/nest-oidc 的常见问题

@5stones/nest-oidc 是什么?

An OIDC authentication module for NestJS APIs

如何安装 @5stones/nest-oidc?

在项目目录运行 npm install @5stones/nest-oidc,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@nestjs/axios(^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0)、@nestjs/common(^9.0.0 || ^10.0.0 || ^11.0.0)、@nestjs/core(^9.0.0 || ^10.0.0 || ^11.0.0)、@nestjs/jwt(*)、@nestjs/passport(*)、passport(*)、passport-jwt(*)、reflect-metadata(*)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@5stones/nest-oidc 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@5stones/nest-oidc 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@5stones/nest-oidc 可以商用吗?

@5stones/nest-oidc 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@5stones/nest-oidc 的下载量有多少?

根据 npm 官方下载统计,@5stones/nest-oidc 在 2026/10/05 – 2026/11/03 这 30 天内被下载 16,330 次,日均约 544 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@5stones/nest-oidc 还在维护吗?

最新版本 2.2.1 发布于 2026/06/10(4 个月前);至今共发布 15 个版本,其中过去 12 个月发布了 2 个;首次发布于 2021/06/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。