OAuth — это протокол, позволяющий вашему приложению получать доступ к данным пользователя на других сервисах без необходимости знать его логин и пароль. Вот полное руководство по настройке.
Для каждого OAuth-провайдера (Google, Facebook и др.) нужно:
Authorized JavaScript Origins
(Разрешенные источники):
http://localhost:3000 (для разработки)
https://yourdomain.com (для продакшена)
Authorized Redirect URIs
(URI перенаправления):
http://localhost:3000/auth/callback (пример)
Для React SPA рекомендуется:
// utils/auth.js
export function generateCodeVerifier() {
const array = new Uint32Array(56);
window.crypto.getRandomValues(array);
return Array.from(array, dec => ('0' + dec.toString(16)).slice(-2)).join('');
}
export async function generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await window.crypto.subtle.digest('SHA-256', data);
return btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
// OAuthButton.jsx
import { generateCodeVerifier, generateCodeChallenge } from './utils/auth';
async function handleLogin() {
const verifier = generateCodeVerifier();
localStorage.setItem('code_verifier', verifier);
const challenge = await generateCodeChallenge(verifier);
const clientId = 'YOUR_CLIENT_ID';
const redirectUri = encodeURIComponent('http://localhost:3000/callback');
const scope = encodeURIComponent('openid profile email');
window.location.href = `https://auth-provider.com/authorize?
response_type=code&
client_id=${clientId}&
redirect_uri=${redirectUri}&
scope=${scope}&
code_challenge=${challenge}&
code_challenge_method=S256`;
}
// CallbackPage.jsx
import { useEffect } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
function CallbackPage() {
const [params] = useSearchParams();
const navigate = useNavigate();
useEffect(() => {
const code = params.get('code');
if (code) exchangeCodeForToken(code);
}, []);
async function exchangeCodeForToken(code) {
const verifier = localStorage.getItem('code_verifier');
const response = await fetch('https://auth-provider.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: 'YOUR_CLIENT_ID',
grant_type: 'authorization_code',
code,
redirect_uri: 'http://localhost:3000/callback',
code_verifier: verifier,
}),
});
const { access_token } = await response.json();
await verifyTokenWithBackend(access_token);
navigate('/dashboard');
}
}
// Install: npm install @react-oauth/google
import { GoogleOAuthProvider, GoogleLogin } from '@react-oauth/google';
function GoogleAuth() {
return (
<GoogleOAuthProvider clientId="YOUR_GOOGLE_CLIENT_ID">
<GoogleLogin
onSuccess={({ credential }) => {
// Отправляем credential на ваш бэкенд для верификации
fetch('/api/auth/google', {
method: 'POST',
body: JSON.stringify({ token: credential })
});
}}
onError={() => console.error('Login Failed')}
/>
</GoogleOAuthProvider>
);
}
Ваш сервер должен:
Пример маршрута для Express.js:
app.post('/api/auth/google', async (req, res) => {
const { token } = req.body;
const client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID);
const ticket = await client.verifyIdToken({
idToken: token,
audience: process.env.GOOGLE_CLIENT_ID,
});
const payload = ticket.getPayload();
const user = await findOrCreateUser(payload);
const jwt = generateJWT(user);
res.json({ user, token: jwt });
});
Для разных провайдеров есть нюансы:
Провайдер | Особенности |
---|---|
Требует проверку домена | |
Нужно указывать версию API | |
GitHub | Позволяет ограничить доступ к организациям |
Apple | Требует специальную конфигурацию |
настройка OAuth в React требует регистрации приложения у провайдера, реализации PKCE потока для безопасности и интеграции с вашим бэкендом. Для большинства случаев можно использовать готовые библиотеки, но понимание процесса важно для сложных сценариев. Всегда проверяйте токены на сервере и соблюдайте меры безопасности.