我正在尝试使用 django-rest-framework 在我的 Django REST API 中实现基于 Auth0 JWT 的身份验证。我知道有一个可用于 REST 框架的 JWT 库,并且我尝试过使用它,因为官方 Auth0 twitter 帐户提到它应该可以很好地与 auth0 + Django 一起使用。
编辑:我为此代码使用官方 auth0 python api 指南。它是为烧瓶编写的,但我想我可以将它移植到 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 的文档中使用的自定义实现。我已经验证这可行,所以这不是问题。
SECRET
根据 Auth0 文档,是我的 Auth0 机密,以 base64 编码(任何其他密钥无法解码)
CLIENT_ID
是我的 Auth0 客户端 ID,用作受众。
我在前端使用 Angular 种子项目,并且我已经验证令牌确实随请求一起发送,并且我已经验证它与存储在token
后端变量中的令牌完全相同。
当jwt.decode()
被调用时,它会触发jwt.DecodeError
每次,我已经花了无数个小时试图解决这个问题,但我对为什么这不起作用感到非常震惊。我尝试将 JWT 选项设置为 false,特别是验证签名选项。这行得通,但我认为禁用 JWT 签名的验证是不安全的。
我不知道为什么这让我失望,我已经尝试了相同的代码,但它没有放在装饰器中,它做同样的事情。被装饰的视图只是一个返回 OK HttpResponse 的空视图。
特长; 使用 Django-REST + Auth0 JWT——jwt.decode()
不管我做什么都行不通。
EDIT2:值得一提的是,我corsheaders
支持 django-rest,它允许我提出跨域请求。我还按照 Auth0 的 Python API 指南底部的提示卸载并重新安装 JWT 库,但这对我没有任何帮助。
我是否忽略了一些东西,这个实现是不安全的,还是你有更好的方法来用 Django 实现 Auth0?请让我知道,这个问题让我做噩梦。