Files
user-system/frontend/admin/src/pages/auth/OAuthCallbackPage/OAuthCallbackPage.tsx

108 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useMemo, useState } from 'react'
import { Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom'
import { Button, Result, Spin, Typography, message } from 'antd'
import { useAuth } from '@/app/providers/auth-context'
import { AuthLayout } from '@/layouts'
import { parseOAuthCallbackHash, sanitizeAuthRedirect } from '@/lib/auth/oauth'
import { getErrorMessage } from '@/lib/errors'
import { exchangeOAuthHandoff } from '@/services/auth'
const { Paragraph } = Typography
export function OAuthCallbackPage() {
const [status, setStatus] = useState<'loading' | 'success' | 'error'>('loading')
const [errorMessage, setErrorMessage] = useState('')
const [searchParams] = useSearchParams()
const location = useLocation()
const navigate = useNavigate()
const { onLoginSuccess } = useAuth()
const redirect = sanitizeAuthRedirect(searchParams.get('redirect'))
const callbackPayload = useMemo(() => parseOAuthCallbackHash(location.hash), [location.hash])
useEffect(() => {
let cancelled = false
const consumeHandoff = async () => {
if (callbackPayload.status === 'error') {
if (!cancelled) {
setStatus('error')
setErrorMessage(callbackPayload.message || '第三方登录失败,请重试')
}
return
}
if (!callbackPayload.code) {
if (!cancelled) {
setStatus('error')
setErrorMessage('缺少OAuth登录交接码请重新发起登录')
}
return
}
try {
const tokenBundle = await exchangeOAuthHandoff(callbackPayload.code)
await onLoginSuccess(tokenBundle)
if (!cancelled) {
setStatus('success')
message.success('第三方登录成功')
navigate(redirect, { replace: true })
}
} catch (error) {
if (!cancelled) {
setStatus('error')
setErrorMessage(getErrorMessage(error, '第三方登录失败,请重试'))
}
}
}
void consumeHandoff()
return () => {
cancelled = true
}
}, [callbackPayload.code, callbackPayload.message, callbackPayload.status, navigate, onLoginSuccess, redirect])
if (status === 'loading') {
return (
<AuthLayout>
<div style={{ textAlign: 'center', padding: '48px 0' }}>
<Spin size="large" />
<Paragraph type="secondary" style={{ marginTop: 16 }}>
...
</Paragraph>
</div>
</AuthLayout>
)
}
if (status === 'success') {
return (
<AuthLayout>
<Result
status="success"
title="登录成功"
subTitle="正在跳转到目标页面..."
/>
</AuthLayout>
)
}
return (
<AuthLayout>
<Result
status="error"
title="第三方登录失败"
subTitle={errorMessage}
extra={[
<Link key="login" to={`/login${redirect !== '/dashboard' ? `?redirect=${encodeURIComponent(redirect)}` : ''}`}>
<Button type="primary"></Button>
</Link>,
]}
/>
</AuthLayout>
)
}