Skip to content

Commit

Permalink
feat(auth0): add module & integrate auth0
Browse files Browse the repository at this point in the history
  • Loading branch information
An Nguyen Q committed Mar 5, 2022
1 parent eed50f6 commit 9dce0cf
Show file tree
Hide file tree
Showing 6 changed files with 530 additions and 15 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/platform-express": "^8.0.0",
"auth0": "^2.40.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
Expand All @@ -39,6 +40,7 @@
"@nestjs/cli": "^8.0.0",
"@nestjs/schematics": "^8.0.0",
"@nestjs/testing": "^8.0.0",
"@types/auth0": "^2.34.13",
"@types/express": "^4.17.13",
"@types/jest": "27.4.1",
"@types/node": "^16.0.0",
Expand Down
3 changes: 3 additions & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const AUTH0_OPTIONS = 'AUTH0_OPTIONS';
export const AUTH0_MANAGEMENT_TOKEN = 'AUTH0_MANAGEMENT_TOKEN';
export const AUTH0_CLIENT_TOKEN = 'AUTH0_CLIENT_TOKEN';
89 changes: 87 additions & 2 deletions src/index.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,93 @@
import { Module } from '@nestjs/common';
import { DynamicModule, Module, Provider } from '@nestjs/common';
import { ManagementClient, AuthenticationClient } from 'auth0';

import {
AUTH0_CLIENT_TOKEN,
AUTH0_MANAGEMENT_TOKEN,
AUTH0_OPTIONS,
} from './constants';
import { Auth0Service } from './index.service';
import {
IAuth0AsyncOptions,
IAuth0Options,
IAuth0OptionsFactory,
} from './types';

@Module({
imports: [],
providers: [Auth0Service],
exports: [Auth0Service],
})
export class Auth0Module {}
export class Auth0Module {
static register(options: IAuth0Options): DynamicModule {
return {
module: Auth0Module,
providers: [
{
provide: AUTH0_MANAGEMENT_TOKEN,
useValue: new ManagementClient({
domain: options.issuer,
clientId: options.clientId,
clientSecret: options.clientSecret,
}),
},
{
provide: AUTH0_CLIENT_TOKEN,
useValue: new AuthenticationClient({
domain: options.issuer,
clientId: options.clientId,
clientSecret: options.clientSecret,
}),
},
],
};
}

static registerAsync(options: IAuth0AsyncOptions): DynamicModule {
return {
module: Auth0Module,
imports: options.imports || [],
providers: [
this.createAsyncOptionsProvider(options),
{
provide: AUTH0_MANAGEMENT_TOKEN,
useFactory: (options: IAuth0Options) =>
new ManagementClient({
domain: options.issuer,
clientId: options.clientId,
clientSecret: options.clientSecret,
}),
inject: [AUTH0_OPTIONS],
},
{
provide: AUTH0_CLIENT_TOKEN,
useFactory: (options: IAuth0Options) =>
new AuthenticationClient({
domain: options.issuer,
clientId: options.clientId,
clientSecret: options.clientSecret,
}),
inject: [AUTH0_OPTIONS],
},
],
};
}

private static createAsyncOptionsProvider(
options: IAuth0AsyncOptions,
): Provider {
if (options.useFactory) {
return {
provide: AUTH0_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
};
}
return {
provide: AUTH0_OPTIONS,
useFactory: async (optionsFactory: IAuth0OptionsFactory) =>
optionsFactory.createAuth0Options(),
inject: [options.useExisting || options.useClass],
};
}
}
46 changes: 43 additions & 3 deletions src/index.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,48 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { AuthenticationClient, ManagementClient } from 'auth0';
import {
AUTH0_CLIENT_TOKEN,
AUTH0_MANAGEMENT_TOKEN,
AUTH0_OPTIONS,
} from './constants';
import { IAuth0Options } from './types';

@Injectable()
export class Auth0Service {
getHello(): string {
return 'Hello World!';
constructor(
@Inject(AUTH0_OPTIONS)
private readonly auth0Options: IAuth0Options,
@Inject(AUTH0_MANAGEMENT_TOKEN)
private readonly managementClient: ManagementClient,
@Inject(AUTH0_CLIENT_TOKEN)
private readonly authClient: AuthenticationClient,
) {}

async getManagementClient() {
return this.managementClient;
}

async getAuthClient() {
return this.authClient;
}

async getAuthenticatedToken() {
return this.authClient.clientCredentialsGrant({
audience: this.auth0Options.audience,
});
}

async setAppMetadata(auth0UserId: string, metadata: Record<string, any>) {
return this.managementClient.updateAppMetadata(
{ id: auth0UserId },
metadata,
);
}

async setUserMetadata(auth0UserId: string, metadata: Record<string, any>) {
return this.managementClient.updateUserMetadata(
{ id: auth0UserId },
metadata,
);
}
}
19 changes: 19 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ModuleMetadata, Type } from '@nestjs/common';

export type IAuth0Options = {
clientId: string;
clientSecret: string;
issuer: string;
audience: string;
};

export type IAuth0OptionsFactory = {
createAuth0Options(): Promise<IAuth0Options> | IAuth0Options;
};

export interface IAuth0AsyncOptions extends Pick<ModuleMetadata, 'imports'> {
useExisting?: Type<IAuth0OptionsFactory>;
useClass?: Type<IAuth0OptionsFactory>;
useFactory?: (...args: any[]) => Promise<IAuth0Options> | IAuth0Options;
inject?: any[];
}
Loading

0 comments on commit 9dce0cf

Please sign in to comment.