oidc-provider module for Nest framework (node.js)
npm install nest-oidc-provider




oidc-provider module for Nest framework (node.js)
``bash`
$ npm i --save nest-oidc-provider oidc-provider
OR
`bash`
$ yarn add nest-oidc-provider oidc-provider
OR
`bash`
$ pnpm add nest-oidc-provider oidc-provider
> ⚠️ Version 8 of oidc-provider is now ESM-only-,oidc%2Dprovider%20is%20now%20an%20ESM%2Donly%20module,-(3c5ebe1)>), which is not yet supported by NestJS natively (nest#7021, nest#8736). This library enables the use of the ESM-only version of oidc-provider for Node.js <= 20.17.x via dynamic imports. To avoid errors like [ERR_REQUIRE_ESM], all interfaces should be imported from this package, and the module should be accessed through dependency injection. Use @InjectOidcModule() to inject the oidc-provider module and @InjectOidcProvider() for the running instance. You must not import anything directly from oidc-provider, unless you're using Node.js >= 20.17.x with the experimental --experimental-require-module flag (#54447)!
You need to install the oidc-provider @types package if you want to use the re-exported types from this library.
`bash`
npm install @types/oidc-provider --save-dev
`ts`
@Module({
imports: [
OidcModule.forRoot({
issuer: 'http://localhost:3000',
path: '/oidc',
oidc: ... // oidc-provider configuration
})
],
})
export class AppModule {}
You can pass a factory function to customize the provider instantiation.
`tsmodule
@Module({
imports: [
OidcModule.forRoot({
issuer: 'http://localhost:3000',
path: '/oidc',
factory: ({ issuer, config, module }) => {
// is the import from oidc-provider`
const provider = new module.Provider(issuer, config);
provider.on('server_error', (ctx, err) => {...})
return provider;
},
oidc: ... // oidc-provider configuration
})
],
})
export class AppModule {}
You can set the proxy option to true to trust TLS offloading proxies.\oidc-provider
For more info visit the documentation: Trusting TLS offloading proxies
`ts`
@Module({
imports: [
OidcModule.forRoot({
issuer: 'http://localhost:3000',
path: '/oidc',
proxy: true, // <- trust TLS offloading proxies
oidc: {...}
})
],
})
export class AppModule {}
You can set the host option to require the HTTP host of incoming requests to match some specific value before they are processed by the oidc-provider callback.
For more info visit the NestJS documentation: Sub-domain routing.
`ts`
@Module({
imports: [
OidcModule.forRoot({
issuer: 'https://oidc.example.com',
path: '/oidc',
host: 'oidc.example.com', // <- Use a specific host/subdomain
oidc: {...}
})
],
})
export class AppModule {}
#### useFactory
`ts`
@Module({
imports: [
OidcModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
issuer: configService.get
path: configService.get
oidc: ... // oidc-provider configuration
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}
#### useClass
`ts`
@Module({
imports: [
OidcModule.forRootAsync({
useClass: OidcConfigService,
}),
],
})
export class AppModule {}
Note that in this example, the OidcConfigService has to implement the OidcModuleOptionsFactory interface, as shown below.
`ts
import type { OidcModuleOptionsFactory } from 'nest-oidc-provider';
@Injectable()
export class OidcConfigService implements OidcModuleOptionsFactory {
constructor(private readonly @InjectConnection() conn: Connection) {}
createModuleOptions(): OidcModuleOptions {
return {
issuer: 'http://localhost:3001',
path: '/oidc',
oidc: ..., // oidc-provider configuration
};
}
createAdapterFactory?(): AdapterFactory {
return (modelName: string) => new MyAdapter(modelName, this.conn);
}
}
`
You can omit the Adapter option of oidc-provider configuration if you implement the createAdapterFactory method.
#### useExisting
`ts`
@Module({
imports: [
OidcModule.forRootAsync({
imports: [OidcConfigModule],
useExisting: OidcConfigService,
}),
],
})
export class AppModule {}
To be able to access the exports of the oidc-provider module or the running instance, you need to use decorators or injection tokens:
`ts
import {
InjectOidcModule,
InjectOidcProvider,
type Provider,
type ProviderModule,
} from 'nest-oidc-provider';
@Controller('/some-controller')
export class SomeController {
constructor(
/* Returns exports from the oidc-provider module /
@InjectOidcModule() oidc: ProviderModule,
/* Returns the running oidc-provider instance /
@InjectOidcProvider() provider: Provider,
) {}
}
`
OR
`ts
import {
OIDC_PROVIDER,
OIDC_PROVIDER_MODULE,
type Provider,
type ProviderModule,
} from 'nest-oidc-provider';
async function bootstrap() {
const app = await NestFactory.create
const { Provider, errors, interactionPolicy } =
app.get
const provider = app.get
await app.listen(3000);
}
`
Returns an instance of InteractionHelper class.
`ts
import { OidcInteraction, type InteractionHelper } from 'nest-oidc-provider';
@Get(':uid')
@Render('login')
async login(
@OidcInteraction() interaction: InteractionHelper
) {
const { prompt, params, uid } = await interaction.details();
const client = await this.provider.Client.find(params.client_id as string);
return { prompt, client, params, uid, ...};
}
`
The InteractionHelper class is just a helper that omits the req and res parameters from the existing interaction methods in oidc-provider.
`ts
interface InteractionHelper {
details(): Promise
finished(
result: InteractionResults,
options?: { mergeWithLastSubmission?: boolean },
): Promise
result(
result: InteractionResults,
options?: { mergeWithLastSubmission?: boolean },
): Promise
}
`
Returns an instance of KoaContextWithOIDC.
`ts
import { OidcContext, type KoaContextWithOIDC } from 'nest-oidc-provider';
@Get()
async index(@OidcContext() ctx: KoaContextWithOIDC) {
const { oidc: { provider } } = ctx;
const session = await provider.Session.get(ctx);
//...
}
`
Returns the user Session from the current context, equivalent to retrieving the session from KoaContextWithOIDC.
`ts
import { OidcSession, type Session } from 'nest-oidc-provider';
@Get()
async index(@OidcSession() session: Session) {
//...
}
``
A complete example can be found in the example directory.
You are welcome to contribute to this project, just open a PR.
See CHANGELOG for more information.
This project is MIT licensed.