From b4c4151550213786bef56289588a7dfdd1c13a58 Mon Sep 17 00:00:00 2001 From: Mathis Date: Mon, 2 Sep 2024 14:57:36 +0200 Subject: [PATCH] Add credential management service and module Introduced `CredentialsService` for handling password hashing, verification, and JWT token operations. Added `CredentialsModule` to register `CredentialsService` and integrate it with the ConfigModule. --- .../src/app/credentials/credentials.module.ts | 10 ++++ .../app/credentials/credentials.service.ts | 57 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 apps/backend/src/app/credentials/credentials.module.ts create mode 100644 apps/backend/src/app/credentials/credentials.service.ts diff --git a/apps/backend/src/app/credentials/credentials.module.ts b/apps/backend/src/app/credentials/credentials.module.ts new file mode 100644 index 0000000..37c4990 --- /dev/null +++ b/apps/backend/src/app/credentials/credentials.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; +import { ConfigModule } from "@nestjs/config"; +import { CredentialsService } from "./credentials.service"; + +@Module({ + imports: [ConfigModule], + providers: [CredentialsService], + exports: [CredentialsService], +}) +export class CredentialsModule {} diff --git a/apps/backend/src/app/credentials/credentials.service.ts b/apps/backend/src/app/credentials/credentials.service.ts new file mode 100644 index 0000000..4c679e0 --- /dev/null +++ b/apps/backend/src/app/credentials/credentials.service.ts @@ -0,0 +1,57 @@ +import { BadRequestException, Injectable } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import * as argon from "argon2"; +import * as jose from "jose"; +import { JWTPayload, generateSecret } from "jose"; + +@Injectable() +export class CredentialsService { + constructor(private readonly configService: ConfigService) {} + + async hash(plaintextPassword: string) { + console.log(plaintextPassword); + if (plaintextPassword.length < 6) + throw new BadRequestException("Password is not strong enough !"); + return argon.hash(plaintextPassword, { + secret: Buffer.from(this.configService.get("APP_HASH_SECRET")), + }); + } + + async check(plaintextPassword: string, hashedPassword: string) { + return argon.verify(hashedPassword, plaintextPassword, { + secret: Buffer.from(this.configService.get("APP_HASH_SECRET")), + }); + } + + async verifyAuthToken(token: string) { + try { + const result = await jose.jwtVerify( + token, + Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")), + { + audience: "auth:user", + issuer: "FabLab", + }, + ); + console.log(result); + return result; + } catch (error) { + console.log(error) + throw new BadRequestException("Invalid token"); + } + } + + async signAuthToken(payload: JWTPayload) { + console.log(this.configService.get("APP_TOKEN_SECRET")); + const token = new jose.SignJWT(payload) + .setProtectedHeader({ alg: "HS512", enc: "A128CBC-HS512" }) + .setIssuedAt() + .setExpirationTime("5 day") + .setIssuer("FabLab") + .setAudience("auth:user"); + console.log(token); + return await token.sign( + Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")), + ); + } +}