From d5ebd5a389eb3838b0abe7997ef73a40d8e644bf Mon Sep 17 00:00:00 2001 From: pagoru Date: Sat, 27 Jul 2024 23:29:39 +0200 Subject: [PATCH] fix #22 --- deno.json | 1 + src/modules/api/v1/account/account.http | 17 ++- src/modules/api/v1/account/login.request.ts | 42 +++++-- src/modules/api/v1/account/main.ts | 3 +- .../api/v1/account/refresh-session.request.ts | 106 ++++++++++++++++++ src/modules/api/v1/hotel/hotel.http | 4 +- .../api/v1/hotel/verify-session.request.ts | 8 ++ src/shared/consts/main.ts | 1 + src/shared/consts/session.consts.ts | 4 + 9 files changed, 174 insertions(+), 12 deletions(-) create mode 100644 src/modules/api/v1/account/refresh-session.request.ts create mode 100644 src/shared/consts/session.consts.ts diff --git a/deno.json b/deno.json index c8dbdfa..969e5c5 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,7 @@ { "tasks": { "start": "deno run -A --watch=./src --unstable-kv mod.ts", + "start:nowatch": "deno run -A --unstable-kv mod.ts", "compile": "deno compile -A --unstable-kv --no-check", diff --git a/src/modules/api/v1/account/account.http b/src/modules/api/v1/account/account.http index b1caf69..6aa9916 100644 --- a/src/modules/api/v1/account/account.http +++ b/src/modules/api/v1/account/account.http @@ -4,7 +4,8 @@ Content-Type: application/json { "username": "pagoru123", - "password": "123456" + "password": "123456", + "captchaId": "" } ### @@ -15,7 +16,19 @@ Content-Type: application/json { "username": "pagoru123", - "password": "123456" + "password": "123456", + "captchaId": "" +} + +### + +# Login +POST http://localhost:2024/v1/account/refresh-session +Content-Type: application/json + +{ + "sessionId": "iZyHMLpYMUFVutkH", + "refreshToken": "bMjnGYbydaMUUM89Qbovx91fCR1H1LXAYvHzPbPrPf5GiuGePWbBhMd9dTSiGIdNY7nfeqhV6nTwEu22UTO4IuZJ680faXRgumnxKnIYvmJORFvkAj4ctRTKafuNe1QW" } ### diff --git a/src/modules/api/v1/account/login.request.ts b/src/modules/api/v1/account/login.request.ts index b0c52d7..bd3ffed 100644 --- a/src/modules/api/v1/account/login.request.ts +++ b/src/modules/api/v1/account/login.request.ts @@ -3,6 +3,10 @@ import { RequestMethod } from "shared/enums/main.ts"; import { System } from "system/main.ts"; import * as bcrypt from "bcrypt"; import { getRandomString } from "shared/utils/main.ts"; +import { + REFRESH_TOKEN_EXPIRE_TIME, + SESSION_EXPIRE_TIME, +} from "shared/consts/main.ts"; export const loginRequest: RequestType = { method: RequestMethod.POST, @@ -20,7 +24,6 @@ export const loginRequest: RequestType = { const { value: account } = await System.db.get(["accounts", username]); - console.log(account); if (!account) return Response.json( { status: 403 }, @@ -40,15 +43,39 @@ export const loginRequest: RequestType = { ); const sessionId = getRandomString(16); + const token = getRandomString(64); + const hash = bcrypt.hashSync(token, bcrypt.genSaltSync(8)); + + const refreshToken = getRandomString(128); + const refreshHash = bcrypt.hashSync(refreshToken, bcrypt.genSaltSync(8)); + + if (account.sessionId) { + await System.db.delete(["session", account.sessionId]); + await System.db.delete(["refresh-session", account.sessionId]); + } - const salt = bcrypt.genSaltSync(8); - const hash = bcrypt.hashSync(token, salt); + await System.db.set( + ["session", sessionId], + { + hash, + accountId: account.accountId, + }, + { expireIn: SESSION_EXPIRE_TIME }, + ); + await System.db.set( + ["refresh-session", sessionId], + { + hash: refreshHash, + accountId: account.accountId, + username, + }, + { expireIn: REFRESH_TOKEN_EXPIRE_TIME }, + ); - await System.db.set(["session", sessionId], { - hash, - accountId: account.accountId, - expireIn: 1000 * 60 * 5, + await System.db.set(["accounts", username], { + ...account, + sessionId, }); return Response.json( @@ -57,6 +84,7 @@ export const loginRequest: RequestType = { data: { sessionId, token, + refreshToken, username, }, }, diff --git a/src/modules/api/v1/account/main.ts b/src/modules/api/v1/account/main.ts index 9fdfc32..9cae90a 100644 --- a/src/modules/api/v1/account/main.ts +++ b/src/modules/api/v1/account/main.ts @@ -3,8 +3,9 @@ import { getPathRequestList } from "shared/utils/main.ts"; import { loginRequest } from "./login.request.ts"; import { registerRequest } from "./register.request.ts"; +import { refreshSessionRequest } from "./refresh-session.request.ts"; export const accountRequestList: RequestType[] = getPathRequestList({ - requestList: [loginRequest, registerRequest], + requestList: [loginRequest, registerRequest, refreshSessionRequest], pathname: "/account", }); diff --git a/src/modules/api/v1/account/refresh-session.request.ts b/src/modules/api/v1/account/refresh-session.request.ts new file mode 100644 index 0000000..00363b3 --- /dev/null +++ b/src/modules/api/v1/account/refresh-session.request.ts @@ -0,0 +1,106 @@ +import { RequestType } from "shared/types/main.ts"; +import { RequestMethod } from "shared/enums/main.ts"; +import { System } from "system/main.ts"; +import * as bcrypt from "bcrypt"; +import { getRandomString } from "shared/utils/main.ts"; +import { + REFRESH_TOKEN_EXPIRE_TIME, + SESSION_EXPIRE_TIME, +} from "shared/consts/main.ts"; + +export const refreshSessionRequest: RequestType = { + method: RequestMethod.POST, + pathname: "/refresh-session", + func: async (request, url) => { + let { sessionId, refreshToken } = await request.json(); + + if (!sessionId || !refreshToken) + return Response.json( + { status: 403 }, + { + status: 403, + }, + ); + + const { value: refreshSession } = await System.db.get([ + "refresh-session", + sessionId, + ]); + + if (!refreshSession) + return Response.json( + { status: 403 }, + { + status: 403, + }, + ); + + const result = bcrypt.compareSync(refreshToken, refreshSession.hash); + + if (!result) + return Response.json( + { status: 403 }, + { + status: 403, + }, + ); + + await System.db.delete(["session", sessionId]); + await System.db.delete(["refresh-session", sessionId]); + + const { value: account } = await System.db.get([ + "accounts", + refreshSession.username, + ]); + + if (!account) + return Response.json( + { status: 403 }, + { + status: 403, + }, + ); + + const token = getRandomString(64); + const hash = bcrypt.hashSync(token, bcrypt.genSaltSync(8)); + + refreshToken = getRandomString(128); + const refreshHash = bcrypt.hashSync(refreshToken, bcrypt.genSaltSync(8)); + + await System.db.set( + ["session", sessionId], + { + hash, + accountId: account.accountId, + }, + { expireIn: SESSION_EXPIRE_TIME }, + ); + await System.db.set( + ["refresh-session", sessionId], + { + hash: refreshHash, + accountId: account.accountId, + username: account.username, + }, + { expireIn: REFRESH_TOKEN_EXPIRE_TIME }, + ); + + await System.db.set(["accounts", account.username], { + ...account, + sessionId, + }); + + return Response.json( + { + status: 200, + data: { + sessionId, + token, + refreshToken, + username: account.username, + }, + }, + { status: 200 }, + ); + }, +}; diff --git a/src/modules/api/v1/hotel/hotel.http b/src/modules/api/v1/hotel/hotel.http index a0b4cdf..5cd8b95 100644 --- a/src/modules/api/v1/hotel/hotel.http +++ b/src/modules/api/v1/hotel/hotel.http @@ -4,8 +4,8 @@ Content-Type: application/json { "username": "pagoru123", - "sessionId": "m58T8hGSKUBnv016", - "token": "8k0Afr58uYQi7Lv40XtcR5Bi7S99CV1BKPxrzw0nGbSDODlLUFYYFKrnjtuxnE5O" + "sessionId": "iZyHMLpYMUFVutkH", + "token": "CnhwAZ7ZbNGfOWlhBoyNRsPD5SmDVMY8BVO2rSzFbpm9JblhsPvh73xZNUIvc2k8" } ### \ No newline at end of file diff --git a/src/modules/api/v1/hotel/verify-session.request.ts b/src/modules/api/v1/hotel/verify-session.request.ts index d5ac361..bff97c0 100644 --- a/src/modules/api/v1/hotel/verify-session.request.ts +++ b/src/modules/api/v1/hotel/verify-session.request.ts @@ -54,6 +54,14 @@ export const verifySessionRequest: RequestType = { // Delete current session await System.db.delete(["session", sessionId]); + // Check if session is current + if (account.sessionId !== sessionId) + return Response.json( + { + status: 403, + }, + { status: 403 }, + ); return Response.json( { diff --git a/src/shared/consts/main.ts b/src/shared/consts/main.ts index ce8353b..32bac2e 100644 --- a/src/shared/consts/main.ts +++ b/src/shared/consts/main.ts @@ -1 +1,2 @@ export * from "./config.consts.ts"; +export * from "./session.consts.ts"; diff --git a/src/shared/consts/session.consts.ts b/src/shared/consts/session.consts.ts new file mode 100644 index 0000000..5c51e3c --- /dev/null +++ b/src/shared/consts/session.consts.ts @@ -0,0 +1,4 @@ +// 5 mins +export const SESSION_EXPIRE_TIME = 1000 * 60 * 5; +// 7 days +export const REFRESH_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 24 * 7;