diff --git a/package.json b/package.json index a5cb599..f8c24db 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "axios": "^1.7.2", "cookie-parser": "^1.4.6", + "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", "http-proxy-middleware": "^3.0.0", diff --git a/sso.js b/sso.js index 0f4f914..f0a2127 100644 --- a/sso.js +++ b/sso.js @@ -2,10 +2,12 @@ //cookie with token is the final product of SSO 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 { createProxyMiddleware } = require("http-proxy-middleware"); -// const path = require("path"); +const cors = require('cors'); const jwt = require("jsonwebtoken"); const fs = require("fs"); const axios = require("axios"); @@ -20,15 +22,20 @@ const signOptions = { algorithm: "RS256", }; +const urlKeycloakToken = `${process.env.KC_URL}/realms/${process.env.KC_REALMS}/protocol/openid-connect/token`; + const app = express(); +app.use(cors({ + origin: 'http://localhost:3002', // Your Vue app's origin + credentials: true, +})); +app.use(express.urlencoded({ extended: true })); app.use(express.json()); +app.use(cookieParser()); app.post("/signin", async (req, res) => { try { const login_user = req.body; - const urlKeycloakToken = `${process.env.KC_URL}/realms/${process.env.KC_REALMS}/protocol/openid-connect/token`; - console.log("urlKeycloakToken===>", urlKeycloakToken); - const formdata = new URLSearchParams(); formdata.append("grant_type", "password"); @@ -36,7 +43,7 @@ app.post("/signin", async (req, res) => { formdata.append("username", login_user.username); formdata.append("password", login_user.password); - console.log("formdata===>", formdata); + // console.log("formdata===>", formdata); const response = await axios.post(urlKeycloakToken, formdata, { headers: { @@ -45,18 +52,13 @@ app.post("/signin", async (req, res) => { }); if (response.data) { - console.log("response===>", response.data); - const payload = { username: login_user.username }; let token = jwt.sign(payload, privateKey, signOptions); - console.log("token===>", token); - console.log("cookieName===>", cookieName); - res.cookie(cookieName, token, { maxAge: 1000 * 60 * 60 * 24, // กำหนด timeout หน่วยเป็น millisecond path: "/", - httpOnly: false, + httpOnly: true, }); res.sendStatus(200); @@ -64,10 +66,86 @@ app.post("/signin", async (req, res) => { res.status(401).send("Incorrect user or password"); } } catch (error) { - res.status(500).send("Incorrect user or password"); + res.status(500).send("Incorrect user or password!"); } }); +// kcauth +const useBMA = Boolean(process.env.USE_BMA) || false; +const publicKeyLanding = fs.readFileSync(`${process.cwd()}/BMA.pub.pem`, "utf8"); +const clientSecret = process.env.KC_CLIENT_SECRET; +const clientId = process.env.KC_CLIENT_ID; + +app.post("/kcauth", async (req, res) => { + try { + const cookies = req.cookies; + const tokenSSO = cookies[cookieName]; + + 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); + const username = d.username; + + // 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); + // console.log("==== postData2 ===="); + // console.log(body2); + + // get admin token + 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.status(200).send(tokenResponse.data); + + } catch (error) { + // console.log("error===>", error); + + res.status(401).send(error); + } +}) + // app.use(express.static(path.join(__dirname, "public-sso"))); // app.get("/", (_req, res) => {