以下の続き kamatimaru.hatenablog.com
認可エンドポイント
RPのクライアントの作成
client_idの存在チェックをしていないので、RPのクライアントを作成できるようにしていく。
まずはModelを定義する。クライアントは一意なので、nameとclient_idにunique=Trueをつける
※ シークレットは必要になってから追加する
models.py
from django.db import models class RelyingParty(models.Model): name = models.CharField(max_length=64, unique=True) client_id = models.CharField(max_length=64, unique=True) def __str__(self): return self.name def __str__(self): return self.name
Django Adminにも登録する
admin.py
from .models import RelyingParty from django.contrib import admin admin.site.register(RelyingParty)
これでDjango AdminからRPのクライアントを登録できるようになった。

client_idの存在チェック
認可エンドポイントにclient_idの存在チェックを追加する
views.py
class AuthorizeView(View): def get(self, request): # ...省略 client_id = form.cleaned_data["client_id"] if not RelyingParty.objects.filter(client_id=client_id).exists(): return HttpResponseBadRequest() # ...省略
存在しないclient_idでリクエストすると400を返すようになったのでok
[29/Dec/2024 01:31:35] "GET /sample/authorize/?response_type=code&scope=openid%20email&client_id=hoge&state=abcd&redirect_uri=http://localhost/callback&nonce=efgh HTTP/1.1" 400 0
ログイン画面の実装
各パラメータのバリデーションをパスしたらログイン画面が表示されるようにしていく。 まずはログイン画面用のフォームを実装する。
forms.py
class LoginForm(forms.Form): username = forms.CharField(max_length=32) password = forms.CharField(widget=forms.PasswordInput)
ログイン画面のテンプレートを実装する
login.html
<html> <head> <title>ログイン</title> </head> <body> <form action="{% url 'sampleapp:authorize' %}" method="post"> {% csrf_token %} <h1>ログイン</h1> {{ form.as_p }} <input type="submit" value="登録"> </form> </body> </html>
views.py Viewでテンプレートを返す
class AuthorizeView(View): def get(self, request): # ...省略 return render(request, "login.html", {"form": LoginForm()})
これでログイン画面が表示されるようになった。POSTリクエストを実装していないので、submitすると405になる。

ID/パスワード認証
ID/パスワード認証を実装していく。
AuthorizeViewに以下のようにPOST時の処理を実装する。Djangoのログインの実装は公式ドキュメントを参照。
Djangoの認証システムを使用する | Django documentation | Django
views.py
from django.contrib.auth import authenticate, login # ...省略 class AuthorizeView(View): # ...省略 def post(self, request): form = LoginForm(request.POST) if not form.is_valid(): return render(request, "login.html", {"form": form}) user = authenticate( request, username=form.cleaned_data["username"], password=form.cleaned_data["password"], ) if user is None: form.add_error(None, "IDかパスワードが間違っています") return render(request, "login.html", {"form": form}) login(request, user) return HttpResponse("Logged in")
- ID/パスワードが正しい場合: ログイン成功
- ID/パスワードが間違ってる場合: ログイン画面をエラーメッセージ付きで再表示
が実装できた。

次はユーザー情報提供同意画面の実装に入っていく。