【问题标题】:What does a JWT cookie need to look like to work with NGINX modules?JWT cookie 需要什么样的外观才能与 NGINX 模块一起使用?
【发布时间】:2019-02-17 03:55:06
【问题描述】:

我一直在使用 NGINX 作为反向代理,最近决定我需要为网站上的路由添加身份验证。我意识到有多个 NGINX 模块可以让我通过 NGINX 处理身份验证(请参阅下面的链接)。因此,我构建了一个单点登录页面,它集成了 auth0 来测试它是如何工作的。

所有模块都相似,允许您指定 auth_jwt_key(用于验证 JWT)以及存储 JWT (auth_jwt) 的变量。我决定将 JWT 存储在 cookie 中。

不幸的是,我无法通过 NGINX 进行验证,并且一直看到 401 unauthorized 返回码。

这是烧瓶应用程序的一部分,我正在处理 auth0 登录并将 JWT 存储到 cookie 中:

@app.route('/callback')
    def callback_handling():
    token = auth0.authorize_access_token()
    response = redirect('/dashboard')
    response.set_cookie('lt_jwt', value=token.get('id_token'), max_age=token.get('expires_in'))
    return response

你能看出这有什么问题吗? 生成的 cookie 看起来像这样(为了便于阅读,我删除了大部分):lt_jwt eyJ0eX[...]SkRNZyJ9.eyJnaXZ[...]kzNDV9.d3Tzr[...]NzbA staging-auth0-login.scapp.io / 9/13/2018, 1:55:45 PM 1.03 KB

我可以将 cookie 值放入 jwt.io 并正确解码,但我的问题是提到的 NGINX 模块在解码时存在问题。

这是一个 NGINX 配置示例,我在其中设置身份验证:

location = /dashboard {
    auth_jwt_key "AUTH0_CLIENT_SECRET";
    auth_jwt $cookie_lt_jwt;

    root /usr/src/lt/nginx;
    try_files /dashboard.html =404;
}

基本上,我从来没有见过dashboard.html,总是得到401 unauthorized。 NGINX error.log 显示解码 JWT 失败:[warn] 64#64: *23 JWT: failed to parse jwt,在本例中是来自我使用的自定义 nginx 模块的错误日志:

// Validate the jwt
if (jwt_decode(&jwt, jwt_data, conf->jwt_key.data, conf->jwt_key.len))
{
  ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "JWT: failed to parse jwt");
  return NGX_HTTP_UNAUTHORIZED;
}

参考:https://github.com/maxx-t/nginx-jwt-module/blob/d9a2ece81ca66647f81fc2586b29b348af67f8aa/src/ngx_http_auth_jwt_module.c#L124

不幸的是,调试起来并不容易,但我从另一个我也测试过的自定义 NGINX 模块收到了类似的响应:jwt_verify: error on decode: SUCCESS,这是此代码段的结果:

  jwt_t* token;
  int err = jwt_decode(&token, token_data, alcf->key.data, alcf->key.len);
  if (err) {
    ngx_log_error(NGX_LOG_ERR, r->connection->log, errno,
                  "jwt_verify: error on decode: %s", strerror(errno));
    return ngx_http_auth_jwt_set_realm(r, &alcf->realm);
  }

参考:https://github.com/tizpuppi/ngx_http_auth_jwt_module/blob/bf8ae5fd4b8e981b7683990378356181dee93842/ngx_http_auth_jwt_module.c#L247

所以在这两种情况下,jwt_decode 都会被调用并失败(即使它的错误代码显然是 SUCCESS)。

我在这里问的原因是我觉得我可能在这里做一些概念上的错误:

  1. 格式化cookie(我见过jwt cookie看起来像这样: Bearer eyJ0eX[...]SkRNZyJ9.eyJnaXZ[...]kzNDV9.d3Tzr[...]NzbA
  2. 假设 auth0 生成的令牌可以这样使用
  3. ...?

如果您对 NGINX + auth0 有任何见解或良好的工作示例,请告诉我。我已阅读 auth0 撰写的这篇文章 https://auth0.com/blog/use-nginx-plus-and-auth0-to-authenticate-api-clients/,详细介绍了如何使用非常相似的 NGINX Pro 模块,但我无权访问该商业模块。

【问题讨论】:

    标签: nginx cookies jwt auth0


    【解决方案1】:

    回答主要问题:cookie 应该只包含没有任何前缀的 JWT。问题中的python(flask)代码没有做错任何事情,我能够通过curl确认您实际上可以获得存储在cookie中的授权(使用有效的JWT):

    curl https://some.page.com/application --cookie "lt_jwt=eyJ0eX[...]SkRNZyJ9.eyJnaXZ[...]kzNDV9.d3Tzr[...]NzbA"
    

    那么这里的问题是什么 - 为什么我不能在浏览器中进行身份验证,当它通过 curl 工作时?

    原因在于 NGINX 配置,它要求在 http 上下文中禁用身份验证。这本质上是 NGINX 模块中的一个错误,后来开发人员设法修复了这个错误。

    经验教训:这通常不是你的错 ;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-27
      • 2015-09-29
      • 1970-01-01
      • 2020-08-20
      • 2013-10-24
      • 2021-03-22
      • 1970-01-01
      • 2014-10-23
      相关资源
      最近更新 更多