google sign in with oauth 2.0. no more console errors or warnings
This commit is contained in:
98
frontend/src/pages/GoogleCallback.tsx
Normal file
98
frontend/src/pages/GoogleCallback.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { fetchCSRFToken } from '../services/api';
|
||||
|
||||
const GoogleCallback: React.FC = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
const { googleLogin } = useAuth();
|
||||
const [error, setError] = useState<string>('');
|
||||
const [processing, setProcessing] = useState(true);
|
||||
const hasProcessed = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleCallback = async () => {
|
||||
// Prevent double execution in React StrictMode
|
||||
if (hasProcessed.current) {
|
||||
return;
|
||||
}
|
||||
hasProcessed.current = true;
|
||||
|
||||
try {
|
||||
const code = searchParams.get('code');
|
||||
const errorParam = searchParams.get('error');
|
||||
|
||||
if (errorParam) {
|
||||
setError('Google Sign-In was cancelled or failed. Please try again.');
|
||||
setProcessing(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
setError('No authorization code received from Google.');
|
||||
setProcessing(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch CSRF token before making auth request
|
||||
const csrfToken = await fetchCSRFToken();
|
||||
|
||||
if (!csrfToken) {
|
||||
console.error('Failed to fetch CSRF token');
|
||||
setError('Failed to initialize security token. Please try again.');
|
||||
setProcessing(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Exchange code for user session
|
||||
await googleLogin(code);
|
||||
|
||||
// Redirect to home page on success
|
||||
navigate('/', { replace: true });
|
||||
} catch (err: any) {
|
||||
console.error('Google OAuth callback error:', err);
|
||||
setError(err.response?.data?.error || 'Failed to sign in with Google. Please try again.');
|
||||
setProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
handleCallback();
|
||||
}, [searchParams, googleLogin, navigate]);
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row justify-content-center mt-5">
|
||||
<div className="col-md-6">
|
||||
<div className="card">
|
||||
<div className="card-body text-center py-5">
|
||||
{processing ? (
|
||||
<>
|
||||
<div className="spinner-border text-primary mb-3" role="status">
|
||||
<span className="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<h5>Completing Google Sign-In...</h5>
|
||||
<p className="text-muted">Please wait while we log you in.</p>
|
||||
</>
|
||||
) : error ? (
|
||||
<>
|
||||
<i className="bi bi-exclamation-circle text-danger" style={{ fontSize: '3rem' }}></i>
|
||||
<h5 className="mt-3">Sign-In Failed</h5>
|
||||
<p className="text-danger">{error}</p>
|
||||
<button
|
||||
className="btn btn-primary mt-3"
|
||||
onClick={() => navigate('/')}
|
||||
>
|
||||
Return to Home
|
||||
</button>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoogleCallback;
|
||||
Reference in New Issue
Block a user