0.3.0 • Published 5 years ago
@nest-auth/auth v0.3.0
Nest Auth
nestjs module to handle session based authentication
Installation
$ npm install --save @nest-auth/authOr
$ yarn add @nest-auth/authInstall peer dependencies
$ npm install --save @nest-auth/cipher @nestjs/passport passport @nestjs/typeorm typeorm body-parser class-transformer class-validator cookie-parser csurf hbs passport-localOr
$ yarn add @nest-auth/cipher @nestjs/passport passport @nestjs/typeorm typeorm body-parser class-transformer class-validator cookie-parser csurf hbs passport-localOptionally install the password strength estimator
$ npm install --save zxcvbnOr
$ yarn add zxcvbnCreate the User and Social Login entities
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
import { Controller } from '@nestjs/common';
import { AuthController } from '@nest-auth/auth';
@AuthController('auth')
export class AppAuthController {}Import it in a module
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
// 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.htmlregister.html
For now, the only supported view engine is handlebars with .html extension
This configuration created thw following url:
- GET
/login: show login formlogin.htmlview. It receives as datacsrfToken: required to be set as_csrfform fieldaction: 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 theredirect_uriquery param - GET
/register: show the registration formregister.htmlview. It receives as datacsrfToken: required to be set as_csrfform fieldaction: 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 theredirect_uriquery param - POST
/logout: logs out the user and redirect to the homepage or theredirect_uriquery 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
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,
}
}
}