django-rest-framework を使用して、Django REST API に Auth0 JWT ベースの認証を実装しようとしています。REST フレームワークで利用できる JWT ライブラリがあることは知っており、Auth0 の公式 Twitter アカウントが auth0 + Django でうまく動作すると述べていたので、それを使用してみました。
編集:このコードには、公式の auth0 python api ガイドを使用しています。これはフラスコ用に書かれていますが、Django と同様に動作することを確認して、Django に移植できると考えました。
さて、それは私が望んでいた方法ではうまくいかなかったのでlogin_required、ビュー用に独自のデコレータを作成しようとしています。ここにあるコードは次のとおりです。
def auth_required(f):
def wrap(request, *args, **kwargs):
auth = request.META.get('HTTP_AUTHORIZATION', None)
if not auth:
return authenticate({'code': 'authorization_header_missing', 'description': 'Authorization header is expected'})
parts = auth.split()
if parts[0].lower() != 'bearer':
return authenticate({'code': 'invalid_header', 'description': 'Authorization header must start with Bearer'})
elif len(parts) == 1:
return authenticate({'code': 'invalid_header', 'description': 'Token not found'})
elif len(parts) > 2:
return authenticate({'code': 'invalid_header', 'description': 'Authorization header must be Bearer + \s + token'})
token = parts[1]
try:
payload = jwt.decode(
token,
base64.b64decode(SECRET.replace("_","/").replace("-","+")),
audience=CLIENT_ID,
)
except jwt.ExpiredSignature:
return authenticate({'code': 'token_expired', 'description': 'token is expired'})
except jwt.InvalidAudienceError:
return authenticate({'code': 'invalid_audience', 'description': 'incorrect audience, expected: ' + CLIENT_ID})
except jwt.DecodeError:
return authenticate({'code': 'token_invalid_signature', 'description': 'token signature is invalid'})
return f(request, *args, **kwargs)
wrap.__doc__=f.__doc__
wrap.__name__=f.__name__
return wrap
さて、これauthenticate()は基本的に私のカスタム実装でJsonify()あり、Auth0 for Python API のドキュメントで使用されています。動作確認済みですので問題ありません。
SECRETbase64 でエンコードされた私の Auth0 シークレット (他のキーはデコードに失敗しました)
CLIENT_IDは、Auth0 ドキュメントによると、オーディエンスとして使用される私の Auth0 クライアント ID です。
フロントエンド側で Angular シード プロジェクトを使用しており、トークンが実際にリクエストと共に送信されることを確認しtoken、バックエンドの変数に格納されるのとまったく同じトークンであることを確認しました。
がjwt.decode()呼び出されると、毎回がトリガーされます。jwt.DecodeErrorこれを修正するために数え切れないほどの時間を費やしてきましたが、なぜこれが機能しないのか完全に唖然としています。JWT オプションを false に設定してみました。具体的には、署名の検証オプションです。これは機能しましたが、JWT 署名の検証を無効にするのは安全ではないと思います。
なぜこれが私を失敗させているのか分かりません。デコレータに入れずにこの同じコードを試してみましたが、同じことをします。装飾されたビューは、OK HttpResponse を返す単なる空のビューです。
Tldr; Django-REST + Auth0 JWT を使用jwt.decode()すると、何をしても機能しません。
EDIT2corsheaders :クロスドメインリクエストを作成できるdjango-restを使用していることに言及する価値があります。また、Auth0 の Python API ガイドの下部にあるヒントに従って、JWT ライブラリをアンインストールして再インストールしましたが、これは何もしませんでした。
私は何かを見落としていますか、この実装は単純に安全ではありませんか、それとも Django で Auth0 を実装するためのより良い方法はありますか? 教えてください、この問題は私に悪夢を引き起こしています。