115 lines
2.8 KiB
JavaScript
Executable File
115 lines
2.8 KiB
JavaScript
Executable File
const express = require("express");
|
|
const session = require("express-session");
|
|
const { Issuer } = require("openid-client");
|
|
const wol = require("wake_on_lan");
|
|
const { createTemplateRenderer } = require("./utils/templates.jsm");
|
|
|
|
require("dotenv").config();
|
|
|
|
const PORT = process.env.PORT || 3000;
|
|
const COMPUTER_NAME = process.env.COMPUTER_NAME || "MyComputer";
|
|
|
|
const app = express();
|
|
app.use(express.json());
|
|
app.use(
|
|
session({
|
|
secret: process.env.COOKIE_SECRET,
|
|
saveUninitialized: false,
|
|
cookie: { maxAge: 10 * 60 * 1000 },
|
|
})
|
|
);
|
|
|
|
const renderHtml = createTemplateRenderer({
|
|
useCache: process.env.NODE_ENV === "production",
|
|
});
|
|
|
|
let client;
|
|
|
|
(async () => {
|
|
const issuer = await Issuer.discover(process.env.OIDC_WELL_KNOWN_URL);
|
|
client = new issuer.Client({
|
|
client_id: process.env.CLIENT_ID,
|
|
client_secret: process.env.CLIENT_SECRET,
|
|
response_types: ["code"],
|
|
});
|
|
|
|
app.get("/", (req, res) => {
|
|
if (req.session.user) {
|
|
res.send(
|
|
renderHtml("index.html", {
|
|
COMPUTER_NAME,
|
|
USERNAME: req.session.user.sub,
|
|
})
|
|
);
|
|
} else {
|
|
res.send(renderHtml("login.html", { COMPUTER_NAME }));
|
|
}
|
|
});
|
|
|
|
const stateMap = {};
|
|
|
|
app.post("/authorize", (req, res) => {
|
|
const { redirectUri } = req.body;
|
|
if (!redirectUri) {
|
|
return res.send(
|
|
renderHtml("login-fail.html", {
|
|
COMPUTER_NAME,
|
|
ERROR: "redirectUri missing or invalid",
|
|
})
|
|
);
|
|
}
|
|
|
|
const state = Math.random().toString(36).substring(2);
|
|
stateMap[state] = { redirectUri };
|
|
|
|
const url = client.authorizationUrl({
|
|
scope: "openid profile",
|
|
redirect_uri: redirectUri,
|
|
state,
|
|
});
|
|
|
|
// 回傳 JSON 給前端,讓前端負責導向
|
|
res.json({ redirect: url });
|
|
});
|
|
|
|
app.get("/callback", async (req, res) => {
|
|
try {
|
|
const state = req.query.state;
|
|
const { redirectUri } = stateMap[state];
|
|
|
|
const params = client.callbackParams(req);
|
|
const tokenSet = await client.callback(redirectUri, params, { state });
|
|
const userinfo = await client.userinfo(tokenSet.access_token);
|
|
|
|
req.session.user = userinfo;
|
|
res.redirect("/");
|
|
} catch (error) {
|
|
res.send(renderHtml("login-fail.html", { COMPUTER_NAME, ERROR: error }));
|
|
}
|
|
});
|
|
|
|
app.get("/wakeup", (req, res) => {
|
|
if (!req.session.user) return res.redirect("/");
|
|
|
|
wol.wake(process.env.MAC_ADDRESS, (error) => {
|
|
if (error) {
|
|
res.send(
|
|
renderHtml("wakeup-fail.html", { COMPUTER_NAME, ERROR: error })
|
|
);
|
|
} else {
|
|
res.send(renderHtml("wakeup-success.html", { COMPUTER_NAME }));
|
|
}
|
|
});
|
|
});
|
|
|
|
app.post("/logout", (req, res) => {
|
|
req.session.destroy(() => {
|
|
res.redirect("/");
|
|
});
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`wakeup3770 listening at http://localhost:${PORT}`);
|
|
});
|
|
})();
|