如何在 OpenID Connect/OAuth2 隐式流程中获取新的访问令牌

How to get new access token in OpenID Connect/OAuth2 Implicit Flow

我目前正在移动应用程序中使用 OpenID Connect/Oauth2 隐式流。我正在打开一个 Web 视图供用户登录并获取访问令牌和到期时间。但是,当访问令牌过期时,是否需要让用户重新登录?或者有没有一种方法可以使用当前访问令牌以静默方式获取新访问令牌,而不会打扰用户。我想另一种选择是将令牌过期时间设置得非常长,但我读到这是个坏主意。

我是不是漏掉了什么?

推荐的方式是使用外部浏览器和授权代码流程。检查 OAuth 2.0 for Native Apps RFC. For Android, there is also a supporting library AppAuth。通过此流程,您可以使用刷新令牌来获取新的访问令牌,但是客户端机密(访问 /token 端点通常需要)存在问题,因为您无法在移动应用程序中保证它的安全(在RFC)。

如果您决定坚持使用不安全的 WebView 和隐式流程(您的应用程序可以看到密码),您可以使用与 JavaScript 应用程序中相同的技术 - 请求一个新令牌/auth?...&prompt=none URL 这将 return 一个新的令牌,如果他仍然在那里有一个打开的会话,则不要求用户提供凭据。

由于隐式流不发送刷新令牌(如 section 9 of RFC6746), usage of refresh tokens is not possible. But as a workaround one can use client credential grant 中所述以获取访问令牌。

一个可行的解决方案是首先遵循隐式流程并对客户端进行身份验证。然后 客户端身份验证授权 可用于执行所需的 API 调用。

示例请求(来自 RFC6749

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

 rant_type=client_credentials

示例响应(来自 RFC6749

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
   "access_token":"2YotnFZFEjr1zCsicMWpAA",
   "token_type":"example",
   "expires_in":3600,
   "example_parameter":"example_value"
}

P.S - 如果您使用的是授权代码流,您可以使用refresh_token获取新的访问令牌。可以从 OAuth2 documentation 获得请求应该如何形成。请注意,为此,您的授权响应应包含`refresh_token.

刷新令牌应像用户凭据一样受到保护。可以从 here

的 keycloak 文档中阅读更多内容

示例请求和响应(来自 RFC6749

请求

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

回应

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "TlBN45jURg",
  "token_type": "Bearer",
  "refresh_token": "9yNOxJtZa5",
  "expires_in": 3600
}