feat: 添加JWKS管理功能,支持基于用户token创建新token

This commit is contained in:
2026-02-21 05:06:25 +08:00
parent 366a21d621
commit 77273bcfeb
11 changed files with 105 additions and 24 deletions

View File

@@ -1,7 +1,7 @@
import { useContextKey } from '@kevisual/context';
import { Redis } from 'ioredis';
import { User } from './user.ts';
import { oauth } from '../oauth/auth.ts';
import { oauth, jwksManager } from '../oauth/auth.ts';
import { OauthUser } from '../oauth/oauth.ts';
import { db } from '../../modules/db.ts';
import { cfUserSecrets, cfUser } from '../../db/drizzle/schema.ts';
@@ -53,6 +53,10 @@ export class UserSecret {
* @returns
*/
static async verifyToken(token: string) {
if (token?.includes?.('.')) {
// 先尝试作为jwt token验证如果验证成功则直接返回用户信息
return await jwksManager.verify(token);
}
if (!oauth.isSecretKey(token)) {
return await oauth.verifyToken(token);
}
@@ -62,11 +66,11 @@ export class UserSecret {
}
console.log('verifyToken: try to verify as secret key');
const userSecrets = await db.select().from(userSecretsTable).where(eq(userSecretsTable.token, token)).limit(1);
if (userSecrets.length === 0) {
return null; // 如果没有找到对应的用户密钥则返回null
}
const userSecret = new UserSecret(userSecrets[0]);
if (userSecret.isExpired()) {
return null; // 如果用户密钥已过期则返回null
@@ -97,13 +101,13 @@ export class UserSecret {
*/
static async findOne(where: { token?: string; id?: string }): Promise<UserSecret | null> {
let query = db.select().from(userSecretsTable);
if (where.token) {
query = query.where(eq(userSecretsTable.token, where.token)) as any;
} else if (where.id) {
query = query.where(eq(userSecretsTable.id, where.id)) as any;
}
const secrets = await query.limit(1);
return secrets.length > 0 ? new UserSecret(secrets[0]) : null;
}
@@ -119,12 +123,12 @@ export class UserSecret {
owner: usersTable.owner,
data: usersTable.data,
}).from(usersTable).where(eq(usersTable.id, this.userId)).limit(1);
let org: any = null;
if (users.length === 0) {
return null; // 如果没有找到对应的用户则返回null
}
const user = users[0];
const expiredTime = this.expiredTime ? new Date(this.expiredTime).getTime() : null;
const oauthUser: Partial<OauthUser> = {
@@ -142,7 +146,7 @@ export class UserSecret {
type: usersTable.type,
owner: usersTable.owner,
}).from(usersTable).where(eq(usersTable.id, this.orgId)).limit(1);
if (orgUsers.length > 0) {
org = orgUsers[0];
oauthUser.id = org.id;
@@ -164,7 +168,7 @@ export class UserSecret {
const expiredTime = new Date(this.expiredTime);
return now > expiredTime.getTime(); // 如果当前时间大于过期时间,则认为已过期
}
/**
* 检查是否过期如果过期则更新状态为expired
*
@@ -225,7 +229,7 @@ export class UserSecret {
await this.save();
return token;
}
static async createToken() {
let token = oauth.generateSecretKey();
// 确保生成的token是唯一的
@@ -234,7 +238,7 @@ export class UserSecret {
}
return token;
}
/**
* 根据 unionid 生成redis的key
* `wxmp:unionid:token:${unionid}`
@@ -244,13 +248,13 @@ export class UserSecret {
static wxRedisKey(unionid: string) {
return `wxmp:unionid:token:${unionid}`;
}
static getExpiredTime(expireDays?: number) {
const defaultExpireDays = expireDays || 365;
const expireTime = defaultExpireDays * 24 * 60 * 60 * 1000;
return new Date(Date.now() + expireTime);
}
static async createSecret(tokenUser: { id: string; uid?: string, title?: string }, expireDays = 365) {
const token = await UserSecret.createToken();
let userId = tokenUser.id;
@@ -259,18 +263,18 @@ export class UserSecret {
userId = tokenUser.uid;
orgId = tokenUser.id;
}
const insertData: Partial<typeof userSecretsTable.$inferInsert> = {
userId,
token,
title: tokenUser.title || randomString(6),
expiredTime: UserSecret.getExpiredTime(expireDays).toISOString(),
};
if (orgId !== null && orgId !== undefined) {
insertData.orgId = orgId;
}
const inserted = await db.insert(userSecretsTable).values(insertData).returning();
return new UserSecret(inserted[0]);