diff --git a/package.json b/package.json index 6715b59..6821661 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "class-validator": "^0.12.2", "class-validator-jsonschema": "^2.0.3", "consola": "^2.15.0", + "cookie-parser": "^1.4.5", "cors": "^2.8.5", "dotenv": "^8.2.0", "express": "^4.17.1", @@ -82,4 +83,4 @@ ], "delay": "2500" } -} \ No newline at end of file +} diff --git a/src/controllers/AuthController.ts b/src/controllers/AuthController.ts index c2002a3..d6d8d81 100644 --- a/src/controllers/AuthController.ts +++ b/src/controllers/AuthController.ts @@ -1,4 +1,4 @@ -import { Body, JsonController, Post } from 'routing-controllers'; +import { Body, CookieParam, JsonController, Post, Res } from 'routing-controllers'; import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; import { IllegalJWTError, InvalidCredentialsError, JwtNotProvidedError, PasswordNeededError, RefreshTokenCountInvalidError, UsernameOrEmailNeededError } from '../errors/AuthError'; import { UserNotFoundError } from '../errors/UserErrors'; @@ -21,14 +21,16 @@ export class AuthController { @ResponseSchema(PasswordNeededError) @ResponseSchema(InvalidCredentialsError) @OpenAPI({ description: 'Create a new access token object' }) - async login(@Body({ validate: true }) createAuth: CreateAuth) { + async login(@Body({ validate: true }) createAuth: CreateAuth, @Res() response: any) { let auth; try { auth = await createAuth.toAuth(); + response.cookie('lfk_backend__refresh_token', auth.refresh_token, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); + response.cookie('lfk_backend__refresh_token_expires_at', auth.refresh_token_expires_at, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); + return response.send(auth) } catch (error) { throw error; } - return auth } @Post("/logout") @@ -39,14 +41,20 @@ export class AuthController { @ResponseSchema(PasswordNeededError) @ResponseSchema(InvalidCredentialsError) @OpenAPI({ description: 'Create a new access token object' }) - async logout(@Body({ validate: true }) handleLogout: HandleLogout) { + async logout(@Body({ validate: true }) handleLogout: HandleLogout, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any) { + if (refresh_token && refresh_token.length != 0 && handleLogout.token == undefined) { + handleLogout.token = refresh_token; + } + let logout; try { logout = await handleLogout.logout() + await response.cookie('lfk_backend__refresh_token', "expired", { expires: new Date(Date.now()), httpOnly: true }); + response.cookie('lfk_backend__refresh_token_expires_at', "expired", { expires: new Date(Date.now()), httpOnly: true }); } catch (error) { - return error; + throw error; } - return logout + return response.send(logout) } @Post("/refresh") @@ -56,13 +64,18 @@ export class AuthController { @ResponseSchema(UserNotFoundError) @ResponseSchema(RefreshTokenCountInvalidError) @OpenAPI({ description: 'refresh a access token' }) - async refresh(@Body({ validate: true }) refreshAuth: RefreshAuth) { + async refresh(@Body({ validate: true }) refreshAuth: RefreshAuth, @CookieParam("lfk_backend__refresh_token") refresh_token: string, @Res() response: any) { + if (refresh_token && refresh_token.length != 0 && refreshAuth.token == undefined) { + refreshAuth.token = refresh_token; + } let auth; try { auth = await refreshAuth.toAuth(); + response.cookie('lfk_backend__refresh_token', auth.refresh_token, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); + response.cookie('lfk_backend__refresh_token_expires_at', auth.refresh_token_expires_at, { expires: new Date(auth.refresh_token_expires_at * 1000), httpOnly: true }); } catch (error) { - return error; + throw error; } - return auth + return response.send(auth) } } diff --git a/src/loaders/express.ts b/src/loaders/express.ts index 32a28cd..fc3dbc4 100644 --- a/src/loaders/express.ts +++ b/src/loaders/express.ts @@ -1,10 +1,11 @@ +import cookieParser from "cookie-parser"; import { Application } from "express"; - /** * Loader for express related configurations. * Currently only enables the proxy trust. */ export default async (app: Application) => { app.enable('trust proxy'); + app.use(cookieParser()); return app; }; diff --git a/src/models/actions/HandleLogout.ts b/src/models/actions/HandleLogout.ts index 5ecab38..37c30c4 100644 --- a/src/models/actions/HandleLogout.ts +++ b/src/models/actions/HandleLogout.ts @@ -1,4 +1,4 @@ -import { IsString } from 'class-validator'; +import { IsOptional, IsString } from 'class-validator'; import * as jsonwebtoken from 'jsonwebtoken'; import { getConnectionManager } from 'typeorm'; import { config } from '../../config'; @@ -8,7 +8,8 @@ import { Logout } from '../responses/ResponseLogout'; export class HandleLogout { @IsString() - token: string; + @IsOptional() + token?: string; public async logout(): Promise { let logout: Logout = new Logout(); diff --git a/src/models/actions/RefreshAuth.ts b/src/models/actions/RefreshAuth.ts index dacca59..afd22fe 100644 --- a/src/models/actions/RefreshAuth.ts +++ b/src/models/actions/RefreshAuth.ts @@ -1,4 +1,4 @@ -import { IsString } from 'class-validator'; +import { IsOptional, IsString } from 'class-validator'; import * as jsonwebtoken from 'jsonwebtoken'; import { getConnectionManager } from 'typeorm'; import { config } from '../../config'; @@ -8,7 +8,8 @@ import { Auth } from '../responses/ResponseAuth'; export class RefreshAuth { @IsString() - token: string; + @IsOptional() + token?: string; public async toAuth(): Promise { let newAuth: Auth = new Auth();