鉴于我有 3 个 oauth2 提供商,我如何自定义他们的客户端注册重定向-Uris。
它们并不都符合默认模式 /login/oauth2/code/{registrationId}
/openId
/login/oauth2/code/sf
/login/oauth2/code/flow
这是SecurityFilterChain
@Bean
public SecurityFilterChain clientSecurityFilterChain(
HttpSecurity http,
OAuth2ClientProperties bootClientProperties,
InMemoryClientRegistrationRepository clientRegistrationRepository,
SpringAddonsOidcProperties springAddonsOidcProperties,
LogoutProperties logoutProperties) throws Exception {
http.csrf(AbstractHttpConfigurer::disable);
http.oauth2Login(login -> login
.successHandler(trapsAuthenticationSuccessHandler())
.failureHandler(trapsAuthenticationFailureHandler())
.authorizationEndpoint(auth -> auth
.authorizationRequestResolver(new SpringAddonsOAuth2AuthorizationRequestResolver(bootClientProperties, clientRegistrationRepository, springAddonsOidcProperties.getClient())))
.redirectionEndpoint(endpoint -> endpoint
.baseUri("/openId/*"))
);
http.exceptionHandling(ex -> ex
.authenticationEntryPoint(trapsLoginUrlAuthenticationEntryPoint()));
http.logout(logout ->
logout.logoutSuccessHandler(new DelegatingOidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository, logoutProperties, "{baseUrl}")));
http.authorizeHttpRequests(auth ->
auth.anyRequest().permitAll());
return http.build();
}
这是配置:
### IDP: Azure AD B2C ###
spring.security.oauth2.client.provider.b2c.jwk-set-uri=${b2c-jwks-endpoint}
spring.security.oauth2.client.provider.b2c.authorization-uri=${b2c-authorization-endpoint}
spring.security.oauth2.client.provider.b2c.token-uri=${b2c-token-endpoint}
spring.security.oauth2.client.registration.b2c-retrieve.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.b2c-retrieve.client-id=${b2c-client-id}
spring.security.oauth2.client.registration.b2c-retrieve.client-secret=${b2c-client-secret}
spring.security.oauth2.client.registration.b2c-retrieve.provider=b2c
spring.security.oauth2.client.registration.b2c-retrieve.scope=${b2c-client-id},openid
spring.security.oauth2.client.registration.b2c-retrieve.redirect-uri={baseUrl}/openId
spring.security.oauth2.client.registration.b2c-save.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.b2c-save.client-id=${b2c-client-id}
spring.security.oauth2.client.registration.b2c-save.client-secret=${b2c-client-secret}
spring.security.oauth2.client.registration.b2c-save.provider=b2c
spring.security.oauth2.client.registration.b2c-save.scope=${b2c-client-id},openid
spring.security.oauth2.client.registration.b2c-save.redirect-uri={baseUrl}/openId
### IDP: Azure AD B2C ###
### IDP: Salesforce ###
sf-issuer=https://lv-direct--inttrn.sandbox.my.site.com/giportal
sf-secret=${secret-2}
spring.security.oauth2.client.provider.sf.issuer-uri=${sf-issuer}
spring.security.oauth2.client.registration.sf.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.sf.client-name=Salesforce (oidc)
spring.security.oauth2.client.registration.sf.client-id=${client-id-2}
spring.security.oauth2.client.registration.sf.client-secret=${client-secret-2}
spring.security.oauth2.client.registration.sf.redirect-uri={baseUrl}/login/oauth2/code/sf
spring.security.oauth2.client.registration.sf.provider=sf
spring.security.oauth2.client.registration.sf.scope=openid
### IDP: Salesforce IDP ###
### IDP: Flow ###
flow-issuer=https://id-lv-test.athenapaas.com/auth/realms/customer-portal
flow-secret=${secret-3}
spring.security.oauth2.client.provider.flow.issuer-uri=${flow-issuer}
spring.security.oauth2.client.registration.flow.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.flow.client-name=Flow (Keycloak - oidc)
spring.security.oauth2.client.registration.flow.client-id=${client-id-3}
spring.security.oauth2.client.registration.flow.client-secret=${client-secret-3}
spring.security.oauth2.client.registration.flow.redirect-uri={baseUrl}/login/oauth2/code/flow
spring.security.oauth2.client.registration.flow.provider=flow
spring.security.oauth2.client.registration.flow.scope=openid
### IDP: Flow ###
我可以看到正确的重定向 uri 已传递给提供程序,当提供程序重定向回来时,不会调用 oauth2 安全过滤器。
注意:我使用的是 Spring Boot 3.2.3 和 Spring Security 6.2.2
以下是调试日志:
logging.level.org.springframework.security=DEBUG
:: Spring Boot :: (v3.2.3)
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
2024-03-21 11:28:15,214 [LAP***::] DEBUG org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder - No authenticationProviders and no parentAuthenticationManager defined. Returning null.
2024-03-21 11:28:16,924 [LAP***::] INFO org.springframework.security.web.DefaultSecurityFilterChain - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@61a7930e, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@60eacbbf, org.springframework.security.web.context.SecurityContextHolderFilter@7f129873, org.springframework.security.web.header.HeaderWriterFilter@40f7fb45, org.springframework.web.filter.CorsFilter@36e6e59f, org.springframework.security.web.authentication.logout.LogoutFilter@c521a79, org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@5ce59833, org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter@22071f0, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@504f2bcd, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@51dd74a0, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@676beb9f, org.springframework.security.web.access.ExceptionTranslationFilter@36afd06f, org.springframework.security.web.access.intercept.AuthorizationFilter@2d3bb293]
2024-03-21 11:29:18,839 [LAP***::] DEBUG org.springframework.security.web.FilterChainProxy - Securing OPTIONS /config
2024-03-21 11:29:19,036 [LAP***::] DEBUG org.springframework.security.web.FilterChainProxy - Securing POST /config
2024-03-21 11:29:19,079 [LAP***::] DEBUG org.springframework.security.web.FilterChainProxy - Secured POST /config
2024-03-21 11:29:19,312 [LAP***:0502ff48-95de-42f0-8ef6-2a02a1aa9e4a:98910f08-2904-464b-801f-e69ae6d5e773] DEBUG org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext
2024-03-21 11:29:19,328 [LAP***::] DEBUG org.springframework.security.web.savedrequest.HttpSessionRequestCache - Saved request https://localhost:8444/config?continue to session
2024-03-21 11:29:19,331 [LAP***::] DEBUG org.springframework.security.web.savedrequest.HttpSessionRequestCache - Saved request https://localhost:8444/config?continue to session
2024-03-21 11:29:19,506 [LAP***::] DEBUG org.springframework.security.web.FilterChainProxy - Securing GET /oauth2/authorization/b2c-retrieve
2024-03-21 11:29:19,551 [LAP***::] DEBUG org.springframework.security.web.DefaultRedirectStrategy - Redirecting to https://sys-login.lvgig.co.uk/270***/oauth2/v2.0/authorize?response_type=code&client_id=f3b***&scope=f3b***%20openid&state=55ViNeTEVyXndja9l69-vTTTZgwPOj1qeSwnXBf_zhA%3D&redirect_uri=https://localhost:8444/openId&nonce=7XVzDwtfW3D-zgoioI1seJly7dtY4Woy5-XNxRKSTic&p=B2C_1A_RPRetrieveQuoteQA3&product=car&style=new&ujt=retrievequote&response_mode=form_post&code_challenge=O53oNMjGap2D3B1GBReVh7knG72A4ngN4vc9i5Vj5vc&code_challenge_method=S256
2024-03-21 11:30:02,729 [LAP***::] DEBUG org.springframework.security.web.FilterChainProxy - Securing POST /openId
2024-03-21 11:30:02,748 [LAP***::] DEBUG org.springframework.security.web.FilterChainProxy - Secured POST /openId
2024-03-21 11:30:02,809 [LAP***::] ERROR com.lv.gi.journeyengine.services.core.impl.DefaultWorkflowServiceImpl - No Workflow found given requestContext
更新1: 我尝试根据以下内容更改以下内容:https://docs.spring.io/spring-security/reference/servlet/oauth2/login/advanced.html#oauth2login-advanced-redirection-endpoint,仍然不起作用。
${je-url} --> {baseUrl} in the config redirect-uri's
.baseUri("/openId") --> .baseUri("/openId/*")
我已经更新了原来的问题以反映这一点。
更新2: 如果我从 SecurityFilterChain 中注释掉以下内容,Salesforce 和 Flow 提供商将再次工作:
// .authorizationEndpoint(auth -> auth
// .authorizationRequestResolver(new SpringAddonsOAuth2AuthorizationRequestResolver(bootClientProperties, clientRegistrationRepository, springAddonsOidcProperties.getClient())))
// .redirectionEndpoint(endpoint -> endpoint
// .baseUri("/openId/*"))
我现在怀疑,我如何使用 SpringAddonsOAuth2AuthorizationRequestResolver (来自 https://github.com/ch4mpy/spring-addons)导致其他提供程序崩溃,并可能增加此问题的混乱。
对重定向 uri 的调用由 Spring Security 的 OAuth2LoginAuthenticationFilter 处理
通常通过 Spring Security DSL 配置,例如:
@Bean
public SecurityFilterChain clientSecurityFilterChain(HttpSecurity http) throws Exception {
http.oauth2Login(login -> login
.redirectionEndpoint(endpoint -> endpoint
.baseUri("/openId"))
);
return http.build();
}
正如我发现的,如果重定向 uri 需要包含 2 种模式,这允许有限的范围:/openId & /login/oauth2/code/*
但是我发现我可以对 OAuth2LoginAuthenticationFilter 进行后处理以允许自定义重定向 uri 匹配,如下所示:
private static ObjectPostProcessor<OAuth2LoginAuthenticationFilter> postProcessor = new ObjectPostProcessor<>() {
@Override
public <O extends OAuth2LoginAuthenticationFilter> O postProcess(O object) {
object.setRequiresAuthenticationRequestMatcher(
new OrRequestMatcher(
AntPathRequestMatcher.antMatcher("/openId"),
AntPathRequestMatcher.antMatcher("/login/oauth2/code/*")));
return object;
}
};
@Bean
public SecurityFilterChain clientSecurityFilterChain(HttpSecurity http) throws Exception {
http.oauth2Login(login -> login
.addObjectPostProcessor(postProcessor)
);
return http.build();
}