iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Software Development

用Keycloak學習身份驗證與授權系列 第 17

Day16 - 【概念篇】OAuth flows: Refresh Token

本系列文之後也會置於個人網站


  +--------+                                           +---------------+
  |        |--(A)------- Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<-(B)----------- Access Token -------------|               |
  |        |               & Refresh Token             |               |
  |        |                                           |               |
  |        |                            +----------+   |               |
  |        |--(C)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(D)- Protected Resource --| Resource |   | Authorization |
  | Client |                            |  Server  |   |     Server    |
  |        |--(E)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(F)- Invalid Token Error -|          |   |               |
  |        |                            +----------+   |               |
  |        |                                           |               |
  |        |--(G)----------- Refresh Token ----------->|               |
  |        |                                           |               |
  |        |<-(H)----------- Access Token -------------|               |
  +--------+           & Optional Refresh Token        +---------------+

               Figure 2: Refreshing an Expired Access Token

   The flow illustrated in Figure 2 includes the following steps:

   (A)  The client requests an access token by authenticating with the
        authorization server and presenting an authorization grant.

   (B)  The authorization server authenticates the client and validates
        the authorization grant, and if valid, issues an access token
        and a refresh token.

   (C)  The client makes a protected resource request to the resource
        server by presenting the access token.

   (D)  The resource server validates the access token, and if valid,
        serves the request.

   (E)  Steps (C) and (D) repeat until the access token expires.  If the
        client knows the access token expired, it skips to step (G);
        otherwise, it makes another protected resource request.

   (F)  Since the access token is invalid, the resource server returns
        an invalid token error.

使用refresh_token取得access_token

接著是使用Refresh Token換取Access Token的流程。這大概是所有中最簡單的一個模式之一了。但因爲先決條件是取得可用的 Refresh Token ,所以無法單獨存在。在RCF6749相關的流程圖中,關注的是G、H的部分。至於一開始有什麼方式取得Refresh Token就非常的多。在已經介紹的密碼模式和code模式都有可能返回refresh_token

如果你是直接從上一篇看下來的話,可能已經取得了refresh_token。但也許這個refresh_token已經過期了。爲此,將先在用密碼模式取得一次access_tokenrefresh_token

同樣使用RESTfer,針對flow-experiment-1這個Client取得refresh_token

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ4VXh6WGR4UWpFNDNIZGdYbXJkUjBQZWxXN1ZoZWowbGRkR2NhN0VubXpZIn0.eyJleHAiOjE2MzIwMjg1MzYsImlhdCI6MTYzMjAyODIzNiwianRpIjoiYjU5MWI5MDQtYzI3Ni00Mjc2LThmMDEtNGUzNTUwOTgzYTNmIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL3F1aWNrLXN0YXJ0IiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjM0NWIxYmNhLTk4MDUtNGI0Yi1hMGY4LWRhMmM3MDE3NmM1OSIsInR5cCI6IkJlYXJlciIsImF6cCI6ImZsb3ctZXhwZXJpbWVudC0xIiwic2Vzc2lvbl9zdGF0ZSI6ImYxZjhkMzkyLTExZDAtNDEzMi05MDEwLTkyOGQ1NmFmMjM2MiIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo0MjAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLXF1aWNrLXN0YXJ0Iiwib2ZmbGluZV9hY2Nlc3MiLCJxdWljay1zdGFydC1leGFtcGxlLXJvbGUxIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiJmMWY4ZDM5Mi0xMWQwLTQxMzItOTAxMC05MjhkNTZhZjIzNjIiLCJ3ZWJzaXRlIjoiaHR0cHM6Ly9ib2IuaWQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZ2VuZGVyIjoibWFuIiwibmFtZSI6IkJvYiBMZWUiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJib2IiLCJnaXZlbl9uYW1lIjoiQm9iIiwiZmFtaWx5X25hbWUiOiJMZWUiLCJlbWFpbCI6ImJvYkBmYWtlLmVtYWlsIn0.d5pTkQxoLteHVW_i_6iHSuTSYhJLyacoRr94HSM97E8txjn9kS55eG9dJIH0E8o0_02g9bR_YuLEStOo9xAgU42jiUsBvxNdeGjMkDyM5tPrtz7V9i_QTu_JUWpHpE5MFdChKAVOa7I5ldmQIEd97LfRINJaeXAu0x4lcmG5fhwBUuu-qR7O09S0D6tQT76wb2TpxqMsZxDprMxE2_CPMcfd7dAwzLdnCbz1iUyBPxdALSU5eY9AXo6uBsIHkDXfvVRj3QgrmXgIwBiv9WkHUet0lz9gwN-LBIOBTzAg9yO85keRXZwkWJRQ-87rWyp7bMZgS10Vrlv-hy-cT1qkDQ",
    "expires_in": 300,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0NjUwNDBkYi1lNGJkLTRiYTYtOWM2Ny02ZWYxZGJmMmUxOWYifQ.eyJleHAiOjE2MzIwMzAwMzYsImlhdCI6MTYzMjAyODIzNiwianRpIjoiMmNlYTQwNzItMWE1Yi00M2I1LWE1M2YtY2Q3MDU0Mjg5NjY0IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL3F1aWNrLXN0YXJ0IiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL3F1aWNrLXN0YXJ0Iiwic3ViIjoiMzQ1YjFiY2EtOTgwNS00YjRiLWEwZjgtZGEyYzcwMTc2YzU5IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImZsb3ctZXhwZXJpbWVudC0xIiwic2Vzc2lvbl9zdGF0ZSI6ImYxZjhkMzkyLTExZDAtNDEzMi05MDEwLTkyOGQ1NmFmMjM2MiIsInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsInNpZCI6ImYxZjhkMzkyLTExZDAtNDEzMi05MDEwLTkyOGQ1NmFmMjM2MiJ9.ThX7d498RX_9WuUq7_aEWx_Xrh75tyqpcrMCiVI3aMk",
    "token_type": "Bearer",
    "not-before-policy": 1631743594,
    "session_state": "f1f8d392-11d0-4132-9010-928d56af2362",
    "scope": "email profile"
}

接著將呼叫Web API的參數調整一下,改成:

  • grant_type: refresh_token
  • client_id: flow-experiment-1
  • refresh_token: <剛剛取得的refresh_token>

然後同樣已POST的方法送出。這麼一來就可以取得新的存取權杖了,夠簡單吧!

refresh_token的作用

所以說爲什麼都可以透過密碼模式、code模式取得存取權杖了,還需要refresh_token?首先先看看關於存取權杖的返回值:

其中是有expires_in的,也就是存取權杖會過期的。如果每次過期,都需要資源擁有者在登入一次是非常麻煩的。所以才有refresh_token,這同樣類似 特殊密碼 。與code模式的特殊密碼有點不同的是,在限定時間內,可能可以透過refresh_token換取多次存取權杖。且與access_token不同的是,refresh_token使用在客戶端與授權伺服器;而access_token使用在客戶端與資源伺服器。相比access_tokenrefresh_token使用頻率沒那麼高,相對也就不容易被竊取,存活到過期時間通常也較長。藉由固定一段時間更新access_token的方式也可以降低一些安全隱患。

另外,refresh_token可以使用幾次,使用多長時間。是否都會返回refresh_token,是由授權伺服器決定的。也就是依照所需要的應用環境、所存在的安全風險,可能可以使用不同的策略。你可能頻繁的更換access_tokenrefresh_token,也有可能一用就是一年。

參考資料


上一篇
Day15 - 【概念篇】OAuth flows: Authorization Code
下一篇
Day17 - 【概念篇】OAuth flows: Client Credentials
系列文
用Keycloak學習身份驗證與授權40

尚未有邦友留言

立即登入留言