microdot.auth --- HTTP 認証

ルートを HTTP 認証の背後に置くデコレータです。2 つの種類があります。ブラウザがネイティブにプロンプトを表示する Authorization: Basic <base64> 方式向けの BasicAuth と、API が使用する Authorization: Bearer <token> 方式向けの TokenAuth です。

どちらのクラスも共通の BaseAuth 基底クラスから派生しています。アプリケーションは認証オブジェクトを構築し、authenticate() で認証コールバックを登録し、保護対象のルートをその認証インスタンスでデコレートします。

class BasicAuth

class microdot.auth.BasicAuth(realm: str = 'Please login', charset: str = 'UTF-8', scheme: str = 'Basic', error_status: int = 401)

HTTP Basic 認証。認証されていないリクエストが保護されたルートに到達すると、ブラウザはユーザー名/パスワードのダイアログを表示し、以降のリクエストでは Authorization: Basic <base64(user:pass)> を送信します。

realm

ブラウザがプロンプトの横に表示する realm 文字列。

charset

WWW-Authenticate チャレンジで通知される文字セット。

scheme

認証方式名。デフォルトは 'Basic' です。

error_status

認証失敗時に返される HTTP ステータス。デフォルトは 401 です。

authenticate(f)

資格情報のチェックを登録するデコレータ。f(request, username, password) を受け取り、認証されたユーザーオブジェクト(資格情報が誤っている場合は None)を返します。返されたオブジェクトは request.g.current_user に格納されます。

basic = BasicAuth(realm='Camera')

@basic.authenticate
async def check(request, username, password):
    user = users.get(username)
    if user and user.check_password(password):
        return user
__call__(f)

BasicAuth インスタンスでルートをデコレートすると、そのルートが保護されます:

@app.route('/admin')
@basic
def admin(request):
    return 'hello ' + request.g.current_user.name
optional(f)

__call__() と同様ですが、資格情報を持たないリクエストを拒否しません。ハンドラは引き続き実行され、request.g.current_user には認証されたユーザーまたは None のいずれかが設定されます。

class TokenAuth

class microdot.auth.TokenAuth(header: str = 'Authorization', scheme: str = 'Bearer', error_status: int = 401)

ベアラートークン認証。クライアントは Authorization ヘッダーにトークンを送信します。アプリケーションは任意のバッキングストアに対してそれを検証します。

header

トークンを保持するヘッダー名。デフォルトの 'Authorization' は値が Bearer <token> であることを想定します。カスタムヘッダーはトークン値を直接保持します。

scheme

Authorization ヘッダーの認証方式。デフォルトは 'Bearer' です。

error_status

認証失敗時の HTTP ステータス。デフォルトは 401 です。

authenticate(f)

トークンのチェックを登録するデコレータ。f(request, token) を受け取り、ユーザーオブジェクトまたは None を返します:

import jwt

tokens = TokenAuth()

@tokens.authenticate
async def check(request, token):
    try:
        claims = jwt.decode(token, SECRET)
    except jwt.exceptions.PyJWTError:
        return None
    return claims['sub']
errorhandler(f)

デフォルトの 401 応答を上書きするデコレータ。f はリクエストオブジェクトを受け取り、応答を返します(または中断します)。

__call__(f: Callable) Callable

TokenAuth インスタンスでルートをデコレートすると、そのルートが保護されます。有効なトークンを持たないリクエストは拒否されます(デフォルトでは 401、または errorhandler() が返した値)。成功すると認証されたユーザーは request.g.current_user に設定されます:

@app.get('/api/me')
@tokens
async def me(request):
    return {'user': request.g.current_user}

ラップされたハンドラを返します。

optional(f: Callable) Callable

__call__() と同様ですが、トークンを持たないリクエストを拒否しません。ハンドラは引き続き実行され、request.g.current_user には認証されたユーザーまたは None のいずれかが設定されます。呼び出し元が認証されているかどうかに応じて出力を変えるものの、認証を必須としないルートに便利です:

@app.get('/api/feed')
@tokens.optional
async def feed(request):
    if request.g.current_user:
        return personalized_feed(request.g.current_user)
    return public_feed()

ラップされたハンドラを返します。

class BaseAuth

class microdot.auth.BaseAuth

BasicAuthTokenAuth の共通基底クラス。カスタム認証方式はこれをサブクラス化できます。

auth_callback: Callable | None

authenticate を介して登録されるコールバック。アプリケーションがコールバックを登録するまでは None です(@auth.authenticate で関数をデコレートすることでこれが設定されます)。

error_callback: Callable

認証失敗時に送信される応答を返す非同期呼び出し可能オブジェクト。コンストラクタによって 401 応答を返すデフォルトに設定されます。TokenAutherrorhandler を介して、またはカスタムの BaseAuth サブクラスで直接置き換えられます。

デコレートされたルートでは、request.g.current_user に認証コールバックから返された値が設定されます。ルート内でその属性を調べることで、呼び出し元を特定できます。