This commit is contained in:
batche
2022-11-07 17:12:06 +01:00
parent 7fd8147140
commit 24b68dc767
328 changed files with 52116 additions and 724 deletions

View File

@@ -1,13 +1,17 @@
import { Controller, Get, Res, UseGuards, Req } from '@nestjs/common';
import { Controller, Get, Res, UseGuards, Req, Post, UnauthorizedException, Body } from '@nestjs/common';
import { AuthenticateGuard, FortyTwoAuthGuard } from './guards/42guards';
import { AuthenticationService } from './authentication.service';
import { JwtService } from '@nestjs/jwt';
import { Response } from 'express';
import { TwoFaDto } from './dto/2fa.dto';
import { UsersService } from 'src/users/users.service';
import { User } from 'src/users/entities/user.entity';
import { request } from 'http';
@Controller('auth')
export class AuthenticationController {
constructor(private authService: AuthenticationService,
private userService: UsersService,
// private jwtservice: JwtService
) {}
@@ -18,6 +22,7 @@ export class AuthenticationController {
@Get()
@UseGuards(FortyTwoAuthGuard)
login() {
console.log('ON EST DANS LOGIN AUTH CONTROLLER');
return ;
}
@@ -28,8 +33,8 @@ export class AuthenticationController {
*/
@Get('redirect')
@UseGuards(FortyTwoAuthGuard)
async redirect(@Res() response : Response) {
response.send(200);
async redirect(@Res() response : Response, @Req() request) {
response.sendStatus(200);
}
/**
@@ -48,7 +53,31 @@ export class AuthenticationController {
* Route pour déconnecter l'utilisateur
*/
@Get('logout')
logout() {
return 'logout';
logout(@Req() request) {
console.log('ON EST DANS LOGOUT AUTH CONTROLLER')
request.session.destroy();
return {msg : 'You are now logged out'};
}
@Post('2fa/generate')
@UseGuards(AuthenticateGuard)
async register(@Req() request, @Res() response){
console.log('ON EST DANS REGISTER POUR 2FA AUTH CONTROLLER')
const { otpauth } = await this.authService.generate2FaSecret(request.user);
return this.authService.pipeQrCodeStream(response, otpauth);
}
@Post('2fa/turn-on')
@UseGuards(AuthenticateGuard)
async verify(@Req() request, @Body() {twoFaCode} : TwoFaDto){
console.log('ON EST DANS VERIFY POUR 2FA AUTH CONTROLLER')
const isCodeIsValid = await this.authService.verify2FaCode(request.user, twoFaCode);
if (isCodeIsValid === false)
{
request.session.destroy();
throw new UnauthorizedException('Wrong Code.');
}
await this.userService.enableTwoFactorAuth(request.user.id);
}
}

View File

@@ -1,6 +1,4 @@
import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Friendship } from 'src/friendship/entities/friendship.entity';
import { User } from 'src/users/entities/user.entity';
@@ -9,7 +7,6 @@ import { UsersService } from 'src/users/users.service';
import { AuthenticationController } from './authentication.controller';
import { AuthenticationService } from './authentication.service';
import { FortyTwoStrategy } from './strategy/42strategy';
import { JwtStrategy } from './strategy/jwtStrategy';
import { SessionSerializer } from './utils/serializer';
@Module({

View File

@@ -2,13 +2,13 @@ import { Injectable } from '@nestjs/common';
import { CreateUsersDto } from 'src/users/dto/create-users.dto';
import { User } from 'src/users/entities/user.entity';
import { UsersService } from 'src/users/users.service';
import { JwtService } from '@nestjs/jwt';
import { toFileStream } from 'qrcode';
import { authenticator } from 'otplib';
@Injectable()
export class AuthenticationService {
constructor(
private readonly userService: UsersService,
// private readonly jwtService: JwtService,
) {}
async validateUser(createUsersDto :CreateUsersDto){
@@ -23,8 +23,21 @@ export class AuthenticationService {
return await this.userService.findOneByFourtyTwoId(fourtytwo_id);
}
// async login(payload: any) {
// return this.jwtService.sign(payload);
// }
async verify2FaCode(user : User, code : string) {
return authenticator.verify({ token: code, secret: user.secretTwoFactorAuth });
}
async generate2FaSecret(user : User) {
const secret = authenticator.generateSecret();
const otpauth = authenticator.keyuri(user.email, process.env.TWO_FACTOR_AUTHENTICATION_APP_NAME, secret);
await this.userService.setAuthenticatorSecret(user.id, secret);
return { secret, otpauth };
}
async pipeQrCodeStream(stream : Response, otpauthUrl : string) {
return toFileStream(stream, otpauthUrl);
}
}

View File

@@ -0,0 +1,6 @@
import { IsEmpty, IsString } from "class-validator";
export class TwoFaDto {
@IsString()
readonly twoFaCode: string;
}

View File

@@ -1,6 +0,0 @@
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

View File

@@ -18,10 +18,13 @@ export class FortyTwoStrategy extends PassportStrategy(Strategy, "42") {
async validate(accessToken: string, refreshToken: string, profile: Profile, callbackURL: string) {
console.log("Validate inside strategy.ts");
console.log(profile.id, profile.username, profile.phoneNumbers[0].value, profile.emails[0].value, profile.photos[0].value);
const userDTO: CreateUsersDto = { fortyTwoId: profile.id, username: profile.username, email: profile.emails[0].value, image_url: profile.photos[0].value };
const userDTO: CreateUsersDto = { fortyTwoId: profile.id, username: profile.username, email: profile.emails[0].value, image_url: profile.photos[0].value, isEnabledTwoFactorAuth: false };
const user = await this.authenticationService.validateUser(userDTO);
if (!user)
throw new UnauthorizedException();
return user;
if (!user.isEnabledTwoFactorAuth)
return user;
if (userDTO.isEnabledTwoFactorAuth)
return user;
}
}

View File

@@ -1,24 +0,0 @@
import { Injectable, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy as PassportJwtStrategy } from "passport-jwt";
import { AuthenticationService } from "../authentication.service";
import { Request } from "express";
@Injectable()
export class JwtStrategy extends PassportStrategy(PassportJwtStrategy, "jwt") {
constructor(private readonly authenticationService: AuthenticationService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.JWT_SECRET,
});
}
async validate(payload: any) {
console.log("Validate inside jwtStrategy.ts");
const user = await this.authenticationService.findUser(payload.fourtyTwoId);
if (!user)
throw new UnauthorizedException('You must be logged in to continue.');
return { fourtyTwoId: payload.fourtyTwoId, username: payload.username, image_url: payload.image_url };
}
}

View File

@@ -2,8 +2,6 @@ import { Body, Controller, Delete, Get, HttpCode, HttpException, HttpStatus, Par
import { AuthenticateGuard } from 'src/auth/42/guards/42guards';
import { User } from 'src/users/entities/user.entity';
import { CreateFriendshipDto } from './dto/create-friendship.dto';
import { UpdateFriendshipDto } from './dto/update-friendship.dto';
import { FriendshipStatus } from './entities/friendship.entity';
import { FriendshipService } from './friendship.service';
@Controller('network')

View File

@@ -1,4 +1,4 @@
import { IsEmail, IsString } from 'class-validator';
import { IsBoolean, IsEmail, IsOptional, IsString } from 'class-validator';
import { Unique } from 'typeorm';
export class CreateUsersDto {
@@ -10,4 +10,7 @@ export class CreateUsersDto {
readonly email: string;
@IsString()
readonly image_url: string;
@IsBoolean()
@IsOptional()
readonly isEnabledTwoFactorAuth: boolean;
}

View File

@@ -30,6 +30,12 @@ export class User {
@Column('json', { nullable: true })
status: [string];
@Column({ default: false, nullable: true })
isEnabledTwoFactorAuth: boolean;
@Column({ nullable: true })
secretTwoFactorAuth: string;
@JoinTable()
@OneToMany(type => Friendship , (friendship) => friendship.requesterId)
requesterId: Friendship[];

View File

@@ -73,4 +73,12 @@ export class UsersService {
throw new HttpException(`The user could not be deleted.`,HttpStatus.NOT_FOUND);
return this.userRepository.remove(user);
}
async enableTwoFactorAuth(id: string) {
return this.userRepository.update(id, {isEnabledTwoFactorAuth: true});
}
async setAuthenticatorSecret(id: number, secret: string) {
return this.userRepository.update(id, {secretTwoFactorAuth: secret});
}
}