【问题标题】:Usage of Refresh Token in OAuth2.0OAuth2.0中刷新令牌的使用
【发布时间】:2016-09-13 05:07:29
【问题描述】:

我正在实现OAuth2.0 server 并尝试读取concepts of refresh token 以及如何使用来调用访问令牌以及如何安全地存储它。

这对我来说听起来很令人困惑的是`因为 Auth2.0 令牌是短暂的令牌,并且假设在成功登录后服务器给了我一个类似这样的令牌:

{
    "token_type":"bearer",
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI1NDMsImV4cCI6MTQ0NDI2MjU2M30.MldruS1PvZaRZIJR4legQaauQ3_DYKxxP2rFnD37Ip4",
    "expires_in":3600,
    "refresh_token":"fdb8fdbecf1d03ce5e6125c067733c0d51de209c"
}

由于访问令牌是短暂的令牌,在我的情况下它将在 1 小时后过期。

假设一个用户是browsing a protected resource,其凭据为access tokens,一段时间后其访问令牌过期,他的请求返回这样的响应。

{
  "code":401,
  "error":"invalid_token",
  "error_description":"The access token provided has expired."
}

现在可以使用浏览器 cookie 中存储的新 refresh tokenbut doesn't the user experience is getting affected as each time an access token expires in an hour a valid request by a client is getting rejected due to expired access token and then we have to first fetch a new access token and then try that request again. 生成新令牌

刷新令牌的获取是否只能这样工作,或者我错过了一些重要的概念?

另外,如何在 cookie 中安全地存储刷新令牌,因为它也不是最好的安全存储方式?

【问题讨论】:

  • 这就是为什么大多数开发人员会在访问令牌过期前 5 分钟检查 expires_in 并获得一个新的。这样用户就不会受到影响。通常,当我获得访问令牌时,我会将 3600 添加到当前时间,然后存储它,我知道何时需要获得新的访问令牌。
  • @DaImTo 我怎样才能在浏览器上安全地存储refresh token
  • 只需将其转储到 cookie 或会话值中,对于没有创建它的客户端 ID 和客户端密钥的任何人来说,它都是无用的,我会假设代码保留在服务器端。

标签: authentication cookies oauth oauth-2.0 openid-connect


【解决方案1】:

刷新令牌是一种特殊的令牌,可用于随时获取更新的 id_token。刷新令牌必须由应用程序安全存储,因为它们本质上允许用户永远保持身份验证。

身份验证请求的响应可能导致 OAuth 发出 id_token。此令牌可用于对安全 API 进行经过身份验证的调用。

在签名等其他安全措施中,OAuth 的过期日期由 exp 声明指示。但是,本地安装在台式机或智能手机等设备上的应用程序可能希望避免在每次令牌过期时都要求用户输入凭据。

刷新令牌允许应用程序请求 OAuth 直接发出新的 id_token,而无需重新进行身份验证。只要刷新令牌未被撤销,此方法就有效。

安全注意事项

因为刷新令牌永不过期,所以提供一种撤销它们的方法很重要。这可以从仪表板手动完成,也可以通过 Auth 的 API 以编程方式完成。

可以为应用、用户和设备的每个组合颁发和撤销刷新令牌。要撤销刷新令牌,您可以调用撤销刷新令牌端点:

DELETE https://YOUR_NAMESPACE/api/users/<user id>/refresh_tokens/<refresh token>

{
  "Authorization":   "Bearer <your access token>",
}

获取刷新令牌

要获取刷新令牌,在通过 /authorize 端点发起身份验证请求时,必须包含 offline_access 范围和任意设备名称。例如:

GET https://YOUR_NAMESPACE/authorize/?
    response_type=token
    &client_id=YOUR_CLIENT_ID
    &redirect_uri=YOUR_CALLBACK_URL
    &state=VALUE_THAT_SURVIVES_REDIRECTS
    &scope=openid%20offline_access
    &device=my-device

使用刷新令牌

要获取新的 id_token,使用委托端点:

POST https://YOUR_NAMESPACE/delegation
Content-Type: 'application/json'
{
  "client_id":       "YOUR_CLIENT_ID",
  "grant_type":      "urn:ietf:params:oauth:grant-type:jwt-bearer",
  "refresh_token":   "your_refresh_token",
  "api_type":        "app"
}

此请求的响应可能如下:

{
  "token_type": "Bearer",
  "expires_in": 30000,
  "id_token": "eyJ..."
}

expires_in 参数表示新 JWT 的生命周期,以秒为单位。可以通过 JWT 的 exp 和 iat 声明的差异来计算。

重要建议:仅当 id_token 过期时才应使用 refresh_token 获取新令牌。例如,每次执行 API 调用时调用端点来获取新令牌是一种不好的做法。 Auth0 中存在速率限制,这将限制使用相同令牌从某个 IP 到此端点的请求数量。

如需进一步阅读,请尝试以下链接

https://auth0.com/docs/refresh-token

【讨论】:

    【解决方案2】:

    刷新令牌是您用来获取另一个有效令牌以与您正在使用的 API 进行交互的令牌,因为这些令牌是短暂的。然后,由于令牌是短暂的,因此每次您想要访问 API 时,您都必须从用户那里获得另一个 oauth2.0 凭证。如何避免这种情况? -> 刷新令牌。

    如前所述,刷新令牌根本不是 API 访问令牌,它只是一种用于每次获取新的短期令牌的令牌。

    然后您的第一个登录凭据在用户同意的情况下获得一个令牌和一个刷新令牌,然后您不再需要用户同意,只需使用刷新令牌。

    不确定我是否在回答你的问题:)

    【讨论】:

      猜你喜欢
      • 2014-10-28
      • 1970-01-01
      • 2018-03-26
      • 1970-01-01
      • 1970-01-01
      • 2014-02-10
      • 2012-10-02
      • 2013-09-02
      • 2019-06-29
      相关资源
      最近更新 更多