백엔드에서 JWT가 아닌 세션 ID 기반으로 인증하도록 변경

This commit is contained in:
static
2025-01-12 07:28:38 +09:00
parent 0bdf990dae
commit 1a86c8d9e0
42 changed files with 487 additions and 624 deletions

View File

@@ -4,20 +4,16 @@ import { loginRequest } from "$lib/server/schemas";
import { login } from "$lib/server/services/auth";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies }) => {
export const POST: RequestHandler = async ({ locals, request, cookies }) => {
const zodRes = loginRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");
const { email, password } = zodRes.data;
const { accessToken, refreshToken } = await login(email, password);
cookies.set("accessToken", accessToken, {
const { sessionIdSigned } = await login(email, password, locals.ip, locals.userAgent);
cookies.set("sessionId", sessionIdSigned, {
path: "/",
maxAge: env.jwt.accessExp / 1000,
sameSite: "strict",
});
cookies.set("refreshToken", refreshToken, {
path: "/api/auth",
maxAge: env.jwt.refreshExp / 1000,
maxAge: env.session.exp / 1000,
secure: true,
sameSite: "strict",
});

View File

@@ -1,14 +1,13 @@
import { error, text } from "@sveltejs/kit";
import { text } from "@sveltejs/kit";
import { authorize } from "$lib/server/modules/auth";
import { logout } from "$lib/server/services/auth";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ cookies }) => {
const token = cookies.get("refreshToken");
if (!token) error(401, "Refresh token not found");
export const POST: RequestHandler = async ({ locals, cookies }) => {
const { sessionId } = await authorize(locals, "any");
await logout(token);
cookies.delete("accessToken", { path: "/" });
cookies.delete("refreshToken", { path: "/api/auth" });
await logout(sessionId);
cookies.delete("sessionId", { path: "/" });
return text("Logged out", { headers: { "Content-Type": "text/plain" } });
};

View File

@@ -1,23 +0,0 @@
import { error, text } from "@sveltejs/kit";
import env from "$lib/server/loadenv";
import { refreshToken as doRefreshToken } from "$lib/server/services/auth";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ cookies }) => {
const token = cookies.get("refreshToken");
if (!token) error(401, "Refresh token not found");
const { accessToken, refreshToken } = await doRefreshToken(token);
cookies.set("accessToken", accessToken, {
path: "/",
maxAge: env.jwt.accessExp / 1000,
sameSite: "strict",
});
cookies.set("refreshToken", refreshToken, {
path: "/api/auth",
maxAge: env.jwt.refreshExp / 1000,
sameSite: "strict",
});
return text("Token refreshed", { headers: { "Content-Type": "text/plain" } });
};

View File

@@ -0,0 +1,26 @@
import { error, json } from "@sveltejs/kit";
import { authorize } from "$lib/server/modules/auth";
import {
sessionUpgradeRequest,
sessionUpgradeResponse,
type SessionUpgradeResponse,
} from "$lib/server/schemas";
import { createSessionUpgradeChallenge } from "$lib/server/services/auth";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ locals, request }) => {
const { sessionId, userId } = await authorize(locals, "notClient");
const zodRes = sessionUpgradeRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");
const { encPubKey, sigPubKey } = zodRes.data;
const { challenge } = await createSessionUpgradeChallenge(
sessionId,
userId,
locals.ip,
encPubKey,
sigPubKey,
);
return json(sessionUpgradeResponse.parse({ challenge } satisfies SessionUpgradeResponse));
};

View File

@@ -0,0 +1,16 @@
import { error, text } from "@sveltejs/kit";
import { authorize } from "$lib/server/modules/auth";
import { sessionUpgradeVerifyRequest } from "$lib/server/schemas";
import { verifySessionUpgradeChallenge } from "$lib/server/services/auth";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ locals, request }) => {
const { sessionId } = await authorize(locals, "notClient");
const zodRes = sessionUpgradeVerifyRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");
const { answer, answerSig } = zodRes.data;
await verifySessionUpgradeChallenge(sessionId, locals.ip, answer, answerSig);
return text("Session upgraded", { headers: { "Content-Type": "text/plain" } });
};

View File

@@ -1,25 +0,0 @@
import { error, json } from "@sveltejs/kit";
import {
tokenUpgradeRequest,
tokenUpgradeResponse,
type TokenUpgradeResponse,
} from "$lib/server/schemas";
import { createTokenUpgradeChallenge } from "$lib/server/services/auth";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies, getClientAddress }) => {
const token = cookies.get("refreshToken");
if (!token) error(401, "Refresh token not found");
const zodRes = tokenUpgradeRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");
const { encPubKey, sigPubKey } = zodRes.data;
const { challenge } = await createTokenUpgradeChallenge(
token,
getClientAddress(),
encPubKey,
sigPubKey,
);
return json(tokenUpgradeResponse.parse({ challenge } satisfies TokenUpgradeResponse));
};

View File

@@ -1,33 +0,0 @@
import { error, text } from "@sveltejs/kit";
import env from "$lib/server/loadenv";
import { tokenUpgradeVerifyRequest } from "$lib/server/schemas";
import { upgradeToken } from "$lib/server/services/auth";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies, getClientAddress }) => {
const token = cookies.get("refreshToken");
if (!token) error(401, "Refresh token not found");
const zodRes = tokenUpgradeVerifyRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");
const { answer, answerSig } = zodRes.data;
const { accessToken, refreshToken } = await upgradeToken(
token,
getClientAddress(),
answer,
answerSig,
);
cookies.set("accessToken", accessToken, {
path: "/",
maxAge: env.jwt.accessExp / 1000,
sameSite: "strict",
});
cookies.set("refreshToken", refreshToken, {
path: "/api/auth",
maxAge: env.jwt.refreshExp / 1000,
sameSite: "strict",
});
return text("Token upgraded", { headers: { "Content-Type": "text/plain" } });
};

View File

@@ -1,15 +1,11 @@
import { error, json } from "@sveltejs/kit";
import { authenticate } from "$lib/server/modules/auth";
import { json } from "@sveltejs/kit";
import { authorize } from "$lib/server/modules/auth";
import { clientListResponse, type ClientListResponse } from "$lib/server/schemas";
import { getUserClientList } from "$lib/server/services/client";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ cookies }) => {
const { userId, clientId } = authenticate(cookies);
if (!clientId) {
error(403, "Forbidden");
}
export const GET: RequestHandler = async ({ locals }) => {
const { userId } = await authorize(locals, "anyClient");
const { userClients } = await getUserClientList(userId);
return json(clientListResponse.parse({ clients: userClients } satisfies ClientListResponse));
};

View File

@@ -1,5 +1,5 @@
import { error, json } from "@sveltejs/kit";
import { authenticate } from "$lib/server/modules/auth";
import { authorize } from "$lib/server/modules/auth";
import {
clientRegisterRequest,
clientRegisterResponse,
@@ -8,16 +8,13 @@ import {
import { registerUserClient } from "$lib/server/services/client";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies, getClientAddress }) => {
const { userId, clientId } = authenticate(cookies);
if (clientId) {
error(403, "Forbidden");
}
export const POST: RequestHandler = async ({ locals, request }) => {
const { userId } = await authorize(locals, "notClient");
const zodRes = clientRegisterRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");
const { encPubKey, sigPubKey } = zodRes.data;
const { challenge } = await registerUserClient(userId, getClientAddress(), encPubKey, sigPubKey);
const { challenge } = await registerUserClient(userId, locals.ip, encPubKey, sigPubKey);
return json(clientRegisterResponse.parse({ challenge } satisfies ClientRegisterResponse));
};

View File

@@ -1,19 +1,16 @@
import { error, text } from "@sveltejs/kit";
import { authenticate } from "$lib/server/modules/auth";
import { authorize } from "$lib/server/modules/auth";
import { clientRegisterVerifyRequest } from "$lib/server/schemas";
import { verifyUserClient } from "$lib/server/services/client";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies, getClientAddress }) => {
const { userId, clientId } = authenticate(cookies);
if (clientId) {
error(403, "Forbidden");
}
export const POST: RequestHandler = async ({ locals, request }) => {
const { userId } = await authorize(locals, "notClient");
const zodRes = clientRegisterVerifyRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");
const { answer, answerSig } = zodRes.data;
await verifyUserClient(userId, getClientAddress(), answer, answerSig);
await verifyUserClient(userId, locals.ip, answer, answerSig);
return text("Client verified", { headers: { "Content-Type": "text/plain" } });
};

View File

@@ -1,15 +1,11 @@
import { error, json } from "@sveltejs/kit";
import { authenticate } from "$lib/server/modules/auth";
import { json } from "@sveltejs/kit";
import { authorize } from "$lib/server/modules/auth";
import { clientStatusResponse, type ClientStatusResponse } from "$lib/server/schemas";
import { getUserClientStatus } from "$lib/server/services/client";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ cookies }) => {
const { userId, clientId } = authenticate(cookies);
if (!clientId) {
error(403, "Forbidden");
}
export const GET: RequestHandler = async ({ locals }) => {
const { userId, clientId } = await authorize(locals, "anyClient");
const { state, isInitialMekNeeded } = await getUserClientStatus(userId, clientId);
return json(
clientStatusResponse.parse({

View File

@@ -5,8 +5,8 @@ import { directoryInfoResponse, type DirectoryInfoResponse } from "$lib/server/s
import { getDirectoryInformation } from "$lib/server/services/directory";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ cookies, params }) => {
const { userId } = await authorize(cookies, "activeClient");
export const GET: RequestHandler = async ({ locals, params }) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = z
.object({

View File

@@ -4,8 +4,8 @@ import { authorize } from "$lib/server/modules/auth";
import { deleteDirectory } from "$lib/server/services/directory";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ cookies, params }) => {
const { userId } = await authorize(cookies, "activeClient");
export const POST: RequestHandler = async ({ locals, params }) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = z
.object({

View File

@@ -5,8 +5,8 @@ import { directoryRenameRequest } from "$lib/server/schemas";
import { renameDirectory } from "$lib/server/services/directory";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies, params }) => {
const { userId } = await authorize(cookies, "activeClient");
export const POST: RequestHandler = async ({ locals, params, request }) => {
const { userId } = await authorize(locals, "activeClient");
const paramsZodRes = z
.object({

View File

@@ -4,8 +4,8 @@ import { directoryCreateRequest } from "$lib/server/schemas";
import { createDirectory } from "$lib/server/services/directory";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies }) => {
const { userId } = await authorize(cookies, "activeClient");
export const POST: RequestHandler = async ({ locals, request }) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = directoryCreateRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");

View File

@@ -5,8 +5,8 @@ import { fileInfoResponse, type FileInfoResponse } from "$lib/server/schemas";
import { getFileInformation } from "$lib/server/services/file";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ cookies, params }) => {
const { userId } = await authorize(cookies, "activeClient");
export const GET: RequestHandler = async ({ locals, params }) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = z
.object({

View File

@@ -4,8 +4,8 @@ import { authorize } from "$lib/server/modules/auth";
import { deleteFile } from "$lib/server/services/file";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ cookies, params }) => {
const { userId } = await authorize(cookies, "activeClient");
export const POST: RequestHandler = async ({ locals, params }) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = z
.object({

View File

@@ -4,8 +4,8 @@ import { authorize } from "$lib/server/modules/auth";
import { getFileStream } from "$lib/server/services/file";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ cookies, params }) => {
const { userId } = await authorize(cookies, "activeClient");
export const GET: RequestHandler = async ({ locals, params }) => {
const { userId } = await authorize(locals, "activeClient");
const zodRes = z
.object({

View File

@@ -5,8 +5,8 @@ import { fileRenameRequest } from "$lib/server/schemas";
import { renameFile } from "$lib/server/services/file";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies, params }) => {
const { userId } = await authorize(cookies, "activeClient");
export const POST: RequestHandler = async ({ locals, params, request }) => {
const { userId } = await authorize(locals, "activeClient");
const paramsZodRes = z
.object({

View File

@@ -4,8 +4,8 @@ import { fileUploadRequest } from "$lib/server/schemas";
import { uploadFile } from "$lib/server/services/file";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies }) => {
const { userId } = await authorize(cookies, "activeClient");
export const POST: RequestHandler = async ({ locals, request }) => {
const { userId } = await authorize(locals, "activeClient");
const form = await request.formData();
const metadata = form.get("metadata");

View File

@@ -4,8 +4,8 @@ import { masterKeyListResponse, type MasterKeyListResponse } from "$lib/server/s
import { getClientMekList } from "$lib/server/services/mek";
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ cookies }) => {
const { userId, clientId } = await authorize(cookies, "activeClient");
export const GET: RequestHandler = async ({ locals }) => {
const { userId, clientId } = await authorize(locals, "activeClient");
const { encMeks } = await getClientMekList(userId, clientId);
return json(
masterKeyListResponse.parse({

View File

@@ -1,14 +1,11 @@
import { error, text } from "@sveltejs/kit";
import { authenticate } from "$lib/server/modules/auth";
import { authorize } from "$lib/server/modules/auth";
import { initialMasterKeyRegisterRequest } from "$lib/server/schemas";
import { registerInitialActiveMek } from "$lib/server/services/mek";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request, cookies }) => {
const { userId, clientId } = authenticate(cookies);
if (!clientId) {
error(403, "Forbidden");
}
export const POST: RequestHandler = async ({ locals, request }) => {
const { userId, clientId } = await authorize(locals, "pendingClient");
const zodRes = initialMasterKeyRegisterRequest.safeParse(await request.json());
if (!zodRes.success) error(400, "Invalid request body");