Я реализовал Google oauth2 вход в Django (с pkce ) с django oauth toolkit .
После входа в систему сервер создает Access_token (в образе ответов) и represh_token , который storted in htton> htston> htston> ht in ht in ht in htston cookie :
@api_view(["POST"])
def google_login(request):
code = request.data.get("code")
if code:
code = unquote(code)
code_verifier = request.data.get("code_verifier")
if not code or not code_verifier:
return Response({"error": "Missing code or code_verifier"}, status=400)
# Google token exchange
token_resp = requests.post("https://oauth2.googleapis.com/token", data={
"client_id": GOOGLE_CLIENT_ID,
"client_secret": GOOGLE_CLIENT_SECRET,
"code": code,
"code_verifier": code_verifier,
"grant_type": "authorization_code",
"redirect_uri": REDIRECT_URI,
}).json()
if "error" in token_resp:
return Response({"error": "Google exchange failed",
"details": token_resp}, status=400)
access_token = token_resp.get("access_token")
# Retrieving and storing user information
userinfo = requests.get("https://openidconnect.googleapis.com/v1/userinfo",
headers={"Authorization": f"Bearer {access_token}"}).json()
email = userinfo.get("email")
if not email:
return Response({"error": "No email returned by Google",
"userinfo": userinfo}, status=400)
user, _ = User.objects.get_or_create(email=email, defaults={
"username": email,
"first_name": userinfo.get("given_name", ""),
"last_name": userinfo.get("family_name", ""),
"avatar": userinfo.get("picture", ""),
})
assign_user_role(user)
# token generation
app = Application.objects.get(name="React SPA")
expires = timezone.now() + timedelta(seconds=oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS)
access_token_obj = AccessToken.objects.create(
user=user,
application=app,
token=generate_token(),
expires=expires,
scope="read write"
)
refresh_token_obj = RefreshToken.objects.create(
user=user,
token=generate_token(),
application=app,
access_token=access_token_obj
)
response = Response({
"access_token": access_token_obj.token,
"expires_in": oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS,
"token_type": "Bearer"
})
response.set_cookie(
"refresh_token",
refresh_token_obj.token,
httponly=True,
secure=False, # True on prod
samesite="Lax",
path="/",
)
return response
< /code>
Я также реализовал пользовательскую конечную точку токена (CustomTokenView), которая поддерживает обновление по cookie (а не через корпус запроса), то есть: < /p>
@method_decorator(csrf_exempt, name='dispatch')
class CustomTokenView(OAuthLibMixin, APIView):
def post(self, request, *args, **kwargs):
if request.data.get("grant_type") == "refresh_token":
refresh_token_cookie = request.COOKIES.get("refresh_token")
if refresh_token_cookie:
post = request._request.POST.copy()
post["refresh_token"] = refresh_token_cookie
request._request.POST = post
url, headers, body, status = self.create_token_response(request._request)
token_data = json.loads(body)
if status == 200:
access_token = token_data.get("access_token")
refresh_token = token_data.get("refresh_token")
if access_token:
token_checksum = hashlib.sha256(access_token.encode("utf-8")).hexdigest()
token = get_access_token_model().objects.get(token_checksum=token_checksum)
app_authorized.send(sender=self, request=request, token=token)
response_data = {
"access_token": access_token,
"expires_in": token_data.get("expires_in", oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS),
"token_type": token_data.get("token_type", "Bearer"),
}
response = Response(response_data, status=status)
if refresh_token:
response.set_cookie(
"refresh_token",
refresh_token,
httponly=True,
secure=False, # Local
samesite="Lax",
path="/",
)
return response
return HttpResponse(content=body, status=status, headers=headers)
< /code>
Мои Urls: < /p>
v1_patterns = [
...
path('auth/authorize/', oauth2_views.AuthorizationView.as_view(), name="authorize"),
path('auth/token/', CustomTokenView.as_view(), name="token"),
path("auth/google/", google_login, name='google_login'),
]
urlpatterns = [
...
path("api/v1/", include(v1_patterns)),
]
< /code>
[b] Проблема: < /strong>
В почтальнице, cookie represh_token установлен без каких -либо проблем. http://127.0.0.1:5173) [/b] я делаю [b] post [/b] в Backend [b] (http://127.0.0.1:8000/api/v1/auth/google/) [/b]
await fetch("http://127.0.0.1:8000/api/v1/auth/google/", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ code, code_verifier }),
});
cors в настройках :
CORS_ALLOWED_ORIGINS = [
"http://127.0.0.1:5173",
]
CORS_ALLOW_CREDENTIALS = True
< /code>
Итак, мой вопрос < /strong>:
Почему браузер не сохраняет файл cookie rupresh_token после запроса, хотя он и в почтальце? Игнорировать Set-cookie?>
Я реализовал [b] Google oauth2 [/b] вход в Django (с [b] pkce [/b]) с [b] django oauth toolkit [/b]. После входа в систему сервер создает Access_token (в образе ответов) и represh_token , который storted in [b] htton> htston> htston> ht in ht in ht in htston cookie [/b]: [code]@api_view(["POST"]) def google_login(request): code = request.data.get("code") if code: code = unquote(code) code_verifier = request.data.get("code_verifier")
if not code or not code_verifier: return Response({"error": "Missing code or code_verifier"}, status=400)
if "error" in token_resp: return Response({"error": "Google exchange failed", "details": token_resp}, status=400)
access_token = token_resp.get("access_token")
# Retrieving and storing user information userinfo = requests.get("https://openidconnect.googleapis.com/v1/userinfo", headers={"Authorization": f"Bearer {access_token}"}).json()
email = userinfo.get("email") if not email: return Response({"error": "No email returned by Google", "userinfo": userinfo}, status=400)
return response < /code> Я также реализовал пользовательскую конечную точку токена (CustomTokenView), которая поддерживает обновление по cookie (а не через корпус запроса), то есть: < /p> @method_decorator(csrf_exempt, name='dispatch') class CustomTokenView(OAuthLibMixin, APIView): def post(self, request, *args, **kwargs): if request.data.get("grant_type") == "refresh_token": refresh_token_cookie = request.COOKIES.get("refresh_token") if refresh_token_cookie: post = request._request.POST.copy() post["refresh_token"] = refresh_token_cookie request._request.POST = post
url, headers, body, status = self.create_token_response(request._request)
token_data = json.loads(body)
if status == 200: access_token = token_data.get("access_token") refresh_token = token_data.get("refresh_token")
My Nodejs Backend устанавливает этот файл cookie:
res.cookie( refresh_token , refresh_token, {
httpOnly: true,
secure: true, // must be true when sameSite: None ,
sameSite: None ,
maxAge: 1000000, // maxAge is in milliseconds
});
Я использую django с drf_social_oauth2 и oauth2_provider для аутентификации Google OAuth2. Я успешно реализовал поток авторизации pkce . GET /api/v1/o/authorize/?client_id=&response_type=code&redirect_uri=
step 2 : Frontend Bearge Code по адресу:...
Я пытаюсь использовать Sanctum для приложения только API. Я не использую его для спа. У меня есть одна конечная точка, настроенная и защищенная промежуточным программным обеспечением Sanctum. Я создаю пользователя и токен для указанного пользователя...
Я пытаюсь аутентифицировать пользователя из Blazor, чтобы получить доступ к ресурсам в основном веб -API ASP.NET с использованием идентификации основной идентификации ASP.NET.
У меня есть два метода аутентификации: JWT и файлы cookie.
Когда я...