Vite React django5 allauth jwt google loginJavascript

Форум по Javascript
Ответить
Anonymous
 Vite React django5 allauth jwt google login

Сообщение Anonymous »

Похоже, что мой код входа в Google работает, но перенаправляет обратно на домашнюю страницу. Токен доступа и обновления находится в приложении браузера, но он по -прежнему не будет перенаправляться обратно на домашнюю страницу, он продолжает ходить на страницу входа в систему. Но если я введу URL -адрес домашней страницы непосредственно, он показывает аутентификацию. Google отправляет код и токен, и это заменяется на токены jwt < /p>
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import axios from "axios";
import Cookies from 'js-cookie'; // Import js-cookie

const GoogleCallback = () => {
    const navigate = useNavigate();

    useEffect(() => {
        const handleCallback = async () => {
            try {
                await axios.get(
                    "http://localhost:8000/api/google/callback/" + window.location.search,
                    { withCredentials: true } // Ensure cookies are sent & received
                );

                // Check for both tokens using js-cookie with domain and path
                const accessToken = Cookies.get('access_token', { domain: '127.0.0.1', path: '/' });
                const refreshToken = Cookies.get('refresh_token', { domain: '127.0.0.1', path: '/' });

                if (accessToken && refreshToken) {
                    navigate("/");
                } else {
                    console.warn("Access token or refresh token not found in cookies under 127.0.0.1:5173");
                    navigate("/login");
                }

            } catch (error) {
                console.error("Google login failed", error);
                navigate("/login");
            }
        };

        handleCallback();
    }, [navigate]);

    return Logging in...;
};

export default GoogleCallback;
< /code>
from django.shortcuts import redirect
from django.http import JsonResponse
import requests
from django.conf import settings
from django.contrib.auth import get_user_model
from allauth.socialaccount.models import SocialAccount, SocialToken
from rest_framework_simplejwt.tokens import RefreshToken
from datetime import timedelta
from django.utils.timezone import now
from django.core.exceptions import ObjectDoesNotExist

User = get_user_model()

def google_login(request):
"""Redirects the user to Google's OAuth 2.0 authentication page."""
google_oauth_url = (
"https://accounts.google.com/o/oauth2/auth"
"?response_type=code"
f"&client_id={settings.SOCIAL_AUTH_GOOGLE_CLIENT_ID}"
f"&redirect_uri={settings.SOCIAL_AUTH_GOOGLE_REDIRECT_URI}"
"&scope=email%20profile%20openid"
"&access_type=offline"
"&prompt=consent"
)
return redirect(google_oauth_url)

def google_login_callback(request):
"""Handles OAuth callback, exchanges code for Google tokens, and generates JWTs."""
code = request.GET.get('code')

if not code:
return JsonResponse({'error': 'Missing authorization code'}, status=400)

# Exchange code for access & refresh tokens
token_url = "https://oauth2.googleapis.com/token"
data = {
'code': code,
'client_id': settings.SOCIAL_AUTH_GOOGLE_CLIENT_ID,
'client_secret': settings.SOCIAL_AUTH_GOOGLE_SECRET,
'redirect_uri': settings.SOCIAL_AUTH_GOOGLE_REDIRECT_URI,
'grant_type': 'authorization_code',
}
response = requests.post(token_url, data=data)
token_data = response.json()

if 'error' in token_data:
return JsonResponse({'error': 'Failed to fetch tokens', 'details': token_data}, status=400)

access_token = token_data.get('access_token')
refresh_token = token_data.get('refresh_token')
id_token = token_data.get('id_token')

# Fetch user info from Google
user_info_url = "https://www.googleapis.com/oauth2/v2/userinfo"
headers = {'Authorization': f'Bearer {access_token}'}
user_info_response = requests.get(user_info_url, headers=headers)
user_info = user_info_response.json()

if 'email' not in user_info:
return JsonResponse({'error': 'Google authentication failed'}, status=400)

email = user_info['email']

# Check if user exists, create if not
user, created = User.objects.get_or_create(username=email, defaults={'email': email})

# Store Google tokens in SocialToken model
try:
social_account = SocialAccount.objects.get(user=user, provider='google')
except ObjectDoesNotExist:
social_account = SocialAccount.objects.create(user=user, provider='google', extra_data=user_info)

social_token, _ = SocialToken.objects.update_or_create(
account=social_account,
defaults={'token': access_token, 'token_secret': refresh_token, 'expires_at': now() + timedelta(seconds=token_data.get("expires_in", 3600))}
)

# Generate JWT tokens
refresh = RefreshToken.for_user(user)
access = refresh.access_token

# Set JWT tokens as secure HTTP-only cookies
response = JsonResponse({'message': 'Login successful'})
response.set_cookie('access_token', str(access), httponly=True, secure=True, samesite='Lax')
response.set_cookie('refresh_token', str(refresh), httponly=True, secure=True, samesite='Lax')

return response

def refresh_google_token(user):
"""Refreshes the user's Google OAuth token if expired."""
try:
social_account = SocialAccount.objects.get(user=user, provider='google')
social_token = SocialToken.objects.get(account=social_account)

if social_token.expires_at and social_token.expires_at < now():
token_url = "https://oauth2.googleapis.com/token"
data = {
'client_id': settings.SOCIAL_AUTH_GOOGLE_CLIENT_ID,
'client_secret': settings.SOCIAL_AUTH_GOOGLE_SECRET,
'refresh_token': social_token.token_secret,
'grant_type': 'refresh_token',
}
response = requests.post(token_url, data=data)
new_token_data = response.json()

if 'access_token' in new_token_data:
social_token.token = new_token_data['access_token']
social_token.expires_at = now() + timedelta(seconds=new_token_data.get("expires_in", 3600))
social_token.save()
return new_token_data['access_token']
else:
return None
return social_token.token
except ObjectDoesNotExist:
return None
from rest_framework_simplejwt.tokens import AccessToken

def verify_user(request):
"""Verifies the user's authentication using JWT stored in cookies."""
access_token = request.COOKIES.get("access_token")

if not access_token:
return JsonResponse({'authenticated': False, 'error': 'No access token'}, status=401)

try:
payload = AccessToken(access_token)
user = User.objects.get(id=payload['user_id'])
return JsonResponse({'authenticated': True, 'email': user.email})
except Exception:
return JsonResponse({'authenticated': False, 'error': 'Invalid or expired token'}, status=401)
< /code>
import { useEffect, useState } from "react";
import { verifyUser, refreshGoogleToken } from "./api";
import { useNavigate } from "react-router-dom";

const Home = () => {
const [user, setUser] = useState(null);
const navigate = useNavigate();

useEffect(() => {
const checkUser = async () => {
const data = await verifyUser();
if (data.authenticated) {
setUser(data);
} else {
console.warn("User verification failed:", data.error);
navigate("/login"); // Redirect immediately if not authenticated - Removed setTimeout delay
}
};

checkUser();
}, [navigate]);

return (

{user ? (

Welcome, {user.email}

) : (
Loading...
)}

);
};

export default Home;
< /code>
Изображение


Подробнее здесь: https://stackoverflow.com/questions/794 ... ogle-login
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»