Signup and Login CQRS Pattern with Nest JS, Passport and GraphQL
Tags: win10, nestjs, graphql, passport
Published: 2020-05-04 01:58:37

---
title: Signup and Login CQRS Pattern with Nest JS, Passport and GraphQL
published: true
description: API CQRS Architecture with Nest JS 
tags: win10, nestjs, graphql, Passport
series: [Nestjs cqrs]
cover_image: https://rohanfaiyaz.com/img/nestjs-graphql.png
---

## Table Of Contents
   * [Short introduction](#intro)
   * [Tools](#tools)
   * [Setup MySQL database](#mysql)
   * [Scaffolding project with cli](#scaffolding)
   * [Use schema first GraphQL](#graphql)
   * [Settings the application](#settings)
   * [Command, Event and Sagas](#cqrs)

### Short introduction <a name="intro"></a>
[Nest JS](https://nestjs.com) is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript and fully supports TypeScript. My decision to adopt this framework was largely influenced by the very good [documentation](https://docs.nestjs.com) :pineapple: and especially the similarity of implementation of the API with the Spring framework :gem:.

I will try to be quite concise and precise in this tutorial. It will involve implementing a registration and login process. I would not go into details in the **installation of tools or frameworks**. At the End of this tutorial i put a link to the github repository.

Have Fun! :hourglass:

### Tools <a name="tools"></a>
I used the following tools in this tutorial:
+ Windows 10 pro
+ VS Code
+ MySQL Workbench + MySQL
+ git 2.20
+ CMDER
+ Node JS 13.13
+ NPM 6.14.4
+ Nest 7.1.2

### Setup MySQL database <a name="mysql"></a>
After installing mysql and possibly mysql workbench, we will create a database with a **Users** table in it.
![Users Table](https://dev-to-uploads.s3.amazonaws.com/i/wgbhzebwy81b2n612sjk.png)

### Scaffolding project with cli <a name="scaffolding"></a>
Open the cmder, create a new project and choose npm at the prompt :
```javascript
λ nest new cqrs-auth-db
λ npm i --save @nestjs/core @nestjs/common rxjs reflect-metadata
```
This command will automatically create default folders and files. Now we will add an .env file in the root of the project. :bell:
```
λ touch .env
```
We will come back to this later.
In nestjs each application has at least [one module](https://docs.nestjs.com/modules), a root module. We will add a new "users" module to our project.
```javascript
λ nest g mo users
CREATE src/users/users.module.ts (82 bytes)
UPDATE src/app.module.ts (312 bytes)
```

### Use schema first GraphQL <a name="graphql"></a>
We need to install the apollo server to use graphql.
```javascript
λ npm install apollo-server-express
```

For implementing the GraphQL, i choose the **schema first** way. So we will first generate the following files:
+ src/users/users.resolver.ts
+ src/users/users.graphql
+ src/app.graphql

In the **app.graphql** we will define input, type, mutation and schema.
```graphql
input Signup {
    username: String!,
    email: EmailAddress!,
    password: String!,
    passwordConfirm: String!,
}

type SignupResponse {
  username: String!,
  email: String!,
}

type AuthPayload {
    Authorization: String!
    user: String!
    expiresIn: String!
}

type Mutation {
  signup(input: Signup!): SignupResponse!
  login(username: EmailAddress!, password: String!): AuthPayload!
}

schema {
  query: Query
}
``` 

### Settings the application <a name="settings"></a>

In this application we will need some libraries and settings for [passport](https://docs.nestjs.com/techniques/authentication#implementing-passport-strategies), [cqrs](https://docs.nestjs.com/recipes/cqrs#cqrs), [graphql](https://docs.nestjs.com/graphql/quick-start), [configuration](https://docs.nestjs.com/techniques/configuration#configuration) and [typeorm](https://docs.nestjs.com/recipes/sql-typeorm#sql-typeorm).

```javascript
λ npm i --save @nestjs/graphql graphql-tools graphql
λ npm i --save @nestjs/passport passport passport-local
λ npm i --save-dev @types/passport-local
λ npm i --save @nestjs/typeorm typeorm mysql
λ npm i --save @nestjs/cqrs
λ npm i --save @nestjs/config
```
Now, we will generate from the graphql schemas the classes in the necessary javascript file **graphql.schema.ts**. Add this configuration to the __import:[]__ in the **app.module.js**:
```javascript
GraphQLModule.forRootAsync({
      useFactory: () => ({
        context: ({ req }) =>  ({ req }),
        typeDefs: [],
        resolvers: [],
        typePaths: ['./**/*.graphql'],
        installSubscriptionHandlers: true,
        definitions: {
          path: join(process.cwd(), 'src/graphql.schema.ts'),
          outputAs: 'class',
        },
      }),
    }),
```

For typeorm, we will need to configure access to the mysql database. We will create a __TypeOrmConfigService__ class which will contain this configuration for the TypeOrmModule:
```javascript
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
  
  constructor(private configService: ConfigService ) {}

  createTypeOrmOptions(): TypeOrmModuleOptions {
    return {
      type: 'mysql',
      host: process.env.TYPEORM_HOST,
      port: Number(process.env.TYPEORM_PORT),
      username: process.env.TYPEORM_USERNAME,
      password: process.env.TYPEORM_PASSWORD,
      database: process.env.TYPEORM_DATABASE,
      entities: [__dirname + '/../**/*.entity{.ts,.js}'],
      synchronize: false,
      migrationsRun: true,
      migrationsTableName: "custom_migration_table",
      migrations: [__dirname + "migration/*.js"],
      "cli": {
        "migrationsDir": "migration"
      },
      autoLoadEntities: true,
      logging: ["query", "error"],
    };
  }
}
```

Then, add this configuration to the __import:[]__ in the **app.module.js**:
```javascript
TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useClass: TypeOrmConfigService,
      inject: [ConfigService],
 }),
```

Now it's time to go back to the **.env** file, did you remember? :smirk:
But before we need to add the ConfigModule to the root module **app.module.ts**.
```javascript
imports:[.., ConfigModule.forRoot({ isGlobal: true, }), ..]
```

We can add this configuration to **.env**, replace dbname and dbpass with your actual configuration:
```
TYPEORM_HOST = "localhost"
TYPEORM_USERNAME = "dbname"
TYPEORM_PASSWORD = "dbpass"
TYPEORM_DATABASE = "testdb"
TYPEORM_PORT = 3306
```
If you run **npm run start:dev** you will be able to see the graphql interface at **localhost:3000/graphql**

The routing with GraphQL is a little bit different. We need a class with a Resolver decoration:
**app.resolver.ts**
```javascript
@Resolver ('App')
export class AppResolver { 

    constructor(
        private commandBus: CommandBus,
    ) {}

    @Mutation('signup')
    public async signup(@Body('input') input: SignUp ) {
        
        try {
            return await this.commandBus.execute( 
                new CreateUserCommand(input.username, 
                   input.email, input.password));
        } catch (errors) {
            console.log("Caught promise rejection (validation failed). Errors: ", errors);
        }
    }
}
```

From here now we can send a request like: 
```javascript
mutation {
  signup(
    input: {
      username:"demo", 
      email:"email@mail.com",
      password:"!?94de807286baDbpass"}
  ) {
    email, username
  }
}
```

### Command, Event and Sagas <a name="cqrs"></a>

There are already a multitude of tutorials on DDD and CQRS. I will limit myself here to the implementation of the cqrs pattern with nestjs and graphql.

#### User Register

In the Resolver class we have the commandBus which execute a Command. If you want to know more about read the [documentation](https://docs.nestjs.com/recipes/cqrs#commands).

The following folders are created:
+ src/users/commands/handlers
+ src/users/commands/impl
+ src/users/events/handlers
+ src/users/events/impl
+ src/users/repositories
+ src/users/sagas
+ src/users/user.entity.ts

Then we create the command Interface and his implementation:

**create-user.command.ts**
```javascript
export class CreateUserCommand {
    constructor(
      public readonly username: string,
      public readonly email: string,
      public readonly password: string,
    ) {}
}
``` 

**create-user.handler.ts**
```javascript
@CommandHandler(CreateUserCommand)
export class CreateUserHandler implements ICommandHandler<CreateUserCommand> {
    constructor(
        private readonly eventBus: EventBus,
    ) { }

    async execute(command: CreateUserCommand) {

        const { username, email, password } = command;
        const userRepository = getCustomRepository(UserRepository);
 
        const user = userRepository.create();
        user.userId = await this.convertStringToBinary(uuidv4());
        user.username = username;
        user.email = email;
        user.password = password;
        
        const userDB: Users = await userRepository.save(user);
        
        
        this.sendEvent(userDB.userId, this.eventBus);
        
        return userDB;
    }

    private async sendEvent(userId: Buffer, eventBus: EventBus) {
        if(userId !== undefined) {
            console.log("send event UserCreatedEvent");
            eventBus.publish(
                new UserCreatedEvent(
                    Buffer.from(userId).toString('hex')));
        }
    }

    private async convertStringToBinary(uuid: string): Promise<Buffer> {
        const guid = Buffer.alloc(16);
        guid.write(uuid);
        return guid;
    }
}
```

If you now send a valid signup you will end up with response json:
```javascript
{
  "data": {
    "signup": {
      "email": "email@mail.com",
      "username": "demo"
    }
  }
}
```

#### User Login

For the login we have to use [Guards](https://docs.nestjs.com/guards). NestJS already provide a really good documentation about it.
In this example i will show you how Passport Guard and GraphQL can work together.

First we have to extends the passport **AuthGuard** and then manually built the *request object*.
```javascript
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {

    constructor() {
        super();
    }  

    async canActivate(context: ExecutionContext): Promise<boolean> {
        await super.canActivate(context);
        const ctx = GqlExecutionContext.create(context);
        const request  = ctx.getContext();
        request.body = ctx.getArgs();
        return true;
    }

    getRequest(context: ExecutionContext) {
        const ctx = GqlExecutionContext.create(context);
        const request  = ctx.getContext();
        request.body = ctx.getArgs();
        return request;
    }
}
```

In the root resolver we have to add the login function and use our custom decorator on it. If you want to use JWT to generate a token please read the [documentation](https://docs.nestjs.com/techniques/authentication#jwt-functionality)

**app.resolver.ts**
```javascript
...
@UseGuards(LocalAuthGuard)
    @Mutation('login')
    public async login(@CurrentUser() req ): Promise<AuthPayload> {
        
        return {
            email: req.email, 
        };
    }
...
```
To validate the username and password combo, the passport uses a pattern called strategy. Here is how our stragety looks like:

**local.strategy.ts**
```javascript
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(
    private commandBus: CommandBus,
  ) { super(); }

  async validate(email: string, password: string): Promise<any> {
    const user = await this.commandBus.execute(
      new PerformLoginCommand(email, password)
    );
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}
```

Here we also use as you see the cqrs using a command **PerformLoginCommand**. We need 2 classes a handler and the interface. 
I keep it simple, but this class could be more complicated if you deal with hashed password for example.
**perform-login.handler.ts**
```javascript
@CommandHandler(PerformLoginCommand)
export class PerformLoginHandler implements ICommandHandler<PerformLoginCommand> {

    async execute(command: PerformLoginCommand) : Promise<any> {      
        const { email, password } = command;
        const user = getRepository(Users)
            .find({email: email, password: password});
        return user;
    }
}
```

Now you can easily sent the request:
```javascript
mutation {
  login(
    username:"email@mail.com",
    password:"!?94de807286baDbpass",
  ) {
    email,
  }
}
```
and get the email as response.


NestJ brings very good tools to work with the CQRS pattern. In the github repo, you can also see how I implemented the Saga and Event model.

[Final Repo](https://github.com/3logy/nestjs-graphql-passport) :tada:
[bit.ly link](https://bit.ly/35sVWj3)