钦娅芬 发表于 2025-6-9 15:13:26

keycloak~refresh_token的深度总结

内容大纲

[*]keycloak关于会话有效期的配置
[*]refresh_token作用
[*]refresh_token使用规范
[*]keycloak开启refresh_token的限制
[*]refresh_token时的错误汇总
[*]keycloak中refresh_token的底层逻辑
[*]session过期时间的清除策略
一 keycloak关于会话有效期的配置

1. session配置说明及推荐配置`

参数名称推荐配置说明Access Token Lifespan5分钟(300秒)access_token的有效期。SSO Session Idle7天(604800秒)用户会话的空闲时间。SSO Session Max1年(31536000秒)用户会话的最大持续时间。Client Session Idle7天(604800秒)客户端会话的空闲时间。Client Session Max1年(31536000秒)客户端会话的最大持续时间。Offline Session Idle7天(604800秒)离线会话的空闲时间(可选)。Offline Session Max1年(31536000秒)离线会话的最大持续时间(可选)。SSO Session Idle Remember Me7天(604800秒)“记住我”会话的空闲时间(可选)。SSO Session Max Remember Me1年(31536000秒)“记住我”会话的最大持续时间(可选)。2. 会话最后更新时间(这对session idle会产生影响)


[*]去登录页换取授权码后,这个时间会更新
[*]刷新token时,这个时间会更新
[*]主动调用introspect验证access_token有效性时,这个时间会更新
[*]授权码登录,code换token时,这个时间不更新
[*]使用access_token访问具体资源时,这个时间不更新
3. code换token时去掉client限制引发的问题


[*]当我们通过客户端a申请授权码code后,我们使用客户端b获取了access_token和refresh_token
[*]这时,我们通过refresh_token来刷新token时,是不成功的,会有两种场景错误
[*]当你使用客户端a来刷新token时,会出现Unmatching clients 400错误
[*]当你使用客户端b来刷新token时,会出现Session doesn't have required client 400错误

[*]所以,否建议把code换token时client_id的限制去掉,这就引发刷新token的问题
二 refresh_token作用

1. 主要作用

refresh_token是用来刷新access_token的,当access_token过期后,可以通过refresh_token来获取新的access_token,而不需要重新登录。
2. 动态会话续期规则


[*]SSO Session Max的限制:

[*]无论用户如何活跃或使用refresh_token,会话的总持续时间不能超过SSO Session Max。
[*]例如,如果SSO Session Max设置为1年,即使用户每天都在使用App,1年后会话也会过期,用户需要重新登录。

[*]SSO Session Idle的限制:

[*]如果用户在SSO Session Idle时间内没有任何操作,会话将过期,即使用户使用refresh_token也无法续期。

三 refresh_token使用规范

1. 使用方法

curl --location --request POST 'https://{keycloak}/auth/realms/{realm}/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token={refresh_token}' \
--data-urlencode 'client_id={client_id}' \
--data-urlencode 'client_secret={client_secret}'**2. 使用规范


[*]每个refresh_token只能使用一次,不可重复使用,KC这边也会进行回收它
[*]通过refresh_token获取新的token时,返回值里会带有新的refresh_token,我们应该使用新的refresh_token来覆盖上一次的refresh_token
[*]refresh_token有效期取决于keycloaktokenssso session idle的值,即会话空闲时间,如果refresh_token在这个时间内没有使用,那么它会失效
[*]refresh_token失效后,当前会话session_state也即失效,此时,需要重新登录
注意:sso session max表示会话最大有效期,在这个时间范围内,用户不需要重新登录,sso session idle表示会话空闲时间,在这个时间内用户不进行操作,会话也会过期(在下次用户主动刷新token时,这个会话将会从keycloak后台会话管理中删除),session max表示最大会话时间,相当于会话在缓存里的有效期,到期后自动清除(缓存自身的特性,不需要keycloak干预;而离线会话由于是存储到mysql的,这块是通过任务调度进行清理的),这两种情况满足后,用户都需要重新登录,这两个值必须大于0;单位为分,小时,天,不支持永久有效期。
用户在刷新token时,如果会话已经失效(session idle到期,而不是session max到期,后者会自动清理),则删除它(而不是keycloak主动检查的)

四 keycloak开启refresh_token的限制


五 refresh_token时的错误汇总


[*]当refresh_token超过限制时,会返回invalid_grant错误,此时,需要重新登录

[*]再次使用refresh_token,同样返回状态码400,但返回消息体会有变化

[*]如果当前session已经失效,即会话达到了session max的时间,将返回下面错误

[*]如果当前客户端与token客户端不一致,将返回下面错误

[*]如果当前当前端开启了同意许可,将返回下面错误

六 keycloak中refresh_token的底层逻辑


[*]validateToken方法

[*]通过session_state获取userSession对象,如果userSession对象为空,说明refresh_token已经失效,返回400 Session not active

[*]isSessionValid方法主要验证会话是否有效,主要判断以下几个部分


[*]用户会话是否存在,user-session是否存在
[*]获取session空闲时间和最大时间,它们的逻辑与是否开启记住我有关
[*]会有两层时间的比较,来确定session是否有效

[*]第一层,session空闲时间是否大于(当前时间-最后刷新token时间-容错窗口期(120秒))
[*]第二层,session最大时间是否大于(当前时间-session开始时间)

[*]上面两层同时满足,说明session是有效的


[*]从userSession中获取当前用户对象
[*]判断用户是否有效

[*]如果用户被删除,返回400 Unknown user
[*]如果用户状态为禁用,返回400 User disabled
[*]如果用户需要一个必要的行为,返回400 User has required action

[*]判断当前refresh_token的建立时间是否早于会话开始时间,正常情况下肯定是晚于会话时间,如果早于,返回400 Refresh toked issued before the user session started
[*]判断当前userSession是否在当前client_id对应的clientSession里,如果没有,返回400 Session doesn't have required client
[*]判断当前refresh_token里的azp是否与请求参数client_id相同,不同返回400 Unmatching clients
[*]验证refresh_token是否被篡改
[*]检查客户端是否有consent的授权许可同意,如果开启了,会返回400 Client no longer has requested consent from user
[*]成功建立新的token对象,整个刷新token流程结束
{
    "access_token": "",
    "expires_in": 120,
    "refresh_expires_in": 300,
    "refresh_token": "",
    "token_type": "Bearer",
    "id_token": "",
    "not-before-policy": 1740449130,
    "session_state": "424b8022-600d-421e-a45d-e0315d1a524d",
    "scope": "openid roles email profile"
}七 session过期时间的清除策略

1. 普通会话


[*]通过infinispan缓存里的过期时间自动管理,到期后,自动清除
2. 离线会话


[*]keycloak通过定时器,实现离线会话的清理,它存到mysql中,这是没有过期时间可言的,可查看offline_user_session相关的内容
[*]org.keycloak.services.scheduled.ScheduledTaskRunner # 默认900秒(15分钟)执行一次

[*]org.keycloak.services.scheduled.ClearExpiredUserSessionsTask

[*]org.keycloak.models.map.authSession.removeExpired



来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: keycloak~refresh_token的深度总结