68 lines
1.8 KiB
TypeScript
68 lines
1.8 KiB
TypeScript
'use client';
|
|
|
|
import { exchangeCodeForTokens } from '@/lib/api/auth';
|
|
import { getOAuthClientId, getOAuthRedirectUri } from '@/lib/env';
|
|
import { takeStoredPkceVerifier } from '@/lib/oauth/browser';
|
|
import { useAuthStore } from '@/stores/auth-store';
|
|
import { useRouter, useSearchParams } from 'next/navigation';
|
|
import { Suspense, useEffect, useState } from 'react';
|
|
|
|
function CallbackInner() {
|
|
const sp = useSearchParams();
|
|
const router = useRouter();
|
|
const [msg, setMsg] = useState<string>('处理中…');
|
|
|
|
useEffect(() => {
|
|
const code = sp.get('code');
|
|
const err = sp.get('error');
|
|
if (err) {
|
|
setMsg(sp.get('error_description') || err);
|
|
return;
|
|
}
|
|
if (!code) {
|
|
setMsg('缺少授权码');
|
|
return;
|
|
}
|
|
const verifier = takeStoredPkceVerifier();
|
|
if (!verifier) {
|
|
setMsg('缺少 PKCE verifier,请从授权入口重新登录');
|
|
return;
|
|
}
|
|
(async () => {
|
|
try {
|
|
const pair = await exchangeCodeForTokens({
|
|
code,
|
|
codeVerifier: verifier,
|
|
clientId: getOAuthClientId(),
|
|
redirectUri: getOAuthRedirectUri(),
|
|
});
|
|
useAuthStore.getState().setTokens(pair.accessToken, pair.refreshToken);
|
|
setMsg('登录成功,正在跳转…');
|
|
router.replace('/dashboard');
|
|
} catch (e) {
|
|
setMsg(e instanceof Error ? e.message : String(e));
|
|
}
|
|
})();
|
|
}, [sp, router]);
|
|
|
|
return (
|
|
<main className="flex min-h-screen items-center justify-center p-6">
|
|
<p className="text-neutral-600">{msg}</p>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
export default function OAuthCallbackPage() {
|
|
return (
|
|
<Suspense
|
|
fallback={
|
|
<main className="flex min-h-screen items-center justify-center">
|
|
<p>加载中…</p>
|
|
</main>
|
|
}
|
|
>
|
|
<CallbackInner />
|
|
</Suspense>
|
|
);
|
|
}
|