keycloak~token有效期與session有效期的調研
一 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是無不效期的。
浙公網安備 33010602011771號