feat: 更新JWKS token创建逻辑,支持refresh token选项

This commit is contained in:
2026-03-03 19:10:57 +08:00
parent bb4096ce7e
commit d2913dd32d
3 changed files with 24 additions and 14 deletions

View File

@@ -46,6 +46,7 @@ type TokenOptions = {
host?: string; // 主机信息
wx?: any;
loginWith?: string; // 登录方式,如 'cli', 'web', 'plugin' 等
hasRefreshToken?: boolean; // 是否需要 refresh token默认为 false
}
/**
* 用户模型,使用 Drizzle ORM
@@ -85,15 +86,15 @@ export class User {
/**
* 创建JWKS token的通用方法
*/
static async createJwksTokenResponse(user: { id: string; username: string }, opts: { expire?: number, save?: boolean } = {}) {
static async createJwksTokenResponse(user: { id: string; username: string }, opts: { expire?: number, hasRefreshToken?: boolean } = {}) {
const expiresIn = opts?.expire ?? JWKS_TOKEN_EXPIRY;
const save = opts?.save ?? true;
const hasRefreshToken = opts?.hasRefreshToken ?? true;
const accessToken = await jwksManager.sign({
sub: 'user:' + user.id,
name: user.username,
exp: Math.floor(Date.now() / 1000) + expiresIn,
});
if (save) {
if (hasRefreshToken) {
await oauth.setJwksToken(accessToken, { id: user.id, expire: expiresIn });
}
@@ -113,6 +114,7 @@ export class User {
async createToken(uid?: string, loginType?: 'default' | 'plugin' | 'month' | 'season' | 'year' | 'week' | 'jwks', opts: TokenOptions = {}) {
const { id, username, type } = this;
const hasRefreshToken = opts.hasRefreshToken ?? true;
const oauthUser: OauthUser = {
id,
username,
@@ -126,7 +128,7 @@ export class User {
if (loginType === 'jwks') {
return await User.createJwksTokenResponse(this, opts);
}
const token = await oauth.generateToken(oauthUser, { type: loginType, hasRefreshToken: true, ...opts });
const token = await oauth.generateToken(oauthUser, { type: loginType, hasRefreshToken, ...opts });
return {
type: 'default',
...token,
@@ -140,6 +142,17 @@ export class User {
static async verifyToken(token: string) {
return await UserSecret.verifyToken(token);
}
static async checkJwksValid(token: string) {
const verified = await User.verifyToken(token);
let isValid = false;
if (verified) {
isValid = true;
}
const jwksToken = await oauth.getJwksToken(token);
if (!isValid && !jwksToken) {
throw new CustomError('Invalid refresh token');
}
}
/**
* 刷新token
* @param refreshToken
@@ -150,10 +163,7 @@ export class User {
let jwsRefreshToken = accessToken || refreshToken;
if (oauth.getTokenType(jwsRefreshToken) === 'jwks') {
// 可能是 jwks token
const jwksToken = await oauth.getJwksToken(jwsRefreshToken);
if (!jwksToken) {
throw new CustomError('Invalid refresh token');
}
await User.checkJwksValid(jwsRefreshToken);
const decoded = await jwksManager.decode(jwsRefreshToken);
return await User.createJwksTokenResponse({
id: decoded.sub.replace('user:', ''),
@@ -212,10 +222,7 @@ export class User {
static async resetToken(refreshToken: string, expand?: Record<string, any>) {
if (oauth.getTokenType(refreshToken) === 'jwks') {
// 可能是 jwks token
const jwksToken = await oauth.getJwksToken(refreshToken);
if (!jwksToken) {
throw new CustomError('Invalid refresh token');
}
await User.checkJwksValid(refreshToken);
const decoded = await jwksManager.decode(refreshToken);
return await User.createJwksTokenResponse({
id: decoded.sub.replace('user:', ''),