【问题标题】:EnableOAuth2Sso Access token expires after 1 hour of activity and UserRedirectRequiredException thrownEnableOAuth2Sso 访问令牌在活动 1 小时后过期并引发 UserRedirectRequiredException
【发布时间】:2021-04-17 17:54:06
【问题描述】:

我已经使用 spring-security-oauth2-autoconfigure 2.1.8.RELEASE 实现了 SSO,它在首次启动时运行良好。我可以登录并调用我的后端 api。

活动一小时后,由于访问令牌已过期且 OAuth2RestTemplate 无法刷新,因此由于 UserRedirectRequiredException 而对我的后端 api 的 REST 调用失败。我得到了这个堆栈:

org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getRedirectForAuthorization(AuthorizationCodeAccessTokenProvider.java:359)
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:205)
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:148)
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:121)
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)

我的应用配置代码是:

@Configuration
@EnableOAuth2Sso
@Order(value = 0)
public class AppConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private Environment env;

    @Autowired
    OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails;

    @Autowired
    OAuth2ClientContext oauth2ClientContext;

    @Autowired
    private OAuth2ClientContextFilter oauth2ClientContextFilter;

    @Value("${security.oauth2.resource.user-info-uri}")
    private String userInfoUri;
    @Value("${security.oauth2.client.access-token-uri}")
    private String accessTokenUri;
    @Value("${security.oauth2.client.user-authorization-uri}")
    private String userAuthorizationUri;
    @Value("${security.oauth2.client.client-id}")
    private String clientID;
    @Value("${security.oauth2.client.client-secret}")
    private String clientSecret;
    @Value("${security.oauth2.client.pre-established-redirect-uri}")
    private String preEstRedirectUri;
    @Value("#{'${security.oauth2.client.scope}'.split(' ')}")
    private List<String> scope;

    @Override
    public void configure(HttpSecurity http) throws Exception {

        String logoutUrl = env.getProperty("endSessionEndpoint") + "?post_logout_redirect_uri=" +
                URLEncoder.encode(env.getProperty("homePage"), "UTF-8");

        http.requiresChannel().anyRequest().requiresSecure();
        http.antMatcher("/**")
                .authorizeRequests(a -> a
                    .antMatchers("/", "/static/**", "/webjars/**", "/login**", "/error**", "/js/**", "/css/**", "/img/**").permitAll()
                    .anyRequest().authenticated()
                )
                .csrf(c -> c
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                )
                .logout(l -> l
                    .deleteCookies()
                    .invalidateHttpSession(true)
                    .logoutSuccessUrl(logoutUrl)
                );
        http.addFilterAfter(oauth2ClientContextFilter, SecurityContextPersistenceFilter.class);
        http.addFilterBefore(swqSSOFilter(), BasicAuthenticationFilter.class);
        http.exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint());
    }

    private Filter swqSSOFilter() {
    private Filter swqSSOFilter() {
        OAuth2ClientAuthenticationProcessingFilter azureSsoFilter = new OAuth2ClientAuthenticationProcessingFilter(preEstRedirectUri);
        OAuth2RestTemplate oauth2RestTemplate = new OAuth2RestTemplate(oAuth2ProtectedResourceDetails, oauth2ClientContext);
        azureSsoFilter.setRestTemplate(oauth2RestTemplate);
        UserInfoTokenServices tokenServices = new UserInfoTokenServices(userInfoUri, oAuth2ProtectedResourceDetails.getClientId());
        tokenServices.setRestTemplate(oauth2RestTemplate);
        azureSsoFilter.setTokenServices(tokenServices);
        return azureSsoFilter;
    }

    @Bean
    public AuthenticationEntryPoint unauthorizedEntryPoint() {
        return (request, response, authException) -> response.sendRedirect(preEstRedirectUri);
    }

    @Bean
    public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, OAuth2ProtectedResourceDetails details) {
        return new OAuth2RestTemplate(details, oauth2ClientContext);
    }

    @Bean
    public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(
        OAuth2ClientContextFilter filter) {
      FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
      registration.setFilter(filter);
      registration.setOrder(-100);
      return registration;
    }
}

我关注了很多 stackoverflow 帖子,但没有一个解决方案对我有用。 有人可以告诉我我做错了什么吗?

【问题讨论】:

  • 嗨@Ranbir,为了增加你的令牌寿命,你需要在你的代码中实现刷新令牌。请参考ms docs
  • 我在范围中添加了“offline_access”,在grant_type中添加了“authorization_code”来获取刷新令牌并使用正确的令牌服务提供商,显然它解决了这个问题。
  • @感谢您的更新。我会将我的答案从 cmets 转移到 answer。

标签: spring azure spring-boot azure-active-directory single-sign-on


【解决方案1】:

来自 cmets 的移动答案,

为了增加你的令牌寿命,你需要在你的代码中实现刷新令牌。请参考ms docs。

【讨论】:

    猜你喜欢
    • 2020-06-07
    • 2012-11-13
    • 2017-08-17
    • 2017-11-15
    • 2018-12-23
    • 2018-01-20
    • 1970-01-01
    • 2019-10-05
    • 2014-08-10
    相关资源
    最近更新 更多