hrms-api-sso/sso.js
2025-09-12 11:01:19 +07:00

190 lines
No EOL
6.2 KiB
JavaScript

require("dotenv").config();
const cookieParser = require('cookie-parser');
const querystring = require("querystring");
const port = Number(process.env.SSO_PORT) || 80;
const express = require("express");
const cors = require('cors');
const jwt = require("jsonwebtoken");
const fs = require("fs");
const axios = require("axios");
const CryptoJS = require("crypto-js");
const secretKey = "uuidSecretKey2025"; // ใช้เป็นคีย์สำหรับเข้ารหัส
const cookieName = process.env.SSO_COOKIE_NAME || "ssotoken";
const privateKey = fs.readFileSync(`./BMA`, "utf8");
const signOptions = {
issuer: "BMA corp",
subject: "sso@bangkok.go.th",
audience: "http://sso.bangkok.go.th",
expiresIn: "12h",
algorithm: "RS256",
};
const urlKeycloakToken = `${process.env.KC_URL}/realms/${process.env.KC_REALMS}/protocol/openid-connect/token`;
const app = express();
// ตั้งค่าการป้องกัน Origin
const allowedOrigins = ['https://hrms.bangkok.go.th', 'https://hrms.chin.in.th', 'https://hrmsbkk.case-collection.com', 'http://localhost:3002']; // อนุญาตเฉพาะ domain ที่กำหนด //http://localhost:3002
app.use(cors({
// origin: function (origin, callback) {
// if (allowedOrigins.includes(origin)) {
// callback(null, true); // อนุญาต
// } else {
// callback(new Error('Origin not allowed by CORS')); // ปฏิเสธ
// }
// },
methods: ['GET', 'POST'], // จำกัดเฉพาะ method ที่อนุญาต
credentials: true,
}));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
app.get("/api/v1/sso", async (req, res) => {
res.status(200).send("HRMS API SSO");
});
app.post("/api/v1/sso/signin", async (req, res) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
try {
const login_user = req.body;
const formdata = new URLSearchParams();
formdata.append("grant_type", "password");
formdata.append("client_id", process.env.VITE_CLIENTID_KEYCLOAK);
formdata.append("username", login_user.username);
formdata.append("password", login_user.password);
await axios.post(urlKeycloakToken, formdata, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}).then(async () => {
const payload = { username: login_user.username };
let token = jwt.sign(payload, privateKey, signOptions);
res.cookie(cookieName, token, {
maxAge: 1000 * 60 * 60 * 24, // กำหนด timeout หน่วยเป็น millisecond
path: "/",
httpOnly: true,
});
const uid = await CryptoJS.AES.encrypt(login_user.username, secretKey).toString();
res.status(200).send({ uid });
}).catch((err) => {
if (err.status) {
res.status(401).send("Incorrect user or password");
} else
res.status(err.status).send(error);
});
} catch (error) {
res.status(500).send(error);
}
} else {
res.status(403).json({ error: 'Forbidden: Origin not allowed' });
}
});
app.post("/api/v1/sso/kcauth", async (req, res) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
try {
// kcauth
// const useBMA = Boolean(process.env.USE_BMA) || false;
// const publicKeyLanding = fs.readFileSync(`./BMA.pub.pem`, "utf8");
const clientSecret = process.env.KC_CLIENT_SECRET;
const clientId = process.env.KC_CLIENT_ID;
// const cookies = req.cookies;
// const tokenSSO = cookies[cookieName];
//if (tokenSSO) {
// let decodedToken = "";
// if (useBMA) {
// decodedToken = jwt.decode(tokenSSO);
// } else {
// decodedToken = jwt.verify(tokenSSO, publicKeyLanding);
// }
// let d = JSON.parse(JSON.stringify(decodedToken));
// console.log("==== username from cookies ====", d);
// username = d.username;
// }
// send uid from client
const uid = req.body.uid;
if (!uid) {
res.status(401).send("Unauthorized");
return;
}
let username = "";
const bytes = CryptoJS.AES.decrypt(uid, secretKey);
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
username = decrypted;
// create body for admin token
let body = {
client_id: clientId,
client_secret: clientSecret,
grant_type: "client_credentials",
};
const postData = querystring.stringify(body);
// get admin token
const response = await axios.post(urlKeycloakToken, postData, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
// console.log("==== admin token ====");
const adminToken = response.data.access_token;
// console.log(adminToken);
// create body for user token
let body2 = {
client_id: clientId,
client_secret: clientSecret,
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
subject_token: adminToken,
requested_token_type: "urn:ietf:params:oauth:token-type:refresh_token",
audience: clientId,
requested_subject: username,
};
const postData2 = querystring.stringify(body2);
// get token for user
const tokenResponse = await axios.post(urlKeycloakToken, postData2, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
// console.log("==== user token ====");
// console.log(tokenResponse.data);
// await postLog('เข้าสู่ระบบ', tokenResponse.data.access_token);
// res.cookie('oldssotoken', tokenSSO, {
// maxAge: 1000 * 60 * 60 * 24, // กำหนด timeout หน่วยเป็น millisecond
// path: "/",
// httpOnly: true,
// });
res.status(200).send(tokenResponse.data);
} catch (error) {
res.status(500).send(error);
}
} else {
res.status(403).json({ error: 'Forbidden: Origin not allowed' });
}
})
console.log("Start BMA SSO Simulator at port " + port);
app.listen(port);