Files
cameleer-saas/ui/src/auth/CallbackPage.tsx

59 lines
1.6 KiB
TypeScript
Raw Normal View History

import { useEffect } from 'react';
import { useNavigate } from 'react-router';
import { useAuthStore } from './auth-store';
import { Spinner } from '@cameleer/design-system';
import { fetchConfig } from '../config';
import { getCodeVerifier } from './pkce';
export function CallbackPage() {
const navigate = useNavigate();
const login = useAuthStore((s) => s.login);
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const code = params.get('code');
if (!code) {
navigate('/login');
return;
}
const codeVerifier = getCodeVerifier();
if (!codeVerifier) {
navigate('/login');
return;
}
const redirectUri = `${window.location.origin}/callback`;
fetchConfig().then((config) => {
fetch(`${config.logtoEndpoint}/oidc/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code,
client_id: config.logtoClientId,
redirect_uri: redirectUri,
code_verifier: codeVerifier,
}),
})
.then((r) => r.json())
.then((data) => {
if (data.access_token) {
login(data.access_token, data.refresh_token || '');
navigate('/');
} else {
navigate('/login');
}
})
.catch(() => navigate('/login'));
});
}, [login, navigate]);
return (
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh' }}>
<Spinner />
</div>
);
}