keycloak~token有效期與session有效期

张占岭發表於2024-10-16

一 refresh_token重新整理access_token

Keycloak會話管理中,獲取到accessToken和refreshToken後,基於accessToken交換使用者資料或者參與KeycloakAPI的請求,當accessToken過期的時候,可使用refreshToken去交換新的accessToken和refreshToken。

這塊根據之前的refresh_token就得到了一個新的token物件

refresh_token和access_token有效期配置

  • refresh_token的有效期一般比access_token的長,這也就是透過refresh_token來換取新的access_token的一個前提,下面來配置一個這兩個token的超時時間。
  • refresh_token超時時間refresh_expires_in,在realms settings中,選擇tokens進行配置,對SSO Session Max進行設定

access_token超時時間expires_in,在realms settings中,選擇tokens進行配置,對Access Token Lifespan進行設定。

這個使用者會話,對應的sessionId(session_state)可以在瀏覽器cookie中找到,或者在kc管理後臺的使用者-》會話中檢視,這個sessionId被客戶端訪問,都會重新整理這個“開始”時間,和“最後訪問”時間,當你的access_token過期後,你透過refresh_token去重新整理access_token時,這個“最後訪問”時間也會更新,如圖

如果使用者訪問資源,在token過期,而refresh_token(sso session max)未過期時,你可以透過refresh_token來獲取新的token,這時會有新的會話產生;但如果refresh_token也過期時,它將跳轉到登入頁,從新進行認證,會話也就被刪除了。

三 refresh_token過期時間的配置

領域設定->Tokens中,有四個選項用來控制refresh_token的超時時間

  • SSO Session Idle
  • SSO Session Max
  • Client Session Idle
  • Client Session Max

下圖的4個選項,配置是有問題的,正確的配置應該是最長時間大於空閒時間,下面配置無意義,這時有效性使用4個選項中最小的值【sso會話空閒時間,sso會話最長時間,client session Idle和client session Max】

如果正常配置的話,當空閒時間和最長時間不相同時,真實的refresh_token_expire時間將取決於client Session Idle的值,如下配置

當refresh_token到期之後到達 ( session max的時間 ) ,session就失效了,而它並不會立即清除,它會交給keycloak進行維護,最長是session max時間後自動清除,而使用者如果在這個時間之前進行refresh_token時,會提示token是不活動的,這時會話也會也被清空,表示令牌過期了,如下面兩張圖:

當session idle和session max不相同時(sso session max和client session max),使用者的會話會在sso session max到期時刪除,而sso session max是全域性的,不能在客戶端單獨配置,一個會話是在什麼時間被系統回收,主要由以下6個引數決定,SSO Session Max和Client Sesssion Max我們設定一個即可,它在keycloak後臺清理session時會以最長的為準,而當session達到session idle時間時,如果使用者主動重新整理token,session也會被主動刪除,不會等session max時間達了再刪。

四 Session Idle和Session Max的作用

會話的空閒時間(Idle),是指在多長時間之內沒有使用refresh_token進行重新整理,這個會話(session_state)就過期,無法再直接用refresh_token去換新的token了,這時使用者就需要重新回到登入頁,完成新的認證;這主要針對長時間不操作的使用者,kc需要讓它重新完成使用者名稱密碼的確認。

注意:如果開啟了“記住我”這個功能,因為如果開啟“記住我”功能之後,你的會話空閒時間等於“記住我空閒時間”,你的”sso session idle”配置將失效,如果記住我配置了最大時間和空閒時間,那麼token的生成和校驗都將使用記住我的時間,如圖keycloak14.0.0.-services裡AuthenticationManage.isSessionValid的原始碼。

session idle在判斷上有2分鐘的誤差,主要考慮DC叢集的資料同步,比如idle有效期5分鐘,那麼真正過期就是5+2為7分鐘】當到7分鐘後,你獲取session是否線上時,結果會返回false.

上面程式碼中,isSessionValid方法會在驗證token和重新整理token時都會進行執行,我們如果希望將session idle和session max去正確使用,還需要修改kc原始碼中的org.keycloak.protocol.oidc
.TokenManager.refreshAccessToken()方法中的程式碼,將verifyRefreshToken方法引數中的checkExpiration改成false,如圖:

最後,下圖配置了access_token有效期2分鐘,refresh_token最長30天,會話空閒為7天;配置的作用為:使用者每2分鐘access_token會過期,然後使用者透過refresh_token去換新的access_token,如果使用者7天沒有換token,這個會話就過期,如果會話已經產生了30天,則會話也過期,使用者就會返回登入頁,重新認證。

事實上,當session idle 和session max相等時,你的refresh_token的過期時間會一直遞減,從第一次申請這個refresh_token開始,這個過期時間就固定了,它和你換新token是無關係的;但如果session idle和 session max不相等時(max>idle),你每換新token,你的新換的refresh_token的過期時間都從頭開始算,它的大小等於session idle的大小,這也是你在session idle時間內沒有去重新整理token而會話就會過期的原因,請注意:我們要用新換回的refresh_token把之前的refresh_token也替換掉,因為老的已經過期了。

五 offline_access角色讓refresh_token永不過期

對於使用者登入後,如果授權碼模式,如果希望refresh_token永不過期,可以使用offline_access這種scope ,前提是你在認證介面呼叫時,scope地方需要新增offline_access這個選項,並且你是授權碼的認證方式,如圖:

當前客戶端模板裡,也是需要新增這個offline_access的客戶端模板

為指定的使用者新增offline_access角色,如果沒有這個角色,需要手動新增。

當沒有開啟Offline session Max limit時,你的重新整理token就是永不過期的,如圖

如果希望控制refresh_token的有效期,可以開啟限制

生成的refresh_token的超時時間將是5分鐘,300秒,還是上面4個配置,誰小用誰,如圖:

Refresh_token的JWT串,解析後Typ有兩種型別,Refresh和Offline,前者的是透過SSO Session Max來控制它的有效期,而後者Offline就是申請token時,使用的scope包含了offline_access,它對應的refresh_token是無不效期的。

相關文章