Code Monkey home page Code Monkey logo

nestjs-oauth2-server-module's Introduction

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": "[email protected]", "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();

nestjs-oauth2-server-module's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nestjs-oauth2-server-module's Issues

No repository for "ClientEntity" was found. Looks like this entity is not registered in current "default" connection?

I am trying to use the module.
I don't think documentation is right btw. It specifies to import OAuth2Module. This is not available (capitalization error). Importing Oauth2Module gives the following error:

No repository for "ClientEntity" was found. Looks like this entity is not registered in current "default" connection?

If you'd like to see the code, it's here:
adamgajzlerowicz/nest-learning#1

Can I get some pointers, please?

Refresh token implementation

Hi guys,

Could someone please give me an example on how to implement the refresh token strategy? Or any other way to implement the refresh token flow.

Thank you.

jsonb data type not supported

Hi,
I try to use the package with mysql database but I have this error

DataTypeNotSupportedError: Data type "jsonb" in "AccessTokenEntity.createdFrom" is not supported by "mysql" database.

Is possible switch the field type to json in order to support more database.

Thanks

Commands Documentation

Description

Document commands that can be executed through the command bus

ToDos

  • CreateClientCommand
  • CreateAccessTokenCommand

No `authorization code` grant strategy

Hello, thanks your great work!
I have seen the code and found you have implement three types of grant.

export * from './client-credentials.strategy';
export * from './refresh-token.strategy';
export * from './password.strategy';

Have you planed to add authorization code strategy?

Error 401 with message"The client with clientId \"undefined\" was not found"

Trying to setup an oauth service with a mongodb orm setup, there's a problem in the query parameter name mapping.
You can find an example causing the problem in this zip.
oauth-service.zip
Node version: v12.16.1

Test call:

POST http://localhost:3000/oauth2/token?grant_type=password&client_id=6ab1cfab-0b3d-418b-8ca2-94d98663fb6f&client_secret=6nV9GGm1pu8OY0HDZ3Y7QsVnxtkb60wu&scopes=carma&[email protected]&password=changeme

Looking into swaggerUI the parameter seems to use the name definedas class member and not the one defined in the decoration.

Can you help me sort the problem?

Thanks,Giacomo

Development Documentation

Description

Add part of the documentation to explain how to setup the module for testing & development purposes.

Events emitted documentation

Description

Document events emitted by commands in the application

ToDos

  • ClientCreatedEvent
  • AccessTokeCreatedEvent

Getting error Error: Nest can't resolve dependencies of the QueryBus (?). Please make sure that the argument ModuleRef at index [0] is available in the CqrsModule context.

Running project i am getting following error:

ERROR [ExceptionHandler] Nest can't resolve dependencies of the QueryBus (?). Please make sure that the argument ModuleRef at index [0] is available in the CqrsModule context.

Potential solutions:

  • If ModuleRef is a provider, is it part of the current CqrsModule?
  • If ModuleRef is exported from a separate @module, is that module imported within CqrsModule?
    @module({
    imports: [ /* the Module containing ModuleRef */ ]
    })

Support Request scope to UserLoader and UserValidator object

Our application is developed with multiple tenant and multiple database. Based on request we determine which database connection should be establish. we can able to achieve this using nest js Request Scope. So the same thing how to achieve for UserLoader and UserValidator.

database : PostgreSQL
Client : Client A, Client B, Client C

Each client can have separate database but entity structure is same. I want to validate user based on client type which will come through the request header.

TenancyModule : which provides database connection based on request header.

import { Global, Module, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { getConnection } from 'typeorm';

const connectionFactory = {
provide: 'CONNECTION',
scope: Scope.REQUEST,
useFactory: (req) => {
const tenant = getConnection(req.headers.client);
return getConnection(tenant);
},
inject: [REQUEST],
};

@global()
@module({
providers: [connectionFactory],
exports: ['CONNECTION'],
})
export class TenancyModule {}

User Service class:

@Injectable({scope: Scope.REQUEST})
export class UserService {
private readonly userRepository: Repository;

constructor(@Inject('CONNECTION') connection) {
this.userRepository = connection.getRepository(User);
}

I want UserLoader to support request scope so that I can get request information based on this I can able to validate User.

Token Queries & Commands

Description

  • List AccessTokens (Search capabilities)
  • Find AccessToken
  • Revoke AccessToken & RefreshToken

Client's Queries & Commands

Description

  • List Clients (Search capabilities)
  • Find Client
  • Revoke a client
  • Refresh client credentials (Reset)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.