Skip to content

crowbartools/nestjs-oauth2-server-module

 
 

Repository files navigation

SwitchIt - Conseil Logo

We build your next generation software !

OAuth2 Server Module CircleCI

This module turns your NestJS Application into an OAuth2 Server. It is based on

Installation

npm install --save @switchit/nestjs-oauth2-server # or yarn install @switchit/nestjs-oauth2-server

Usage

Implement the UserValidatorInterface

The UserValidatorInterface lets you validate a user using the PasswordGrantStrategy. It is queried in your application to validate that the given username and password matches with a user in your application's DB.

IMPORTANT: When the user is not found your have to throw an InvalidUserException.

import {Injectable} from "@nestjs/common";
import {UserValidatorInterface, UserInterface, InvalidUserException} from "@switchit/nestjs-oauth2-server";

@Injectable()
export class UserValidator implements UserValidatorInterface {
    async validate(username, password): Promise<UserInterface> {
        // check if the user exists with the given username and password
        // ...
        // or
        throw InvalidUserException.withUsernameAndPassword(username, password);
    }
}

The validate method should return an instance of the UserInterface:

export interface UserInterface {
    id: string;
    username: string;
    email: string;
}

The user interface is then accessible in the payload once connected ot the AccessToken is used.

Implement the UserLoaderInterface

The UserLoaderInterface lets you load a user from the database when the AccessToken is user specific. The user is then accessible in the request context of your application.

IMPORTANT: When the user is not found your have to throw an InvalidUserException.

import {Injectable} from "@nestjs/common";
import {UserLoaderInterface, UserInterface, InvalidUserException} from "@switchit/nestjs-oauth2-server";

@Injectable()
export class UserLoader implements UserLoaderInterface {
    async load(userId: string): Promise<UserInterface> {
        // Load the user from the database
        // ...
        // or throw and 
        throw InvalidUserException.withId(userId);
    }
}

Implement the module in your application

Import the OAuth2Module into the root AppModule.

//app.module.ts
import { Module } from '@nestjs/common';
import { OAuth2Module } from '@switchit/nestjs-oauth2-server';

@Module({
    imports: [
        OAuth2Module.forRoot({
            userLoader: new UserLoader(),
            userValidator: new UserValidator(),
        }),
    ],
})
export class AppModule {}

Of course you can use an async configuration:

//app.module.ts
import { Module } from '@nestjs/common';
import { OAuth2Module } from '@switchit/nestjs-oauth2-server';

@Module({
    imports: [
        OAuth2Module.forRootAsync({
            useFactory: () => ({
                userLoader: new UserLoader(),
                userValidator: new UserValidator(),
            })
        }),
    ],
})
export class AppModule {}

The OAuth2 Controller

The modules is shipped with a specific controller that lets you expose the oauth2/token endpoint in your application and use the different implemented strategies accordingly to the request sent.

Client Credentials

Used for server-to-server communications.

curl -X POST http://localhost:3000/oauth2/token -d '{"grant_type":"client_credentials", "client_id":"6ab1cfab-0b3d-418b-8ca2-94d98663fb6f", "client_secret": "6nV9GGm1pu8OY0HDZ3Y7QsVnxtkb60wu", "scopes": ["app-1"]}'

Refresh Token

Used to refresh an existing token

curl -X POST http://localhost:3000/oauth2/token -d '{"grant_type":"refresh_token", "client_id":"6ab1cfab-0b3d-418b-8ca2-94d98663fb6f", "client_secret": "6nV9GGm1pu8OY0HDZ3Y7QsVnxtkb60wu", "refresh_token": "6nV9GGm1pu8OY0HDZ3Y7QsVnxtkb6fgqstyudhjqskdqsd"}'

Password

Used to refresh an existing token

curl -X POST http://localhost:3000/oauth2/token -d '{"grant_type":"password", "client_id":"6ab1cfab-0b3d-418b-8ca2-94d98663fb6f", "username": "j.doe@change.me", "password": "changeme", "scopes": ["app-1"]}'

Securing your routes using the AccessTokenStrategy

The module comes with a PassportJS strategy of type http-bearer. You can secure your routes using the passport AuthGuard with the access-token strategy name:

@Controller('oauth2-secured')
export class TestSecuredController {
    @Get('me')
    @UseGuards(AuthGuard('access-token'))
    async auth(): Promise<any> {
        return {message: 'hello'};
    }
}

Adding the entities to your TypeORM configuration

IMPORTANT: The module comes with entities you have to add the configuration node_modules/@switchit/**/*.entity.js to let typeorm scan your entities or add them to the entitie configuration variable in TypeORM.

Using the global validation pipes

IMPORTANT: In addition, you should enable the global validation pipe in your NestJS application. In your main.ts you should use the useGlobaPipes with the ValidationPipe and the transform options set to true:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  useContainer(app.select(AppModule), {fallbackOnErrors: true});
  app.useGlobalPipes(new ValidationPipe({
    transform: true,
  }));

  await app.listen(3000);
}
bootstrap();

About

OAuth2 Server for NestJS

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 99.0%
  • Makefile 1.0%