npm package: @nest-auth/auth
Description: nestjs module to handle session based authentication
Author: Davide Gheri
Latest version: 0.3.0


# Nest Auth

### nestjs module to handle session based authentication

## Installation

```bash
$ npm install --save @nest-auth/auth
```
Or
```bash
$ yarn add @nest-auth/auth
```

#### Install peer dependencies

```bash
$ npm install --save @nest-auth/cipher @nestjs/passport passport @nestjs/typeorm typeorm body-parser class-transformer class-validator cookie-parser csurf hbs passport-local
```
Or
```bash
$ yarn add @nest-auth/cipher @nestjs/passport passport @nestjs/typeorm typeorm body-parser class-transformer class-validator cookie-parser csurf hbs passport-local
```

#### Optionally install the password strength estimator
```bash
$ npm install --save zxcvbn
```
Or
```bash
$ yarn add zxcvbn
```

#### Create the User and Social Login entities

```typescript
import { Entity } from 'typeorm';
import { AuthUser, AuthSocialLogin } from '@nest-auth/auth';

@Entity()
export class UserEntity extends AuthUser() {
  @OneToMany(() => SocialLoginEntity, sl => sl.user, {
    eager: true,
  })
  socialLogins: SocialLoginEntity[];
}

@Entity()
export class SocialLoginEntity extends AuthSocialLogin() {
  @ManyToOne(() => UserEntity, u => u.socialLogins, {
    onDelete: 'CASCADE',
  })
  user: Promise<UserEntity>;
}
```

### Create the Auth controller

```typescript
import { Controller } from '@nestjs/common';
import { AuthController } from '@nest-auth/auth';

@AuthController('auth')
export class AppAuthController {}
```

#### Import it in a module

```typescript
import { Module } from '@nestjs/common';
import { AuthModule } from '@nest-auth/auth';

@Module({
  imports: [
    //...
    AuthModule.forRoot({
      // Required options
      userEntity: UserEntity,
      socialLoginEntity: SocialLoginEntity,
      // Optional
      connection: 'default', // Typeorm connection name
      minPasswordScore: undefined, // if passed, ensures that the password meets the passed minimun score, uses the zxcvbn package
      registerDto: RegisterDto, // Dto that should extend RegisterDto, useful to add more data to the user during registration
    }),
    
    // Or with Async configuration
    AuthModule.forRootAsync({
      import: [ConfigModule],
      inject: [ConfigService],
      useFactory: config => config.get('auth'),
    }),
    //...
  ],
  controllers: [
    // Do not forget to register the Auth controller
    AppAuthController,
  ],
})
export class AppModule {}
```

### Add auth middleware to the underlying Express adapter

```typescript
// main.ts

import { NestApplication } from '@nestjs/core';
import { addAuthMiddlewares } from '@nest-auth/auth';

const app = await NestApplication.create(AppModule, {
  //...
});

//...

addAuthMiddlewares(app, {
  sessionSecret: 'supersecret',
  clientDir: './client',
  sessionStore: store, // Compatible express session store,
  session: session, // compatible express session (`express-session`),
});

//...

await app.listen(3000);
```

### Create authentication views

Create a `views` directory inside the `clientDir` directory (ex. `client/views`)

Create the required views:
* `login.html`
* `register.html`

For now, the only supported view engine is `handlebars` with `.html` extension

----

This configuration created thw following url:

* GET `/login`: show login form `login.html` view. It receives as data
    * `csrfToken`: required to be set as `_csrf` form field
    * `action`: url to call as POST to handle authentication
* POST `/login`: handle the login request. Login the user and redirect to the homepage or the value of the `redirect_uri` query param
* GET `/register`: show the registration form `register.html` view. It receives as data
  * `csrfToken`: required to be set as `_csrf` form field
  * `action`: url to call as POST to handle authentication
* POST `/register`: handle the registration request. Register the user, logs in him and redirect to the homepage or the `redirect_uri` query param
* POST `/logout`: logs out the user and redirect to the homepage or the `redirect_uri` query param

### Protect the routes

Guard a route with the `AuthenticatedGuard` to ensure the user is authenticated.
It returns a standard 403 json error

To ensure the user is redirected to the Login page, add the Filter `ForbiddenExceptionFilter` to the same route

### Get the user

To get the user from session, use the `@CurrentUser` param decorator

#### Example

```typescript
import { Controller, Get, Render, UseFilters, UseGuards } from '@nestjs/common';
import { AuthenticatedGuard, ForbiddenExceptionFilter, CurrentUser } from '@nest-auth/auth';
import { User } from '../entities';

@Controller()
export class PrivateController {
  @UseFilters(ForbiddenExceptionFilter)
  @UseGuards(AuthenticatedGuard)
  @Render('private')
  @Get('/private')
  private(
    @CurrentUser() user: User,
  ) {
    return {
      message: 'You are authenticated',
      user,
    }
  }

  @UseGuards(AuthenticatedGuard)
  @Get('/api/private')
  apiPrivate(
    @CurrentUser() user: User,
  ) {
    return {
      message: 'You are authenticated',
      user,
    }
  }
}
```