JWT 身份验证:使用 UI 令牌对 Graphene/Django (GraphQL) 查询进行身份验证?

Posted

技术标签:

【中文标题】JWT 身份验证:使用 UI 令牌对 Graphene/Django (GraphQL) 查询进行身份验证?【英文标题】:JWT Authentication: Use UI token to authenticate Graphene/Django (GraphQL) queries? 【发布时间】:2016-12-17 11:58:44 【问题描述】:

我正在开发一个具有以下架构的项目:

UI:通过 Node 服务器、Apollo Client for GraphQL 对客户端和服务器端渲染做出反应,

API:Django 通过 Graphene 处理 GraphQL 查询。

我使用 Auth0(基于 JWT)进行前端身份验证。我想使用我获得的令牌在 GraphQL 查询 API 端的上下文中对我的用户进行身份验证。

[编辑2]

要将令牌传递给我的 API,我使用:

const idToken = cookie.load('idToken') || null;
networkInterface.use([
  applyMiddleware(req, next) 
    if (!req.options.headers) 
      req.options.headers = ;  // Create the header object if needed.
    
    req.options.headers.authorization = `Bearer $idToken`;
    next();
  
]);

然后我需要在 Django 中检索它:我使用 django-jwt-auth 和@Craig Ambrose 提出的代码。

我的授权标头被接收并解码(我可以得到有效载荷)但在验证签名时出现问题:我得到“错误解码签名”。

这很奇怪,因为我在 jwt.io 上测试签名时验证了签名。

如何在 Django 端进行身份验证?

【问题讨论】:

据我了解,您正在尝试执行以下操作。 - 使用 Auth0 进行身份验证, - 使用 Auth0 返回的令牌调用 Django 应用程序,然后使用 Graphene 进行查询?对吗? 绝对是!我想设置我的 Django 项目,以便当使用 JWT 标头进行 GraphQL 查询时,我可以在我的 graphql-django-view 中使用:@with_context 并使用 context.user.is_authenticated() 就像在 User-based Queryset Filtering 那么您到底面临什么问题呢?目前,id_token 可以工作,但 Auth0 很快就会添加允许您设置资源服务器并请求访问令牌以便能够向这些请求服务器发出请求的功能。 嗨@Abhishrek。我的问题是我找不到任何文档来解释我的 Django 设置对于这个配置应该是什么样子(可能这个配置不是那么特别)。 django-auth0、django-jwt-auth 或 djangorestframework-auth0 似乎不适合。所以我要求对此提供某种输入/指导。我没有时间尝试一些解决方案。你对我应该在哪里看有什么建议吗?一旦我有东西启动并运行,我会发布我的设置。 【参考方案1】:

我刚刚使用 django-jwt-auth 完成了这项工作(不使用 Auth0)

例如,该包提供了一个 JSONWebTokenAuthMixin,您可以将其与来自 graphene_django 的 GraphQLView 结合使用。

from jwt_auth.mixins import JSONWebTokenAuthMixin

class AuthGraphQLView(JSONWebTokenAuthMixin, GraphQLView):
    pass

urlpatterns = [
    url(r'^graphql', csrf_exempt(AuthGraphQLView.as_view(schema=schema))),
    url(r'^graphiql', include('django_graphiql.urls')),
]

这可行,但我发现 graphiql 停止工作,因为它没有发送到令牌。出于开发目的,我想继续使用基于 cookie 的身份验证,因此将其更改为以下内容。

from jwt_auth.mixins import JSONWebTokenAuthMixin

class OptionalJWTMixin(JSONWebTokenAuthMixin):
    def dispatch(self, request, *args, **kwargs):
        auth = get_authorization_header(request)
        if auth:
            return super(OptionalJWTMixin, self).dispatch(request, *args, **kwargs)
        else:
            return super(JSONWebTokenAuthMixin, self).dispatch(request, *args, **kwargs)


class AuthGraphQLView(OptionalJWTMixin, GraphQLView):
    pass

urlpatterns = [
    url(r'^graphql', csrf_exempt(AuthGraphQLView.as_view(schema=schema))),
    url(r'^graphiql', include('django_graphiql.urls')),
]

【讨论】:

克雷格您好,感谢您的回答!上个月我没有机会处理这个问题,但很快就会看看你的解决方案。【参考方案2】:

我的设置现在有效:

我使用了来自@Craig Ambrose 的代码和django-jwt-auth。我不得不在 Github 上 fork 包来处理 Auth0 令牌中存在的 Audience 'aud' 有效负载。

def jwt_get_user_id_from_payload_handler(payload):
    sub = payload.get('sub')
    Auth0User = import_string('project.models.Auth0User')
    auth0_user = Auth0User.objects.filter(auth0_id=sub)[0]
    user_id = auth0_user.user.id
    return user_id

JWT_PAYLOAD_GET_USER_ID_HANDLER = jwt_get_user_id_from_payload_handler
auth0_key = '<MyAuth0SECRET>'
JWT_SECRET_KEY = base64.b64decode(auth0_key.replace("_","/").replace("-","+"))
JWT_VERIFY = True
JWT_AUTH_HEADER_PREFIX = 'Bearer'
JWT_AUDIENCE = '<MyAuth0CLIENT_ID>'

使用 Aut0User 的模型具有 OnoToOne 与经典 Django 用户的关系以及具有 auth0_id 的字段。

【讨论】:

以上是关于JWT 身份验证:使用 UI 令牌对 Graphene/Django (GraphQL) 查询进行身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

在 Kong API 网关中使用 .jks 密钥对 JWT 令牌进行身份验证

验证 API 密钥和 JWT 令牌是微服务的责任吗?

如何跨不同 API 对 JSON Web 令牌 (JWT) 进行身份验证?

使用 JWT 和刷新令牌对移动应用程序进行身份验证

ASP.NET Core 中的 Jwt 令牌身份验证

使用 Spring 和 JWT 进行基于令牌的身份验证