< 一覧に戻る

Django 認証に Cognito を組み込む


Django 認証バックエンドに Cognito を設定し、API から認証を実行可能とするバックエンドの例

AWS article Django Python
Source Code: https://github.com/kemu3007/django-cognito 認証バックエンドを設定することで Django Admin 等のデフォルト機能を利用可能としています。 トークン類はセッションとして DB に保存しバックエンドからのみ参照可能です。 ## `urls.py` ```python from django.contrib import admin from django.urls import path from auth.views import auth_api urlpatterns = [path("admin/", admin.site.urls), path("auth/", auth_api.urls)] ``` ## `backend.py` ```python import requests from django.conf import settings from django.contrib.auth.backends import BaseBackend from django.contrib.auth.models import User from django.db.models.base import Model class CognitoBackend(BaseBackend): def authenticate(self, request, username=None, password=None): response = requests.post( settings.COGNITO_EP, json={ "AuthFlow": "USER_PASSWORD_AUTH", "ClientId": settings.COGNITO_CLIENT_ID, "AuthParameters": {"USERNAME": username, "PASSWORD": password}, }, headers={ "Content-Type": "application/x-amz-json-1.1", "X-Amz-Target": "AWSCognitoIdentityProviderService.InitiateAuth", }, ) if response.status_code != 200: return None request.session["cognito"] = response.json() user, _ = User.objects.get_or_create( username=username, is_staff=True, is_superuser=True ) return user def get_user(self, user_id: int): return User.objects.filter(pk=user_id).first() ``` ## `views.py` ```python import jwt import requests from django.conf import settings from django.contrib.auth import authenticate, logout from ninja import NinjaAPI, Schema auth_api = NinjaAPI() class LoginSchema(Schema): username: str password: str class LoginResponseSchema(Schema): pk: int username: str @auth_api.post("/login", response=LoginResponseSchema) def login(request, input: LoginSchema): return authenticate(request, username=input.username, password=input.password) class SignUpSchema(Schema): username: str password: str email: str @auth_api.post("/signUp") def signUp(request, input: SignUpSchema): response = requests.post( settings.COGNITO_EP, json={ "ClientId": settings.COGNITO_CLIENT_ID, "Username": input.username, "Password": input.password, "UserAttributes": [{"Name": "email", "Value": input.email}], }, headers={ "Content-Type": "application/x-amz-json-1.1", "X-Amz-Target": "AWSCognitoIdentityProviderService.SignUp", }, ) return response.json() class ConfirmSignUpSchema(Schema): username: str code: str @auth_api.post("/confirmSignUp") def confirmSignUp(request, input: ConfirmSignUpSchema): response = requests.post( settings.COGNITO_EP, json={ "ClientId": settings.COGNITO_CLIENT_ID, "Username": input.username, "ConfirmationCode": input.code, }, headers={ "Content-Type": "application/x-amz-json-1.1", "X-Amz-Target": "AWSCognitoIdentityProviderService.ConfirmSignUp", }, ) return response.json() @auth_api.get("/getUser") def getUser(request): try: jwks_client = jwt.PyJWKClient(settings.COGNITO_JWK_EP) token = request.session["cognito"]["AuthenticationResult"]["IdToken"] payload = jwt.decode( token, jwks_client.get_signing_key_from_jwt(token), audience=settings.COGNITO_CLIENT_ID, algorithms=["RS256"], ) return payload except (jwt.exceptions.PyJWTError, KeyError) as e: return None ```