초기 PM 소스 전체 업로드
This commit is contained in:
44
oauth/oauthController.js
Normal file
44
oauth/oauthController.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const crypto = require('crypto');
|
||||
const oauthService = require('./oauthService');
|
||||
const axios = require('axios');
|
||||
|
||||
// 1. 로그인 여부 검증 미들웨어
|
||||
exports.isLoggedIn = async (req, res, next) => {
|
||||
if (req.session?.user || (req.isAuthenticated && req.isAuthenticated())) {
|
||||
return next();
|
||||
}
|
||||
console.log('🚥 [oauthController] User not authenticated. Redirecting to login page.');
|
||||
return res.redirect('/user/login?path=' + encodeURIComponent(req.originalUrl));
|
||||
};
|
||||
|
||||
|
||||
// 2. OAuth Callback 핸들러 (로컬 개발 환경에서는 직접 호출되지 않음)
|
||||
exports.handleCallback = async (req, res) => {
|
||||
const { code, state, next } = req.query;
|
||||
try {
|
||||
const { user } = await oauthService.exchangeToken(code, state, req.hostname);
|
||||
req.session.user = user;
|
||||
req.user = user;
|
||||
return res.redirect(next || "/");
|
||||
} catch (err) {
|
||||
console.error("Token exchange error:", err);
|
||||
return res.status(500).send("토큰 처리 실패");
|
||||
}
|
||||
};
|
||||
|
||||
// 3. 사용자 정보 역직렬화 (GSIM 연동 우회 및 가상 최고권한 권한 설정)
|
||||
exports.deserializeUser = async (req, res, next) => {
|
||||
if (req.session?.user) {
|
||||
req.user = {
|
||||
user_id: req.session.user.userId,
|
||||
user_nm: req.session.user.user_nm,
|
||||
group: req.session.user.group,
|
||||
company: '한맥기술',
|
||||
dept: '개발본부',
|
||||
position: '부장',
|
||||
permission: 1535, // master/dev급 세부 권한 비트플래그
|
||||
bookmark: ''
|
||||
};
|
||||
}
|
||||
next();
|
||||
};
|
||||
21
oauth/oauthRouter.js
Normal file
21
oauth/oauthRouter.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const oauthController = require("./oauthController");
|
||||
|
||||
router.get("/callback", oauthController.handleCallback);
|
||||
|
||||
router.get("/logout", (req, res) => {
|
||||
const redirectUrl = `${req.protocol}://${req.get("host")}`;
|
||||
|
||||
// 1) 서비스 로컬 세션 제거
|
||||
req.session.destroy(() => {
|
||||
res.clearCookie("connect.sid");
|
||||
|
||||
// 2) Sentinel 로그아웃 호출 (redirect 포함)
|
||||
return res.redirect(
|
||||
`${process.env.SENTINEL_BASE}/oauth/logout?redirect=${redirectUrl}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
90
oauth/oauthService.js
Normal file
90
oauth/oauthService.js
Normal file
@@ -0,0 +1,90 @@
|
||||
const crypto = require('crypto');
|
||||
const axios = require('axios');
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
exports.exchangeToken = async (code, state, hostname) => {
|
||||
let client_id = '';
|
||||
if (process.env.CLIENT_ID.includes('PM_LOCAL')) client_id = process.env.CLIENT_ID;
|
||||
else if (process.env.SERVICE_NAME === 'PM_ver4_ONPREMISE') client_id = 'PM_ONPREMISE';
|
||||
else if (process.env.SERVICE_NAME === 'PM_ver4_CLOUD_OVERSEAS') {
|
||||
if (hostname.toLowerCase().includes('gtb.')) client_id = 'PM_GTB';
|
||||
if (hostname.toLowerCase().includes('bim.')) client_id = 'PM_BIM';
|
||||
if (hostname.toLowerCase().includes('overseas.')) client_id = 'PM_OVERSEAS';
|
||||
if (hostname.toLowerCase().includes('jangheon.')) client_id = 'PM_JANGHEON';
|
||||
if (hostname.toLowerCase().includes('jangheonindustry.')) client_id = 'PM_JANGHEONINDUSTRY';
|
||||
//test용 - sentinel에 등록되어있어야함
|
||||
if (hostname.toLowerCase().includes('172') || hostname.toLowerCase().includes('localhost')) {
|
||||
client_id = process.env.CLIENT_ID;
|
||||
}
|
||||
}
|
||||
|
||||
let secret = '';
|
||||
if (process.env.CLIENT_ID.includes('PM_LOCAL')) secret = process.env.CLIENT_SECRET_LOCAL;
|
||||
else if (process.env.SERVICE_NAME === 'PM_ver4_ONPREMISE') secret = process.env.CLIENT_SECRET_ONPREMISE;
|
||||
else if (process.env.SERVICE_NAME === 'PM_ver4_CLOUD_OVERSEAS') {
|
||||
if (hostname.toLowerCase().includes('gtb.')) secret = process.env.CLIENT_SECRET_GTB;
|
||||
if (hostname.toLowerCase().includes('bim.')) secret = process.env.CLIENT_SECRET_BIM;
|
||||
if (hostname.toLowerCase().includes('overseas.')) secret = process.env.CLIENT_SECRET_OVERSEAS;
|
||||
if (hostname.toLowerCase().includes('jangheon.')) secret = process.env.CLIENT_SECRET_JANGHEON;
|
||||
if (hostname.toLowerCase().includes('jangheonindustry.')) secret = process.env.CLIENT_SECRET_JANGHEONINDUSTRY;
|
||||
//test용 - sentinel에 등록되어있어야함
|
||||
if (hostname.toLowerCase().includes('172') || hostname.toLowerCase().includes('localhost')) {
|
||||
secret = process.env.CLIENT_SECRET_LOCAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const { encrypted, iv } = _encrypt(secret);
|
||||
console.log("encrypted ", encrypted);
|
||||
const tokenResp = await axios.post(`${process.env.SENTINEL_BASE}/oauth/token`, {
|
||||
code,
|
||||
client_id: client_id,
|
||||
client_secret_enc: encrypted,
|
||||
iv,
|
||||
state // state 추가
|
||||
});
|
||||
|
||||
const { access_token, next } = tokenResp.data;
|
||||
// return jwt.verify(access_token, process.env.JWT_SECRET);
|
||||
|
||||
const verifyOptions = {
|
||||
issuer: process.env.JWT_ISSUER,
|
||||
audience: client_id,
|
||||
algorithms: ["HS256"],
|
||||
clockTolerance: 30
|
||||
};
|
||||
|
||||
const user = jwt.verify(access_token, process.env.JWT_SECRET, verifyOptions);
|
||||
|
||||
return {
|
||||
user,
|
||||
next: next || null,
|
||||
};
|
||||
};
|
||||
|
||||
exports.isLoggedIn = async (req, res, next) => {
|
||||
// 로컬 테스트 시 강제로 세션 주입하고 통과시킴
|
||||
req.session.user = {
|
||||
userId: 'test_user',
|
||||
user_nm: '테스트사용자',
|
||||
group: 'dev'
|
||||
};
|
||||
next();
|
||||
}
|
||||
|
||||
//const AES_KEY = Buffer.from(process.env.AES_KEY_32BYTE, "utf8");
|
||||
const AES_KEY_32BYTE = "abcdefghijklmnopqrstuvwxyz123456";
|
||||
|
||||
|
||||
function _encrypt(text) {
|
||||
const iv = crypto.randomBytes(16);
|
||||
const cipher = crypto.createCipheriv("aes-256-cbc", AES_KEY, iv);
|
||||
|
||||
let enc = cipher.update(text, "utf8", "base64");
|
||||
enc += cipher.final("base64");
|
||||
|
||||
return {
|
||||
encrypted: enc,
|
||||
iv: iv.toString("base64")
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user