Skip to content

Commit

Permalink
feat(api): jwt auth guard
Browse files Browse the repository at this point in the history
  • Loading branch information
Hagith committed Feb 9, 2020
1 parent e1b665d commit f03a69c
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 15 deletions.
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@types/express": "^4.17.1",
"@types/jest": "^24.0.18",
"@types/node": "^12.7.5",
"@types/passport-jwt": "^3.0.3",
"@types/passport-local": "^1.0.33",
"@types/supertest": "^2.0.8",
"jest": "^24.9.0",
Expand Down
17 changes: 12 additions & 5 deletions apps/api/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { Controller, Post, Request, UseGuards } from '@nestjs/common';
import { AuthTokenDto, UserDto } from '@app/dto';
import { Controller, Get, Post, Request, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { AuthService } from './auth.service';

@Controller('auth')
@Controller()
export class AuthController {
constructor(private readonly authService: AuthService) {}

@UseGuards(AuthGuard('local'))
@Post()
async login(@Request() req) {
return this.authService.login(req.user);
@Post('auth')
async authenticate(@Request() req): Promise<AuthTokenDto> {
return this.authService.issueToken(req.user);
}

@UseGuards(AuthGuard())
@Get('me')
async currentUser(@Request() req): Promise<UserDto> {
return req.user;
}
}
7 changes: 4 additions & 3 deletions apps/api/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { UsersModule } from '../users/users.module';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { jwtConstants } from './constants';
import { AuthJwtStrategy } from './jwt.strategy';
import { AuthLocalStrategy } from './local.strategy';
import { AuthController } from './auth.controller';

@Module({
imports: [
PassportModule,
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
UsersModule,
],
providers: [AuthService, AuthLocalStrategy],
providers: [AuthService, AuthLocalStrategy, AuthJwtStrategy],
controllers: [AuthController],
})
export class AuthModule {}
7 changes: 4 additions & 3 deletions apps/api/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthTokenDto, JwtClaimsDto } from '@app/dto';
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User, UsersService } from '../users/users.service';
Expand All @@ -6,7 +7,7 @@ import { User, UsersService } from '../users/users.service';
export class AuthService {
constructor(private readonly users: UsersService, private readonly jwtService: JwtService) {}

async validateUser(login: string, password: string): Promise<User> {
async validate(login: string, password: string): Promise<User> {
const user = await this.users.findOne(login);
if (user && password === user.password) {
return user;
Expand All @@ -15,8 +16,8 @@ export class AuthService {
return null;
}

async login(user: User) {
const payload = { login: user.login, sub: user.id };
async issueToken(user: User): Promise<AuthTokenDto> {
const payload: JwtClaimsDto = { login: user.login, sub: user.id };
return {
access: this.jwtService.sign(payload),
};
Expand Down
20 changes: 20 additions & 0 deletions apps/api/src/auth/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { JwtClaimsDto } from '@app/dto';
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy, StrategyOptions } from 'passport-jwt';
import { jwtConstants } from './constants';

@Injectable()
export class AuthJwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: jwtConstants.secret,
} as StrategyOptions);
}

async validate(payload: JwtClaimsDto) {
return { id: payload.sub, login: payload.login };
}
}
6 changes: 3 additions & 3 deletions apps/api/src/auth/local.strategy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { IStrategyOptions, Strategy } from 'passport-local';
import { User } from '../users/users.service';
import { AuthService } from './auth.service';

Expand All @@ -9,11 +9,11 @@ export class AuthLocalStrategy extends PassportStrategy(Strategy) {
constructor(private readonly authService: AuthService) {
super({
usernameField: 'login',
});
} as IStrategyOptions);
}

async validate(login: string, password: string): Promise<User> {
const user = await this.authService.validateUser(login, password);
const user = await this.authService.validate(login, password);
if (!user) {
throw new UnauthorizedException();
}
Expand Down
4 changes: 4 additions & 0 deletions libs/dto/auth/jwt-claims.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface JwtClaimsDto {
sub: number;
login: string;
}
1 change: 0 additions & 1 deletion libs/dto/auth/token.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export interface AuthTokenDto {
access: string;
refresh: string;
}
2 changes: 2 additions & 0 deletions libs/dto/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './auth/request.dto';
export * from './auth/token.dto';
export * from './auth/jwt-claims.dto';
export * from './user/user.dto';
4 changes: 4 additions & 0 deletions libs/dto/user/user.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface UserDto {
id: number;
login: string;
}
16 changes: 16 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2149,6 +2149,13 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=

"@types/jsonwebtoken@*":
version "8.3.7"
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.3.7.tgz#ab79ad55b9435834d24cca3112f42c08eedb1a54"
integrity sha512-B5SSifLkjB0ns7VXpOOtOUlynE78/hKcY8G8pOAhkLJZinwofIBYqz555nRj2W9iDWZqFhK5R+7NZDaRmKWAoQ==
dependencies:
"@types/node" "*"

"@types/jsonwebtoken@7.2.8":
version "7.2.8"
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz#8d199dab4ddb5bba3234f8311b804d2027af2b3a"
Expand Down Expand Up @@ -2186,6 +2193,15 @@
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==

"@types/passport-jwt@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/passport-jwt/-/passport-jwt-3.0.3.tgz#47b6c43af668852d7c83e56a23ed9f4515dd1814"
integrity sha512-RlOCXiTitE8kazj9jZc6/BfGCSqnv2w/eYPDm3+3iNsquHn7ratu7oIUskZx9ZtnwMdpvdpy+Z/QYClocH5NvQ==
dependencies:
"@types/express" "*"
"@types/jsonwebtoken" "*"
"@types/passport-strategy" "*"

"@types/passport-local@^1.0.33":
version "1.0.33"
resolved "https://registry.yarnpkg.com/@types/passport-local/-/passport-local-1.0.33.tgz#d245b60c5b801cb3aeca1ffab557d5fe1534260d"
Expand Down

0 comments on commit f03a69c

Please sign in to comment.