fix: 为失效 OIDC 事务提供安全重试
细分回调事务、状态和授权响应错误,提供脱敏诊断编号与显式重新登录入口,避免失效事务形成重试循环。
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { OIDCCallbackNotice } from './OIDCCallbackNotice';
|
||||
|
||||
describe('OIDCCallbackNotice', () => {
|
||||
it('renders a one-click fresh login action for an invalid transaction', () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<OIDCCallbackNotice
|
||||
error={{ code: 'OIDC_LOGIN_INVALID', message: '登录事务已过期', retryable: true }}
|
||||
onRetry={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(html).toContain('登录事务已过期');
|
||||
expect(html).toContain('>重新登录</button>');
|
||||
});
|
||||
|
||||
it('does not retry non-transaction callback failures', () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<OIDCCallbackNotice
|
||||
error={{ code: 'OIDC_TOKEN_EXCHANGE_FAILED', message: '登录结果无效', retryable: false }}
|
||||
onRetry={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(html).toContain('登录结果无效');
|
||||
expect(html).not.toContain('<button');
|
||||
});
|
||||
|
||||
it('shows a safe diagnostic id without exposing callback parameters', () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<OIDCCallbackNotice
|
||||
error={{
|
||||
code: 'OIDC_LOGIN_INVALID',
|
||||
reason: 'STATE_MISMATCH',
|
||||
diagnosticId: 'diag-123',
|
||||
message: '认证回调与当前登录事务不匹配',
|
||||
retryable: true,
|
||||
}}
|
||||
onRetry={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(html).toContain('诊断编号:diag-123');
|
||||
expect(html).not.toContain('state=');
|
||||
expect(html).not.toContain('code=');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { OIDCCallbackError } from '../lib/oidc';
|
||||
import { Button } from './ui';
|
||||
|
||||
export function OIDCCallbackNotice(props: {
|
||||
error: OIDCCallbackError;
|
||||
onRetry: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="notice oidcCallbackNotice" role="alert">
|
||||
<span className="oidcCallbackMessage">
|
||||
<span>{props.error.message}</span>
|
||||
{props.error.diagnosticId && <small>诊断编号:{props.error.diagnosticId}</small>}
|
||||
</span>
|
||||
{props.error.retryable && (
|
||||
<Button type="button" variant="outline" size="sm" onClick={props.onRetry}>
|
||||
重新登录
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user