npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@nestjs-hybrid-auth/okta

v1.0.0

Published

NestJS okta authentication using passport

Downloads

67

Readme

NestJS Okta Authentication

Implement okta authentication in your NestJS application.

Install

npm install @nestjs-hybrid-auth/okta --save

OR

yarn add @nestjs-hybrid-auth/okta

How To Use?

The package exports mainly a dynamic module and guard. The module should be imported in your app.module.ts and guards should be used on the route handlers of any controller.

Example Code For app.module.ts

Simple static configuration

Want to jump directly to the available options?

If you just want to provide the static values or have them handy, pass them as options to the forRoot static method like below. The options object is type of OktaAuthModuleOptions.

import { OktaAuthModule } from '@nestjs-hybrid-auth/okta';

@Module({
  imports: [
    OktaAuthModule.forRoot({
      clientID: process.env.CLIENT_ID,
      clientSecret: process.env.CLIENT_SECRET,
      callbackURL: process.env.CALLBACK_URL,
      audience: process.env.DOMAIN,
      scope: ['openid', 'email', 'profile'],
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

useFactory to get the ConfigService injected.

If you want to make use of nest's ConfigModule to get the auth configuration for a provider from .env config files, use forRootAsync static method. The options to this method are typeof OktaAuthModuleAsyncOptions which accepts a useFactory property. useFactory is a function which gets the instances injected whatever has been provided in inject array. You can use those instances to prepare and return the actual OktaAuthModuleOptions object. ConfigService can be one of them as per your choice.

import { OktaAuthModule } from '@nestjs-hybrid-auth/okta';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      cache: true,
      expandVariables: true,
    }),
    OktaAuthModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        clientID: configService.get('OKTA_CLIENT_ID'),
        clientSecret: configService.get('OKTA_CLIENT_SECRET'),
        callbackURL: configService.get('OKTA_CALLBACK_URL'),
        audience: configService.get('OKTA_DOMAIN'),
        scope: ['email', 'profile', 'openid'],
      }),
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Use useClass to get your auth config from a class

If the useFactory makes your app module bloated with a lot of boilerplate code, you can useClass to provide an existing config provider class. The class must implement OktaAuthModuleOptionsFactory interface and createModuleOptions method. This method should return OktaAuthModuleOptions object. Similar to useFactory, whatever you provide in inject array, it will get injected in the constructor of your class. Follow the example:

hybrid-auth.config.ts

import { ConfigService } from '@nestjs/config';
import {
  OktaAuthModuleOptions,
  OktaAuthModuleOptionsFactory,
} from '@nestjs-hybrid-auth/okta';

@Injectable()
class HybridAuthConfig implements OktaAuthModuleOptionsFactory {
  constructor(private configService: ConfigService) {}

  createModuleOptions(): OktaAuthModuleOptions {
    return {
      clientKey: this.configService.get('OKTA_CLIENT_ID'),
      clientSecret: this.configService.get('OKTA_CLIENT_SECRET'),
      callbackURL: this.configService.get('OKTA_CALLBACK_URL'),
      audience: this.configService.get('OKTA_DOMAIN'),
      scope: ['email', 'profile', 'openid'],
    };
  }
}

app.module.ts

import { OktaAuthModule } from '@nestjs-hybrid-auth/okta';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      cache: true,
      expandVariables: true,
    }),
    OktaAuthModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useClass: HybridAuthConfig,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Example Code For Controller

Once you have setup the module properly in module file, its time to configure your route handlers to make the user properly redirected to appropriate identity provider's login page. @nestjs-hybrid-auth/okta provides a guard and result interface to make it enabled.

Each route will have two variants. One is to redirect to social login page and the other is to collect the response such as access/refresh tokens and user profile etc. The result will be attached to Request object's hybridAuthResult property as shown in the example below.

app.controller.ts

import { UseOktaAuth, OktaAuthResult } from '@nestjs-hybrid-auth/okta';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @UseOktaAuth()
  @Get('auth/okta')
  loginWithOkta() {
    return 'Login with Okta';
  }

  @UseOktaAuth()
  @Get('auth/okta-login/callback')
  oktaCallback(@Request() req): Partial<OktaAuthResult> {
    const result: OktaAuthResult = req.hybridAuthResult;
    return {
      accessToken: result.accessToken,
      refreshToken: result.refreshToken,
      profile: result.profile,
    };
  }
}

Exports

@nestjs-hybrid-auth/okta exports various decorators, interfaces and methods.

UseOktaAuth

UseOktaAuth is NestJS Guard which hijacks your nest request and redirects users to the appropriate login page of your configured identity provider (okta in this case). The same guard can be used on callback route also as shown in the example above. In the callback route handler, the req: Request object will have a property hybridAuthResult which is an object of type OktaAuthResult.

@UseOktaAuth(options: OktaAuthGuardOptions)
@Get('auth/okta')
loginWithOkta() {
  return 'Login with Okta';
}

OktaAuthGuardOptions

This is a simple object to be passed into UseOktaAuth guard as shown in example above if you want to pass some extra parameters to query the okta result. It can be left empty for default result.

OktaAuthModule

This is the dynamic module which must be imported in your app's main module with forRoot or forRootAsync static methods whichever suits your need. Both will return a NestJS dynamic module.

interface OktaAuthModule {
  forRoot(options: OktaAuthModuleOptions): DynamicModule;
  forRootAsync(options: OktaAuthModuleAsyncOptions): DynamicModule;
}

OktaAuthModuleOptions

If you are configuring your module with forRoot static method, pass in the module options given below. They can be called the okta passport strategy options also.

interface OktaAuthModuleOptions {
  audience: string;
  clientID: string;
  clientSecret: string;
  callbackURL: string;
  scope: string[]; // email | profile | openid
  identityProvider?: string;
}

OktaAuthModuleAsyncOptions

If you want to configure the OktaAuthModule dynamically having the config or other services injected, pass in async options in the forRootAsync static method. Please refer to the example above for useFactory and useClass properties.

interface OktaAuthModuleAsyncOptions {
  useExisting?: Type<OktaAuthModuleOptionsFactory>;
  useClass?: Type<OktaAuthModuleOptionsFactory>;
  useFactory?: (
    ...args: any[]
  ) => Promise<OktaAuthModuleOptions> | OktaAuthModuleOptions;
  inject?: any[];
}

OktaAuthModuleOptionsFactory

interface OktaAuthModuleOptionsFactory {
  createModuleOptions(): Promise<OktaAuthModuleOptions> | OktaAuthModuleOptions;
}

Have Issues?

If you still have trouble setting up the workflow properly, please file an issue at Issues page.

Maintainers

Manish Jangir