mirror of
https://github.com/woodchen-ink/aimodels-prices.git
synced 2025-07-18 13:41:59 +08:00
Migrate Discourse SSO authentication to use Deno's native crypto and encoding modules
This commit is contained in:
parent
f4e7d16c90
commit
ec53c5ec17
16
deno.json
Normal file
16
deno.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"lib": ["deno.window"],
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"importMap": {
|
||||||
|
"imports": {
|
||||||
|
"std/": "https://deno.land/std@0.220.1/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tasks": {
|
||||||
|
"start": "deno run --allow-net --allow-env --allow-read main.ts",
|
||||||
|
"dev": "deno run --watch --allow-net --allow-env --allow-read main.ts"
|
||||||
|
}
|
||||||
|
}
|
50
main.ts
50
main.ts
@ -1,4 +1,6 @@
|
|||||||
import { serve } from "https://deno.land/std@0.220.1/http/server.ts";
|
import { serve } from "std/http/server.ts";
|
||||||
|
import { crypto } from "std/crypto/mod.ts";
|
||||||
|
import { encode as base64Encode, decode as base64Decode } from "std/encoding/base64.ts";
|
||||||
import { createHmac } from "crypto";
|
import { createHmac } from "crypto";
|
||||||
|
|
||||||
// 类型定义
|
// 类型定义
|
||||||
@ -113,12 +115,24 @@ async function verifyDiscourseSSO(request: Request): Promise<string | null> {
|
|||||||
return session.value.username;
|
return session.value.username;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加登录和登出函数
|
// 修改 generateSSO 函数为异步函数
|
||||||
function generateSSO(returnUrl: string): string {
|
async function generateSSO(returnUrl: string): Promise<string> {
|
||||||
const payload = Buffer.from(`return_sso_url=${encodeURIComponent(returnUrl)}`).toString('base64');
|
const payload = base64Encode(`return_sso_url=${encodeURIComponent(returnUrl)}`);
|
||||||
const sig = createHmac('sha256', DISCOURSE_SSO_SECRET)
|
const key = await crypto.subtle.importKey(
|
||||||
.update(payload)
|
"raw",
|
||||||
.digest('hex');
|
new TextEncoder().encode(DISCOURSE_SSO_SECRET),
|
||||||
|
{ name: "HMAC", hash: "SHA-256" },
|
||||||
|
false,
|
||||||
|
["sign"]
|
||||||
|
);
|
||||||
|
const signature = await crypto.subtle.sign(
|
||||||
|
"HMAC",
|
||||||
|
key,
|
||||||
|
new TextEncoder().encode(payload)
|
||||||
|
);
|
||||||
|
const sig = Array.from(new Uint8Array(signature))
|
||||||
|
.map(b => b.toString(16).padStart(2, '0'))
|
||||||
|
.join('');
|
||||||
return `${DISCOURSE_URL}/session/sso_provider?sso=${encodeURIComponent(payload)}&sig=${sig}`;
|
return `${DISCOURSE_URL}/session/sso_provider?sso=${encodeURIComponent(payload)}&sig=${sig}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,7 +619,7 @@ async function handler(req: Request): Promise<Response> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const ssoUrl = generateSSO(returnUrl);
|
const ssoUrl = await generateSSO(returnUrl);
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 302,
|
status: 302,
|
||||||
headers: {
|
headers: {
|
||||||
@ -633,16 +647,28 @@ async function handler(req: Request): Promise<Response> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 验证签名
|
// 验证签名
|
||||||
const expectedSig = createHmac('sha256', DISCOURSE_SSO_SECRET)
|
const key = await crypto.subtle.importKey(
|
||||||
.update(sso)
|
"raw",
|
||||||
.digest('hex');
|
new TextEncoder().encode(DISCOURSE_SSO_SECRET),
|
||||||
|
{ name: "HMAC", hash: "SHA-256" },
|
||||||
|
false,
|
||||||
|
["sign"]
|
||||||
|
);
|
||||||
|
const signature = await crypto.subtle.sign(
|
||||||
|
"HMAC",
|
||||||
|
key,
|
||||||
|
new TextEncoder().encode(sso)
|
||||||
|
);
|
||||||
|
const expectedSig = Array.from(new Uint8Array(signature))
|
||||||
|
.map(b => b.toString(16).padStart(2, '0'))
|
||||||
|
.join('');
|
||||||
|
|
||||||
if (sig !== expectedSig) {
|
if (sig !== expectedSig) {
|
||||||
throw new Error('Invalid signature');
|
throw new Error('Invalid signature');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解码 payload
|
// 解码 payload
|
||||||
const payload = Buffer.from(sso, 'base64').toString();
|
const payload = new TextDecoder().decode(base64Decode(sso));
|
||||||
const payloadParams = new URLSearchParams(payload);
|
const payloadParams = new URLSearchParams(payload);
|
||||||
const username = payloadParams.get('username');
|
const username = payloadParams.get('username');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user