前提・実現したいこと
現在フロントとバックエンドのサーバーを分けてWebアプリを作成しています
既にデプロイ済みです
○バックエンド○
・Django + Heroku
○フロントエンド○
・Next.js + Vercel
Herokuは無料のものを使っています
よろしくお願いします
発生している問題・エラーメッセージ
ログイン時に返ってきたクッキーをブラウザにセットしたいです
実際はsetCookie属性が付いたレスポンスが返ってきているにもかかわらずブラウザにCookieがセットされていません
ログイン時のログ(一部)
Heroku
12021-07-16T10:03:08.590609+00:00 heroku[router]: at=info method=POST path="/api/v1/token-refresh/" host=www.tyoitasi.com request_id=26c4d377-4507-44df-a041-9b5aa88b4442 fwd="2400:4052:e20:2f00:50b:f8fb:bd08:3843,172.68.118.61" dyno=web.1 connect=2ms service=5031ms status=500 bytes=107800 protocol=https 22021-07-16T10:03:10.314311+00:00 heroku[router]: at=info method=POST path="/api/v1/login/" host=www.tyoitasi.com request_id=d6bfc715-22e6-428c-b8da-20e274de2a1d fwd="2400:4052:e20:2f00:50b:f8fb:bd08:3843,172.68.118.61" dyno=web.1 connect=0ms service=6757ms status=200 bytes=3443 protocol=https 32021-07-16T10:03:10.315683+00:00 app[web.1]: 10.41.200.163 - - [16/Jul/2021:19:03:10 +0900] "POST /api/v1/login/ HTTP/1.1" 200 1257 "https://project-tyoitasi.vercel.app/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" 42021-07-16T10:03:10.841532+00:00 heroku[router]: at=info method=GET path="/api/v1/get-list-article/" host=www.tyoitasi.com request_id=5796fd55-9b7f-4f0e-b111-a6e4f60907a2 fwd="2400:4052:e20:2f00:50b:f8fb:bd08:3843,172.68.118.61" dyno=web.1 connect=1ms service=79ms status=200 bytes=387 protocol=https
該当のソースコード
Next
1export async function login(email: string, password: string) { 2 let isSuccess: boolean = false; 3 await fetch(`${process.env.NEXT_PUBLIC_RESTAPI_URL}api/v1/login/`, { 4 method: "POST", 5 body: JSON.stringify({ email: email, password: password }), 6 headers: { 7 "Content-Type": "application/json", 8 }, 9 credentials: "include", 10 }).then((res) => { 11 if (res.status === 400) { 12 isSuccess = false; 13 } else if (res.ok) { 14 isSuccess = true; 15 } 16 }); 17 window.location.reload(); 18 return isSuccess; 19}
Django
1from dj_rest_auth.app_settings import (JWTSerializer, 2 JWTSerializerWithExpiration, 3 TokenSerializer, create_token) 4from dj_rest_auth.models import TokenModel 5from dj_rest_auth.views import sensitive_post_parameters_m 6from dj_rest_auth.utils import jwt_encode 7from django.conf import settings 8from django.contrib.auth import login as django_login 9from django.utils import timezone 10from rest_framework import status 11from rest_framework.generics import GenericAPIView 12from rest_framework.permissions import AllowAny 13from rest_framework.response import Response 14import datetime 15 16from accounts.serializers import CustomLoginSerializer 17 18def set_userid_cookies(response): 19 userid = response.data['user']['id'] 20 max_age = 24 * 60 * 60 21 expires = datetime.datetime.strftime( 22 datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age), 23 "%a, %d-%b-%Y %H:%M:%S GMT", 24 ) 25 26 response.set_cookie( 27 'UID', 28 userid, 29 max_age=max_age, 30 expires=expires, 31 samesite='Lax', 32 secure=True, 33 ) 34 35 36class LoginView(GenericAPIView): 37 permission_classes = (AllowAny,) 38 serializer_class = CustomLoginSerializer 39 token_model = TokenModel 40 throttle_scope = 'dj_rest_auth' 41 42 @sensitive_post_parameters_m 43 def dispatch(self, *args, **kwargs): 44 return super(LoginView, self).dispatch(*args, **kwargs) 45 46 def process_login(self): 47 django_login(self.request, self.user) 48 49 def get_response_serializer(self): 50 if getattr(settings, 'REST_USE_JWT', False): 51 52 if getattr(settings, 'JWT_AUTH_RETURN_EXPIRATION', False): 53 response_serializer = JWTSerializerWithExpiration 54 else: 55 response_serializer = JWTSerializer 56 57 else: 58 response_serializer = TokenSerializer 59 return response_serializer 60 61 def login(self): 62 self.user = self.serializer.validated_data['user'] 63 64 if getattr(settings, 'REST_USE_JWT', False): 65 self.access_token, self.refresh_token = jwt_encode(self.user) 66 else: 67 self.token = create_token(self.token_model, self.user, 68 self.serializer) 69 70 if getattr(settings, 'REST_SESSION_LOGIN', True): 71 self.process_login() 72 73 def get_response(self): 74 serializer_class = self.get_response_serializer() 75 76 access_token_expiration = None 77 refresh_token_expiration = None 78 if getattr(settings, 'REST_USE_JWT', False): 79 from rest_framework_simplejwt.settings import \ 80 api_settings as jwt_settings 81 access_token_expiration = (timezone.now() + jwt_settings.ACCESS_TOKEN_LIFETIME) 82 refresh_token_expiration = (timezone.now() + jwt_settings.REFRESH_TOKEN_LIFETIME) 83 return_expiration_times = getattr(settings, 'JWT_AUTH_RETURN_EXPIRATION', False) 84 85 data = { 86 'user': self.user, 87 'access_token': self.access_token, 88 'refresh_token': self.refresh_token 89 } 90 91 if return_expiration_times: 92 data['access_token_expiration'] = access_token_expiration 93 data['refresh_token_expiration'] = refresh_token_expiration 94 95 serializer = serializer_class(instance=data, 96 context=self.get_serializer_context()) 97 else: 98 serializer = serializer_class(instance=self.token, 99 context=self.get_serializer_context()) 100 101 response = Response(serializer.data, status=status.HTTP_200_OK) 102 if getattr(settings, 'REST_USE_JWT', False): 103 from dj_rest_auth.jwt_auth import set_jwt_cookies 104 set_jwt_cookies(response, self.access_token, self.refresh_token) 105 set_userid_cookies(response) 106 107 return response 108 109 def post(self, request, *args, **kwargs): 110 self.request = request 111 self.serializer = self.get_serializer(data=self.request.data) 112 self.serializer.is_valid(raise_exception=True) 113 114 self.login() 115 return self.get_response()
Django
1# allauth設定 2ACCOUNT_USERNAME_REQUIRED = False 3ACCOUNT_AUTHENTICATION_METHOD = 'email' 4ACCOUNT_EMAIL_REQUIRED = True 5ACCOUNT_UNIQUE_EMAIL = True 6ACCOUNT_EMAIL_VERIFICATION = 'mandatory' 7ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 600 8AUTHENTICATION_BACKENDS = [ 9 'allauth.account.auth_backends.AuthenticationBackend', 10 'django.contrib.auth.backends.ModelBackend', 11] 12 13# dj_rest_auth設定 14SITE_ID = 1 15REST_USE_JWT = True 16JWT_AUTH_COOKIE = 'access' 17JWT_AUTH_REFRESH_COOKIE = 'refresh' 18JWT_AUTH_HTTPONLY = True 19JWT_AUTH_SECURE = True 20REST_AUTH_SERIALIZERS = { 21 'USER_DETAILS_SERIALIZER': 'accounts.serializers.CustomUserSerializer' 22} 23 24# simple_jwt設定 25key = RSA.generate(2048) 26PRIVATE_KEY = key.export_key() 27PUBLIC_KEY = key.publickey().export_key() 28SIMPLE_JWT = { 29 'AUTH_HEADER_TYPES': ('JWT',), 30 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5), 31 'REFRESH_TOKEN_LIFETIME': timedelta(hours=12), 32 'ROTATE_REFRESH_TOKENS': True, 33 'BLACKLIST_AFTER_ROTATION': True, 34 'ALGORITHM': 'RS256', 35 'SIGNING_KEY': PRIVATE_KEY, 36 'VERIFYING_KEY': PUBLIC_KEY, 37}
試したこと
フロントのアプリからログインをしてみました
実際にログイン自体は成功しています
問題はCookieがフロントにセットされないことだけです
補足情報(FW/ツールのバージョンなど)
OS: macOS 10.15.7
Next.js: 11.0.1
nginx: 1.21.1
Google Chrome
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。