feat: 更新N5代理逻辑,支持使用用户JWKS令牌进行身份验证

This commit is contained in:
2026-03-03 18:33:41 +08:00
parent 120303961c
commit bb4096ce7e
2 changed files with 29 additions and 3 deletions

View File

@@ -85,14 +85,17 @@ export class User {
/** /**
* 创建JWKS token的通用方法 * 创建JWKS token的通用方法
*/ */
private static async createJwksTokenResponse(user: { id: string; username: string }, opts: { expire?: number } = {}) { static async createJwksTokenResponse(user: { id: string; username: string }, opts: { expire?: number, save?: boolean } = {}) {
const expiresIn = opts?.expire ?? JWKS_TOKEN_EXPIRY; const expiresIn = opts?.expire ?? JWKS_TOKEN_EXPIRY;
const save = opts?.save ?? true;
const accessToken = await jwksManager.sign({ const accessToken = await jwksManager.sign({
sub: 'user:' + user.id, sub: 'user:' + user.id,
name: user.username, name: user.username,
exp: Math.floor(Date.now() / 1000) + expiresIn, exp: Math.floor(Date.now() / 1000) + expiresIn,
}); });
await oauth.setJwksToken(accessToken, { id: user.id, expire: expiresIn }); if (save) {
await oauth.setJwksToken(accessToken, { id: user.id, expire: expiresIn });
}
const token = { const token = {
accessToken, accessToken,

View File

@@ -1,4 +1,5 @@
import { convex, convexApi } from '@/app.ts'; import { convex, convexApi } from '@/app.ts';
import { User } from '@/models/user.ts';
import { IncomingMessage, ServerResponse } from 'http'; import { IncomingMessage, ServerResponse } from 'http';
type ProxyOptions = { type ProxyOptions = {
@@ -19,11 +20,33 @@ export const N5Proxy = async (req: IncomingMessage, res: ServerResponse, opts?:
opts?.createNotFoundPage?.('应用未找到'); opts?.createNotFoundPage?.('应用未找到');
return false; return false;
} }
const link = convexResult.data.link; const data = convexResult.data ?? {};
const link = data.link;
if (!link) { if (!link) {
opts?.createNotFoundPage?.('应用未找到'); opts?.createNotFoundPage?.('应用未找到');
return false; return false;
} }
if (data?.useOwnerToken) {
const userId = convexResult.userId;
if (!userId) {
opts?.createNotFoundPage?.('未绑定账号');
return false;
}
try {
const user = await User.findByPk(userId);
const token = await User.createJwksTokenResponse({ id: userId, username: user?.username || '' }, { save: false });
const urlObj = new URL(link);
urlObj.searchParams.set('token', token.accessToken);
const resultLink = await fetch(urlObj.toString(), { method: 'GET' }).then(res => res.json())
res.end(JSON.stringify(resultLink));
} catch (e) {
console.error('Error fetching the link:', e);
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Failed to fetch the link' }));
}
return true;
}
res.writeHead(302, { res.writeHead(302, {
Location: link, Location: link,
}); });