casualroom/apps/fenghuo/web/lib/auth/token-manager.ts

116 lines
3.4 KiB
TypeScript
Raw Normal View History

2025-07-28 07:50:50 +08:00
// apps/web/lib/token-manager.ts
interface TokenData {
access_token: string;
refresh_token?: string;
expires_at: number;
token_type: string;
}
export class TokenManager {
private static readonly ACCESS_TOKEN_KEY = 'oidc_access_token';
private static readonly REFRESH_TOKEN_KEY = 'oidc_refresh_token';
private static readonly EXPIRES_AT_KEY = 'oidc_expires_at';
private static readonly TOKEN_TYPE_KEY = 'oidc_token_type';
/**
*
*/
static saveTokens(tokenResponse: {
access_token: string;
refresh_token?: string;
expires_in: number;
token_type: string;
}): void {
const expiresAt = Date.now() + (tokenResponse.expires_in * 1000);
localStorage.setItem(this.ACCESS_TOKEN_KEY, tokenResponse.access_token);
localStorage.setItem(this.EXPIRES_AT_KEY, expiresAt.toString());
localStorage.setItem(this.TOKEN_TYPE_KEY, tokenResponse.token_type);
if (tokenResponse.refresh_token) {
localStorage.setItem(this.REFRESH_TOKEN_KEY, tokenResponse.refresh_token);
}
}
/**
* 访
*/
static getAccessToken(): string | null {
return localStorage.getItem(this.ACCESS_TOKEN_KEY);
}
/**
*
*/
static getRefreshToken(): string | null {
return localStorage.getItem(this.REFRESH_TOKEN_KEY);
}
/**
*
*/
static isTokenExpired(): boolean {
const expiresAt = localStorage.getItem(this.EXPIRES_AT_KEY);
if (!expiresAt) return true;
return Date.now() >= parseInt(expiresAt);
}
/**
* 访
*/
static async getValidAccessToken(): Promise<string | null> {
const accessToken = this.getAccessToken();
if (!accessToken) return null;
if (!this.isTokenExpired()) {
return accessToken;
}
// 尝试刷新令牌
const refreshToken = this.getRefreshToken();
if (refreshToken) {
try {
const { oidcClient } = await import('./oidc-client');
const newTokens = await oidcClient.refreshToken(refreshToken);
this.saveTokens(newTokens);
return newTokens.access_token;
} catch (error) {
console.error('刷新令牌失败:', error);
this.clearTokens();
return null;
}
}
return null;
}
/**
*
*/
static clearTokens(): void {
localStorage.removeItem(this.ACCESS_TOKEN_KEY);
localStorage.removeItem(this.REFRESH_TOKEN_KEY);
localStorage.removeItem(this.EXPIRES_AT_KEY);
localStorage.removeItem(this.TOKEN_TYPE_KEY);
}
/**
*
*/
static getTokenData(): TokenData | null {
const accessToken = this.getAccessToken();
if (!accessToken) return null;
const refreshToken = this.getRefreshToken();
const expiresAt = localStorage.getItem(this.EXPIRES_AT_KEY);
const tokenType = localStorage.getItem(this.TOKEN_TYPE_KEY) || 'Bearer';
return {
access_token: accessToken,
refresh_token: refreshToken || undefined,
expires_at: expiresAt ? parseInt(expiresAt) : 0,
token_type: tokenType,
};
}
}