Skip to content

Commit

Permalink
Server / 실행 환경 수정 (#682)
Browse files Browse the repository at this point in the history
* fix: disable admin

* fix: fix env

* fix: fix develop env

* fix: fix package.json

* feat: implement randomKey method

* fix: fix typoe

* fix: fix cors

* feat: implement api key generate & validation logic

* fix: implement config session_key

* fix: log signed sid

* fix: fix generateAPIKey API

* fix: test1

* fix: revert

* fix: fix APIs

* fix: fix settings

* fix: add comment
  • Loading branch information
jessie129j authored Aug 10, 2024
1 parent a16f49f commit 1d55410
Show file tree
Hide file tree
Showing 12 changed files with 404 additions and 339 deletions.
28 changes: 13 additions & 15 deletions server/@types/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,36 @@ declare namespace NodeJS {
}
interface ProcessEnv {
/** node environment */
SERVER_URL?: string;
SERVER_URL: string;
SERVER_PORT: string;
CLIENT: string;
CLIENT_ADMIN: string;
DB_URL: string;

REDIS_URL: string;
SESSION_KEY: string;

CRYPTO_KEY: string;
CRYPTO_SALT: string;
CRYPTO_ALGORITHM: string;

GOOGLE_CLIENT_ID: string;
GOOGLE_CLIENT_SECRET: string;
NAVER_CLIENT_ID: string;
NAVER_CLIENT_SECRET: string;
KAKAO_CLIENT_ID: string;

SALT_ROUNDS: string;
SESSION_KEY: string;

NODEMAILER_USER: string;
NODEMAILER_PASS: string;

REDIS_URL: string;

CRYPTO_KEY: string;
CRYPTO_SALT: string;
CRYPTO_ALGORITHM: string;

S3_ACESSKEYID: string;
S3_SECRETACCESSKEY: string;
S3_BUCKET_LOGS: string;

PORTONE_IMP_KEY: string;
PORTONE_IMP_SECRET: string;
PORTONE_IMP_IP_LIST: string;
PORTONE_IMP_IP_SEP: string;

GOOGLE_CREDENTIALS_CLIENT_EMAIL: string;
GOOGLE_CREDENTIALS_PRIVATE_KEY_NEWLINE_SEP: string;
GOOGLE_CREDENTIALS_PRIVATE_KEY: string;

APPLE_SHARED_SECRET: string;
}
}
4 changes: 4 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"description": "",
"main": "src/app.ts",
"scripts": {
"local": "cross-env NODE_ENV=local npm run build:live",
"dev:new": "cross-env NODE_ENV=develop node -r ./tsconfig-paths-bootstrap.js dist/src/app.js",
"dev": "cross-env NODE_ENV=development npm run build:live",
"prod": "cross-env NODE_ENV=production node -r ./tsconfig-paths-bootstrap.js dist/src/app.js",
"build": "tsc -p . && npm run build:copy-files",
Expand All @@ -15,10 +17,12 @@
"license": "ISC",
"dependencies": {
"@types/axios": "^0.14.0",
"@types/cookie-signature": "^1.1.2",
"@types/passport-google-oauth20": "^2.0.11",
"axios": "^1.4.0",
"connect-redis": "^6.1.3",
"cookie-parser": "^1.4.6",
"cookie-signature": "^1.2.1",
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"dayjs": "^1.11.11",
Expand Down
73 changes: 44 additions & 29 deletions server/src/api/controllers/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,22 @@ import { SnsIdNotFoundError } from "src/errors/NotFoundError";
import { AtLeastOneSnsIdIsRequiredError } from "src/errors/ConfilicError";
import { FieldInvalidError } from "src/errors/InvalidError";
import { convertToUser } from "src/types/user";
import cookieSignature from "cookie-signature";
import config from "src/config";

const AuthService = UserService.AuthService;

const clientRedirectURL = process.env.CLIENT.trim() + "/redirect/auth";

const clientAdminURL = process.env.CLIENT_ADMIN.trim();
// const clientAdminURL = process.env.CLIENT_ADMIN.trim();

function logSignedSID(sid: string) {
if (config.stage === "develop") {
const signedSID = "s:" + cookieSignature.sign(sid, config.SESSION_KEY);

console.info(`🔑 connect.sid: ${signedSID}`);
}
}

export const find = async (req: Request, res: Response) => {
const user = req.user!;
Expand All @@ -38,28 +49,28 @@ export const find = async (req: Request, res: Response) => {
});
};

export const callbackAdmin = async (
req: Request,
res: Response,
next: NextFunction
) => {
passport.authenticate(
"googleAdmin",
async (authError: Error, user: Express.User) => {
try {
if (authError) throw authError;
return req.login(user, (loginError) => {
if (loginError) throw loginError;
return res.redirect(clientAdminURL + "/login/redirect");
});
} catch (err: any) {
return res.redirect(
clientAdminURL + "?error=" + encodeURIComponent(err.message)
);
}
}
)(req, res, next);
};
// export const callbackAdmin = async (
// req: Request,
// res: Response,
// next: NextFunction
// ) => {
// passport.authenticate(
// "googleAdmin",
// async (authError: Error, user: Express.User) => {
// try {
// if (authError) throw authError;
// return req.login(user, (loginError) => {
// if (loginError) throw loginError;
// return res.redirect(clientAdminURL + "/login/redirect");
// });
// } catch (err: any) {
// return res.redirect(
// clientAdminURL + "?error=" + encodeURIComponent(err.message)
// );
// }
// }
// )(req, res, next);
// };

export const callback = async (
req: Request,
Expand Down Expand Up @@ -93,9 +104,9 @@ export const callback = async (
/* _____ 소셜 로그인 _____ */
if (type === "login") {
return req.login(user, (loginError) => {
if (loginError) {
throw loginError;
}
if (loginError) throw loginError;
logSignedSID(req.sessionID);

// 로그인 성공
req.session.cookie["maxAge"] = 365 * 24 * 60 * 60 * 1000; //1 year
return res.redirect(
Expand All @@ -106,9 +117,9 @@ export const callback = async (
} else if (type === "register") {
/* _____ 소셜 회원 가입 _____ */
return req.login(user, (loginError) => {
if (loginError) {
throw loginError;
}
if (loginError) throw loginError;
logSignedSID(req.sessionID);

// 회원 가입 후 로그인 성공
req.session.cookie["maxAge"] = 365 * 24 * 60 * 60 * 1000; //1 year
return res.redirect(
Expand Down Expand Up @@ -171,6 +182,8 @@ export const local = async (
if ((type === "loginVerify" || type === "registerVerify") && user) {
return req.login(user, (loginError) => {
if (loginError) throw loginError;
logSignedSID(req.sessionID);

/* set maxAge as 1 year if auto login is requested */
if (req.body.persist === true) {
req.session.cookie["maxAge"] = 365 * 24 * 60 * 60 * 1000; //1 year
Expand Down Expand Up @@ -214,6 +227,8 @@ export const guest = async (

return req.login(user, (loginError) => {
if (loginError) throw loginError;
logSignedSID(req.sessionID);

/* set maxAge as 1 year if auto login is requested */
if (req.body.persist === true) {
req.session.cookie["maxAge"] = 365 * 24 * 60 * 60 * 1000; //1 year
Expand Down
27 changes: 27 additions & 0 deletions server/src/api/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
NOT_LOGGED_IN,
NOT_PERMITTED,
} from "src/api/message";
import { API_KEY_COOKIE, API_KEYS } from "src/loaders/express";

export const isLoggedIn = (req: Request, res: Response, next: NextFunction) => {
if (req.isAuthenticated()) {
Expand Down Expand Up @@ -65,3 +66,29 @@ export const isPortOneWebHook = (
res.status(400).send({ message: NOT_LOGGED_IN });
}
};

export function validateAPIKey(
req: Request,
res: Response,
next: NextFunction
) {
if (req.url === "/api/develop/generate-api-key") {
return next();
}

if (!(API_KEY_COOKIE in req.cookies)) {
return res.status(400).send({
code: "API_KEY_REQUIRED",
message: "API key is required",
});
}

if (!API_KEYS.has(req.cookies[API_KEY_COOKIE])) {
return res.status(400).send({
code: "API_KEY_INVALID",
message: "API key is invalid or expired",
});
}

return next();
}
16 changes: 8 additions & 8 deletions server/src/api/routes/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { wrapAsync } from "../middleware/error";

router.get("/", isLoggedIn, auth.find);

router.get(
"/google/admin",
isNotLoggedIn,
passport.authenticate("googleAdmin", {
scope: ["profile"],
})
);
router.get("/google/admin/callback", auth.callbackAdmin);
// router.get(
// "/google/admin",
// isNotLoggedIn,
// passport.authenticate("googleAdmin", {
// scope: ["profile"],
// })
// );
// router.get("/google/admin/callback", auth.callbackAdmin);

router.get(
"/google",
Expand Down
25 changes: 25 additions & 0 deletions server/src/api/routes/develop.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import express, { Request, Response } from "express";
import { API_KEYS } from "src/loaders/express";
import { randomKey } from "src/utils/crypto";
const router = express.Router();

router.get("/generate-api-key", (req: Request, res: Response) => {
const key = randomKey(32);

if (API_KEYS.size >= 10) {
API_KEYS.clear();
}

API_KEYS.add(key);

console.info(`🔑 API Key is generated(${API_KEYS.size}/10): ${key}`);

const maskedKey = key.slice(0, 4) + "*".repeat(28);

return res.status(200).send({
code: "API_KEY_GENERATED",
message: `API key is generated(${maskedKey}); Please check log`,
});
});

export default router;
2 changes: 2 additions & 0 deletions server/src/api/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import agreements from "./agreements";
import test from "./test";
import backups from "./backup.controller";
import migrationRouter from "./migration.router";
import developRouter from "./develop.controller";

export default [
{ label: "users", routes: users },
Expand All @@ -32,4 +33,5 @@ export default [
{ label: "test", routes: test },
{ label: "backups", routes: backups },
{ label: "migrations", routes: migrationRouter },
{ label: "develop", routes: developRouter },
];
Loading

0 comments on commit 1d55410

Please sign in to comment.