fix: 为失效 OIDC 事务提供安全重试
细分回调事务、状态和授权响应错误,提供脱敏诊断编号与显式重新登录入口,避免失效事务形成重试循环。
This commit is contained in:
@@ -2,13 +2,28 @@ const enabled = import.meta.env.VITE_OIDC_ENABLED === 'true';
|
||||
const browserSessionEnabled = import.meta.env.VITE_OIDC_BROWSER_SESSION_ENABLED !== 'false';
|
||||
const gatewayAPIBase = (import.meta.env.VITE_GATEWAY_API_BASE_URL ?? 'http://localhost:8088').replace(/\/$/, '');
|
||||
|
||||
const callbackErrors: Record<string, string> = {
|
||||
OIDC_LOGIN_INVALID: '统一认证登录事务无效或已过期,请重新登录',
|
||||
OIDC_TOKEN_EXCHANGE_FAILED: '统一认证登录结果无效,请重新登录',
|
||||
OIDC_SESSION_STORE_UNAVAILABLE: '登录会话存储暂时不可用,请稍后重试',
|
||||
GATEWAY_USER_NOT_PROVISIONED: '该账号尚未开通 EasyAI Gateway',
|
||||
GATEWAY_USER_DISABLED: '该 Gateway 账号已停用,请联系管理员',
|
||||
GATEWAY_TENANT_UNAVAILABLE: 'Gateway 租户尚未就绪,请联系管理员',
|
||||
export type OIDCCallbackError = {
|
||||
code: string;
|
||||
reason?: string;
|
||||
diagnosticId?: string;
|
||||
message: string;
|
||||
retryable: boolean;
|
||||
};
|
||||
|
||||
const callbackErrors: Record<string, Omit<OIDCCallbackError, 'code'>> = {
|
||||
OIDC_LOGIN_INVALID: { message: '统一认证登录事务无效或已过期,请重新登录', retryable: true },
|
||||
OIDC_TOKEN_EXCHANGE_FAILED: { message: '统一认证登录结果无效,请重新登录', retryable: false },
|
||||
OIDC_SESSION_STORE_UNAVAILABLE: { message: '登录会话存储暂时不可用,请稍后重试', retryable: false },
|
||||
GATEWAY_USER_NOT_PROVISIONED: { message: '该账号尚未开通 EasyAI Gateway', retryable: false },
|
||||
GATEWAY_USER_DISABLED: { message: '该 Gateway 账号已停用,请联系管理员', retryable: false },
|
||||
GATEWAY_TENANT_UNAVAILABLE: { message: 'Gateway 租户尚未就绪,请联系管理员', retryable: false },
|
||||
};
|
||||
|
||||
const loginTransactionFailureMessages: Record<string, string> = {
|
||||
COOKIE_MISSING: '浏览器未携带统一认证登录事务 Cookie,请允许 localhost Cookie 后重新登录',
|
||||
TRANSACTION_INVALID: '统一认证登录事务无法验证或已过期,请重新登录',
|
||||
STATE_MISMATCH: '认证回调与当前登录事务不匹配,请关闭重复登录页面后重新登录',
|
||||
AUTHORIZATION_RESPONSE_MISSING: '认证中心回调缺少必要参数,请重新登录',
|
||||
};
|
||||
|
||||
export function oidcLoginEnabled() {
|
||||
@@ -41,9 +56,22 @@ export async function startOIDCLogout() {
|
||||
export function consumeOIDCCallbackError() {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const code = params.get('oidcError') ?? '';
|
||||
if (!code) return '';
|
||||
if (!code) return null;
|
||||
const rawReason = params.get('oidcErrorReason') ?? '';
|
||||
const reason = code === 'OIDC_LOGIN_INVALID' && loginTransactionFailureMessages[rawReason] ? rawReason : '';
|
||||
const rawDiagnosticId = params.get('oidcDiagnosticId') ?? '';
|
||||
const diagnosticId = /^[A-Za-z0-9_-]{6,64}$/.test(rawDiagnosticId) ? rawDiagnosticId : '';
|
||||
params.delete('oidcError');
|
||||
params.delete('oidcErrorReason');
|
||||
params.delete('oidcDiagnosticId');
|
||||
const query = params.toString();
|
||||
window.history.replaceState({}, '', `${window.location.pathname}${query ? `?${query}` : ''}${window.location.hash}`);
|
||||
return callbackErrors[code] ?? '统一认证登录失败,请重试';
|
||||
const callbackError = callbackErrors[code] ?? { message: '统一认证登录失败,请重试', retryable: false };
|
||||
return {
|
||||
code,
|
||||
...(reason ? { reason } : {}),
|
||||
...(diagnosticId ? { diagnosticId } : {}),
|
||||
...callbackError,
|
||||
...(reason ? { message: loginTransactionFailureMessages[reason] } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user