Use dynamic redirectUri

This commit is contained in:
2025-10-19 02:33:44 +08:00
parent f038ca8e79
commit 99d49dbc10
3 changed files with 60 additions and 12 deletions

View File

@@ -10,7 +10,6 @@ services:
- OIDC_WELL_KNOWN_URL=
- CLIENT_ID=
- CLIENT_SECRET=
- REDIRECT_URI=http://127.0.0.1:3000/callback
- COOKIE_SECRET=
network_mode: host
restart: always

View File

@@ -8,11 +8,9 @@ require("dotenv").config();
const PORT = process.env.PORT || 3000;
const COMPUTER_NAME = process.env.COMPUTER_NAME || "MyComputer";
const REDIRECT_URI =
process.env.REDIRECT_URI || "http://127.0.0.1:3000/callback";
const app = express();
app.use(express.json());
app.use(
session({
secret: process.env.COOKIE_SECRET,
@@ -32,7 +30,6 @@ let client;
client = new issuer.Client({
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uris: [REDIRECT_URI],
response_types: ["code"],
});
@@ -49,18 +46,39 @@ let client;
}
});
app.get("/login", (req, res) => {
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: REDIRECT_URI,
redirect_uri: redirectUri,
state,
});
res.redirect(url);
// 回傳 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(REDIRECT_URI, params);
const tokenSet = await client.callback(redirectUri, params, { state });
const userinfo = await client.userinfo(tokenSet.access_token);
req.session.user = userinfo;

View File

@@ -1,20 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>登入 | 喚醒 {{COMPUTER_NAME}}</title>
<style>
body {
font-family: sans-serif; padding: 1.5rem; font-size: 1.2rem;
font-family: sans-serif;
padding: 1.5rem;
font-size: 1.2rem;
}
a, button {
a,
button {
font-size: 1.1rem;
}
</style>
</head>
<body>
<h1>喚醒 {{COMPUTER_NAME}}</h1>
<a href="/login">點此登入</a>
<button id="loginBtn">登入</button>
<script>
document.getElementById('loginBtn').addEventListener('click', async function () {
const redirectUri = window.location.origin + '/callback';
try {
const res = await fetch('/authorize', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ redirectUri })
});
if (!res.ok) {
alert('伺服器錯誤');
return;
}
const data = await res.json();
if (data && data.redirect) {
window.location.href = data.redirect;
}
} catch (err) {
alert('請求失敗: ' + err);
}
});
</script>
</body>
</html>