AI DEV portal 초기 커밋
Express+EJS+Postgres 사내 개발 포털. - Keycloak OIDC(사번 로그인), GitHub 감성 UI - 사이트 모음 + 프로젝트 공유/코멘트/스타 - DB: OpenEverest appdb portal schema (portal_app role) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
53
src/auth.js
Normal file
53
src/auth.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// Keycloak OIDC (Authorization Code). openid-client v5.
|
||||
import { Issuer, generators } from "openid-client";
|
||||
import { config } from "./config.js";
|
||||
|
||||
let client;
|
||||
|
||||
export async function initOidc() {
|
||||
const issuer = await Issuer.discover(config.oidc.issuer);
|
||||
client = new issuer.Client({
|
||||
client_id: config.oidc.clientId,
|
||||
client_secret: config.oidc.clientSecret,
|
||||
redirect_uris: [`${config.baseUrl}/auth/callback`],
|
||||
response_types: ["code"],
|
||||
});
|
||||
return client;
|
||||
}
|
||||
|
||||
// 로그인 시작 — state/nonce 를 세션에 저장하고 Keycloak 으로 리다이렉트
|
||||
export function loginRedirect(req, res) {
|
||||
const state = generators.state();
|
||||
const nonce = generators.nonce();
|
||||
req.session.oidc = { state, nonce };
|
||||
const url = client.authorizationUrl({
|
||||
scope: "openid profile email",
|
||||
state,
|
||||
nonce,
|
||||
});
|
||||
res.redirect(url);
|
||||
}
|
||||
|
||||
// 콜백 처리 — 토큰 교환 후 사용자 클레임 반환
|
||||
export async function handleCallback(req) {
|
||||
const params = client.callbackParams(req);
|
||||
const { state, nonce } = req.session.oidc || {};
|
||||
const tokenSet = await client.callback(`${config.baseUrl}/auth/callback`, params, {
|
||||
state,
|
||||
nonce,
|
||||
});
|
||||
const claims = tokenSet.claims();
|
||||
return {
|
||||
sabun: claims.preferred_username, // 사번
|
||||
name: claims.name || claims.given_name || claims.preferred_username,
|
||||
email: claims.email,
|
||||
};
|
||||
}
|
||||
|
||||
// 로그인 필수 가드
|
||||
export function requireAuth(req, res, next) {
|
||||
if (req.session.user) return next();
|
||||
// API 요청은 401, 페이지 요청은 로그인으로
|
||||
if (req.path.startsWith("/api/")) return res.status(401).json({ error: "unauthorized" });
|
||||
return res.redirect("/login");
|
||||
}
|
||||
Reference in New Issue
Block a user