以下の内容はhttps://kamatimaru.hatenablog.com/entry/2024/12/29/115146より取得しました。


勉強のためにOpen ID ConnectのIDプロバイダー側をDjangoで実装する②

以下の続き kamatimaru.hatenablog.com

認可エンドポイント

RPのクライアントの作成

client_idの存在チェックをしていないので、RPのクライアントを作成できるようにしていく。 まずはModelを定義する。クライアントは一意なので、nameclient_idunique=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/パスワードが間違ってる場合: ログイン画面をエラーメッセージ付きで再表示

が実装できた。

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




以上の内容はhttps://kamatimaru.hatenablog.com/entry/2024/12/29/115146より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14