带有 oidc 的 Spring Security:刷新令牌
Posted
技术标签:
【中文标题】带有 oidc 的 Spring Security:刷新令牌【英文标题】:Spring Security with oidc: refresh the tokens 【发布时间】:2019-01-18 06:49:43 【问题描述】:带有 Spring Security 5 的 Spring Boot 2 可以配置为使用 openID 连接 ID 提供程序进行身份验证。 我设法通过配置 Spring Security 来设置我的项目 - 它适用于各种完美预配置的安全机制,例如缓解会话固定。
但似乎Spring Security在令牌过期时不会自行刷新令牌(存储在会话中)。
是否有这样的设置,还是我必须自己照顾刷新?
更新:Spring Boot 2.1 已经发布,是时候重新审视这个问题了。我仍然不知道现在是否可以自动刷新 accessToken,或者我是否必须为此编写代码......
【问题讨论】:
【参考方案1】:即使是 100 个代表点的赏金也没有产生答案。所以我猜目前没有实现使用 Spring Security 自动刷新访问令牌的机制。
一种有效的替代方法似乎是使用能够刷新令牌的 spring boot keycloak 适配器。
【讨论】:
最新的docs.spring.io/spring-security/site/docs/current/reference/… 文档指出,如果给定了刷新令牌,spring security 应该自动尝试刷新它。 github.com/spring-projects/spring-security/wiki/…也支持,支持 @DarrenForsythe 感谢链接 - 将其作为答案如何,以便我可以将赏金分配给您? 所以看起来网络客户端处理了刷新令牌。因此,据我所知,应用程序会在端点上收到请求,并且只有当控制器尝试通过 webClient 使用访问令牌时,才会使用刷新令牌。有趣的概念... Keycloak 适配器已经用传入的请求刷新了 accesstoken... 我不确定支持使用 webclient 获取和刷新令牌等的底层实现,我目前遇到了自己的问题,但从我看到的代码来看如果您已经过身份验证,它会尝试刷新刷新令牌是否在对给定提供者的请求上可用的身份验证对象。也可以获取较低级别的 bean 并自己做,spring.io/blog/2018/03/06/… 有一个例子 知道如何使用新的春季安全版本来做到这一点???我们可以使用任何自定义过滤器来刷新令牌并更新主体吗?【参考方案2】:根据文档,
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#webclient
使用正确配置的 WebClient 时,如文档中所述,它将自动刷新。
Spring Security 会自动刷新过期的令牌(如果有刷新令牌的话)
支持刷新令牌的特征矩阵也支持这一点。
https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Features-Matrix
有一篇关于 Spring Security 5 的较早的博客可以让您访问可以手动执行此操作的 bean,
Authentication authentication =
SecurityContextHolder
.getContext()
.getAuthentication();
OAuth2AuthenticationToken oauthToken =
(OAuth2AuthenticationToken) authentication;
OAuth2AuthorizedClientService 将在 Spring 应用程序上下文中自动配置为 bean,因此您只需将其注入到您将使用它的任何地方。
OAuth2AuthorizedClient client =
clientService.loadAuthorizedClient(
oauthToken.getAuthorizedClientRegistrationId(),
oauthToken.getName());
String refreshToken = client.getRefreshToken();
而且,现在找不到它,但我认为 OAuth2AuthorizedClientExchangeFilterFunction
的一部分有调用来进行刷新。
【讨论】:
感谢这个详细的答案!【参考方案3】:根据https://github.com/spring-projects/spring-security/issues/6742 看来是故意不刷新令牌:
ID 令牌通常带有到期日期。 RP 可能 依靠它来使 RP 会话过期。
春天没有。最后提到了两个增强功能,它们应该可以解决一些刷新问题 - 两者都仍然开放。
作为一种解决方法,我实现了一个 GenericFilterBean,它检查令牌并清除当前安全上下文中的身份验证。因此需要一个新的令牌。
@Configuration
public class RefreshTokenFilterConfig
@Bean
GenericFilterBean refreshTokenFilter(OAuth2AuthorizedClientService clientService)
return new GenericFilterBean()
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication instanceof OAuth2AuthenticationToken)
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
OAuth2AuthorizedClient client =
clientService.loadAuthorizedClient(
token.getAuthorizedClientRegistrationId(),
token.getName());
OAuth2AccessToken accessToken = client.getAccessToken();
if (accessToken.getExpiresAt().isBefore(Instant.now()))
SecurityContextHolder.getContext().setAuthentication(null);
filterChain.doFilter(servletRequest, servletResponse);
;
此外,我必须将过滤器添加到安全配置中:
@Bean
public WebSecurityConfigurerAdapter webSecurityConfigurer(GenericFilterBean refreshTokenFilter)
return new WebSecurityConfigurerAdapter()
@Override
protected void configure(HttpSecurity http) throws Exception
http
.addFilterBefore(refreshTokenFilter, AnonymousAuthenticationFilter.class)
在 2.2.7.RELEASE 版本中使用 spring-boot-starter-parent 和依赖项实现:
spring-boot-starter-web spring-boot-starter-security spring-boot-starter-oauth2-client我很欣赏有关此解决方法的意见,因为我仍然不确定 Spring Boot 中是否真的需要这样的开销。
【讨论】:
对于仍在寻找解决方案的人来说,这里是docs.spring.io/spring-security/site/docs/5.1.2.RELEASE/…。 WebClient 是补救措施。以上是关于带有 oidc 的 Spring Security:刷新令牌的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security 和 OpenID Connect (OIDC)
Spring Security:提取 oidc 角色声明给 Spring 当局
针对 Azure OIDC OAuth2 流的 Spring Security
在多租户 stup 中使用 Spring Security OAuth 动态注册 OIDC 客户端