spring security 5.7 - multiple authentication provider without WebSecurityConfigurerAdapter - spring

I'm using spring security 5.7 and WebSecurityConfigurerAdapter is deprecated.
I want use multiple Authentication Provider(Ldap and Dao) but ldap provider not working and spring security just call DaoAuthenticationProvider.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {
#Autowired
private JWTTokenFilter jwtTokenFilter;
#Autowired
private LdapAuthProvider ldapAuthProvider;
#Autowired
private UserService userService;
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors()
.and().csrf().disable()
.headers().frameOptions().disable()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().antMatchers("/api/test/**", "/auth/**", "/h2-console/**").permitAll()
.and().authorizeRequests().anyRequest().authenticated()
.and().addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
http.authenticationProvider(ldapAuthProvider);
http.authenticationProvider(authenticationProvider());
return http.build();
}
#Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
when remove DaoAuthenticationProvider then LdapAuthProvider is work.
what's the problem?
edit:
i want use exposed AuthenticationManager in whole app like this:
#Autowired
private AuthenticationManager authenticationManager;
#PostMapping("/login")
public ResponseEntity<?> login(#RequestBody AuthRequest authRequest) {
if(authRequest.getUsername() == null || authRequest.getPassword() == null) {
return ResponseEntity.badRequest().build();
}
Authentication authenticate = null;
try {
authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
authRequest.getUsername(),
authRequest.getPassword()));
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(401).build();
}
but this AuthenticationManager not contain my custom AuthenticationProvider

Below is an example of using two authentication providers (Ldap and Dao) in Spring Security 5.7. This is in the context of a traditional web application using form login. The trick was to explicitly set the AuthenticationManager to use (i.e. ProviderManager) in the filter chain and reference both authentication providers:
#Bean
public ActiveDirectoryLdapAuthenticationProvider getAdAuthProvider(CustomLdapUserDetailsMapper customLdapUserDetailsMapper) {
ActiveDirectoryLdapAuthenticationProvider authProvider = new ActiveDirectoryLdapAuthenticationProvider(domain, urls);
authProvider.setSearchFilter("(&(objectClass=user)(sAMAccountName={1}))");
authProvider.setUserDetailsContextMapper(customLdapUserDetailsMapper);
return authProvider;
}
#Bean
public DaoAuthenticationProvider getDaoAuthProvider(CustomDatabaseUserDetailsService customDatabaseUserDetailsService) {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(customDatabaseUserDetailsService);
provider.setPasswordEncoder(new BCryptPasswordEncoder());
return provider;
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http, ActiveDirectoryLdapAuthenticationProvider adAuthProvider, DaoAuthenticationProvider dbAuthProvider) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
...
.anyRequest().hasAuthority("ADMIN")
.and().formLogin().loginPage("/login").permitAll()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll()
.and().authenticationManager(new ProviderManager(List.of(adAuthProvider, dbAuthProvider)));
return http.build();
}

#Brice Roncace's answer above worked for me too. Just to add on to that, since you want the AuthenticationManager exposed as a bean, this is what I did:
#Bean
public AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(List.of(authenticationProvider1(), authenticationProvider2()));
}
and then wire this bean into the config:
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authenticationManager(authenticationManager())
...

Related

Error occured when Spring Security CustomLoginFilter is applied! somebody help me

I want to apply CustomLoginProcessingFilter in my application but i can't figure out how it works!
I'm using Spring boot 2.7.2, the lastest version when i started studying this.
here's my code
Another custom providers or custom detail services work so well.
But, once i enroll new bean fore login processing filter, AjaxLoginProcessingFilter, they tell me that i need to specify authentitcationManager!
so, i added at filterChain method this in SecurityConfig.java, but it doesn't work.
enter image description here
/**
----------------- SecurityConfig -------------------------
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
#RequiredArgsConstructor
public class SecurityConfig {
private final CustomAuthenticationSuccessHandler authenticationSuccessHandler;
private final CustomAuthenticationFailureHandler authenticationFailureHandler;
private final FormAuthenticationDetailsSource authenticationDetailsSource;
private final AjaxLoginProcessingFilter ajaxLoginProcessingFilter;
#Bean
AuthenticationManager authenticationManager(AuthenticationManagerBuilder builder) throws Exception {
return builder.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(registry -> {
registry.antMatchers("/","/users","user/login/**","/login*").permitAll()
.antMatchers("/mypage").hasRole("USER")
.antMatchers("/messages").hasRole("MANAGER")
.antMatchers("/config").hasRole("ADMIN")
.anyRequest().authenticated();
}).formLogin(login -> {
login.loginPage("/login")
.loginProcessingUrl("/login_proc")
.defaultSuccessUrl("/")
.authenticationDetailsSource(authenticationDetailsSource)
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler)
.permitAll();
}).exceptionHandling(exception -> {
exception.accessDeniedHandler(accessDeniedHandler());
})
.addFilterBefore(ajaxLoginProcessingFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
#Bean
public AccessDeniedHandler accessDeniedHandler(){
CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler();
accessDeniedHandler.setErrorPage("/denied");
return accessDeniedHandler;
}
#Bean
public WebSecurityCustomizer webSecurityCustomizer() throws Exception {
return (web) -> web.ignoring().antMatchers("/resources/**");
}
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
/*Explanation:
In the old version you inject AuthenticationManagerBuilder, set userDetailsService, passwordEncoder and build it.
But authenticationManager is already created in this step.
It is created the way we wanted (with userDetailsService and the passwordEncoder).
https://stackoverflow.com/questions/72381114/spring-security-upgrading-the-deprecated-websecurityconfigureradapter-in-spring
*/
#Bean
CustomUserDetailsService customUserDetailsService() {
return new CustomUserDetailsService();
}
#Bean
public AuthenticationProvider authenticationProvider() {
return new CustomAuthenticationProvider();
}
}
-++------------------ AjaxLoginProcessingFilter ---------------------
#Component("loginProcessingFilter")
public class AjaxLoginProcessingFilter extends AbstractAuthenticationProcessingFilter {
private ObjectMapper objectMapper = new ObjectMapper();
public AjaxLoginProcessingFilter() {
super(new AntPathRequestMatcher("/api/login"));
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
if(isAjax(request)){
throw new IllegalStateException("Authentication is not supported");
}
AccountDto accountDto = objectMapper.readValue(request.getReader(), AccountDto.class);
if(StringUtils.isEmpty(accountDto.getUsername()) || StringUtils.isEmpty(accountDto.getPassword())){
throw new IllegalArgumentException("Username or password is not empty");
}
AjaxAuthenticationToken authenticationToken = new AjaxAuthenticationToken(accountDto.getUsername(), accountDto.getPassword());
return getAuthenticationManager().authenticate(authenticationToken);
}
private boolean isAjax(HttpServletRequest request) throws IOException {
if("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))){
return true;
}
return false;
}
}

Getting Spring Security KeyCloak Adapter and Spring Security ACL to play together

I have a grails 4 application that uses Spring Security ACL to protect access to resources. I am trying to incorporate KeyCloak SSO into the mix and unable to figure out how to bridge the two worlds. I've configured KeyCloak Authentication and after login can see keyCloakPrincipal on SpringSecurity Context. How do I go from here to set up the roles for ACL?
here is my keycloak adapter:
#Configuration
#EnableWebSecurity
#ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(
AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider
= keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(
new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/customers*")
.hasRole("user")
.anyRequest()
.permitAll();
}
}
and here is my ACL:
#Autowired
DataSource dataSource;
#Bean
public AclAuthorizationStrategy aclAuthorizationStrategy() {
return new AclAuthorizationStrategyImpl(
new SimpleGrantedAuthority("ROLE_ADMIN"));
}
#Bean
public PermissionGrantingStrategy permissionGrantingStrategy() {
return new DefaultPermissionGrantingStrategy(
new ConsoleAuditLogger());
}
#Bean
public EhCacheBasedAclCache aclCache() {
return new EhCacheBasedAclCache(
aclEhCacheFactoryBean().getObject(),
permissionGrantingStrategy(),
aclAuthorizationStrategy()
);
}
#Bean
public EhCacheFactoryBean aclEhCacheFactoryBean() {
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
ehCacheFactoryBean.setCacheName("aclCache");
return ehCacheFactoryBean;
}
#Bean
public EhCacheManagerFactoryBean aclCacheManager() {
return new EhCacheManagerFactoryBean();
}
#Bean
public LookupStrategy lookupStrategy() {
return new BasicLookupStrategy(
dataSource,
aclCache(),
aclAuthorizationStrategy(),
new ConsoleAuditLogger()
);
}
How do I

Spring Security Authentication Server with multiple authentication providers for client_credentials

I am trying to setup an authentication server using Spring Security authentication and need to have multiple authentication providers for client_credentials.
I have done quite a bit of searching and have yet to find how to configure spring security to add my custom authentication provider to the client credentials authentication provider list. Every approach I found results in the same 2 providers for the client credentials authentication. The anonymous and the dao authentication providers.
I would appreciate any help in figuring out how to configure the the spring security authentication server for multiple client credential authentication providers.
AuthorizationServerConfig
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
{
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(passwordEncoder())
.allowFormAuthenticationForClients();
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("sampleClientId").authorizedGrantTypes("implicit")
.scopes("read", "write", "foo", "bar")
.autoApprove(false)
.accessTokenValiditySeconds(3600)
.redirectUris("http://localhost:8083/")
.and()
.withClient("fooClientIdPassword")
.secret(passwordEncoder().encode("secret"))
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("foo", "read", "write")
.accessTokenValiditySeconds(3600) // 1 hour
.refreshTokenValiditySeconds(2592000) // 30 days
.redirectUris("xxx")
.and()
.withClient("barClientIdPassword")
.secret(passwordEncoder().encode("secret"))
.authorizedGrantTypes("client_credentials", "refresh_token")
.scopes("bar", "read", "write")
.resourceIds("kip-apis")
.accessTokenValiditySeconds(3600) // 1 hour
.refreshTokenValiditySeconds(2592000) // 30 days
.and()
.withClient("testImplicitClientId")
.autoApprove(true)
.authorizedGrantTypes("implicit")
.scopes("read", "write", "foo", "bar")
.redirectUris("xxx");
}
#Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain
.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.authenticationManager(authenticationManager)
.tokenServices(tokenServices())
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain);
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(accessTokenConverter());
return defaultTokenServices;
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
WebSecurityConfig:
#Configuration
#EnableWebSecurity( debug = true ) // turn off the default configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().disable() // disable form authentication
.anonymous().disable() // disable anonymous user
.authorizeRequests().anyRequest().denyAll(); // denying all access
}
#Autowired
public void globalUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("john").password(passwordEncoder.encode("123")).roles("USER").and()
.withUser("tom").password(passwordEncoder.encode("111")).roles("ADMIN").and()
.withUser("user1").password(passwordEncoder.encode("pass")).roles("USER").and()
.withUser("admin").password(passwordEncoder.encode("nimda")).roles("ADMIN");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
I have tried a few options for trying to add an additional authentication provider for the client credentials grant. Such as in the WebSecurityConfig ...
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(customDaoAuthenticationProvider);
}
It didn't work and when stepping through the authentication for client_credentials I didn't see the custom one added to the provider list, just the anonymous and dao authentication providers.
I was able to finally get the configuration of the spring security authentication server to a point where we can add multiple providers for client_credentials.
#Configuration
#EnableAuthorizationServer
public class AuthenticationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.addTokenEndpointAuthenticationFilter(clientCredentialsTokenEndpointFilter());
}
#Bean
protected ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() {
ClientCredentialsTokenEndpointFilter cctef = new CustomClientCredentialsTokenEndpointFilter();
cctef.setAuthenticationManager(clientAuthenticationManager());
return cctef;
}
#Bean
protected ProviderManager clientAuthenticationManager() {
return new ProviderManager(Arrays.asList(authProvider()));
}
#Bean
protected DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new CustomDaoAuthenticationProvider();
authProvider.setUserDetailsService(clientDetailsUserService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Bean
protected BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
protected UserDetailsService clientDetailsUserService() {
return new ClientDetailsUserDetailsService(clientDetailsService());
}
#Bean
protected ClientDetailsService clientDetailsService() {
return new ClientDetailsService() {
#Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
BaseClientDetails details = new BaseClientDetails();
details.setClientId("barClientIdPassword");
details.setClientSecret(passwordEncoder().encode("secret"));
details.setAuthorizedGrantTypes(Arrays.asList("client_credentials"));
details.setScope(Arrays.asList("read", "trust"));
details.setResourceIds(Arrays.asList("kip-apis"));
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_CLIENT"));
details.setAuthorities(authorities);
details.setAccessTokenValiditySeconds(3600); //1hr
details.setRegisteredRedirectUri(null);
return details;
}
};
}
#Bean
public AuthenticationEntryPoint oauthAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint aep = new OAuth2AuthenticationEntryPoint();
aep.setRealmName("theRealm");
return aep;
}
#Bean
public AuthenticationEntryPoint clientAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint aep = new OAuth2AuthenticationEntryPoint();
aep.setRealmName("theRealm/client");
return aep;
}
#Bean
public AccessDeniedHandler oauthAccessDeniedHandler() {
return new OAuth2AccessDeniedHandler();
}
}
In the clientAuthenticationManager we can now add our providers to the provider manager list.
I am not sure the is the completely correct method to get this working, but it does seem to allow us to do what we wanted.

Spring Oauth 2 Facebook Authentication Redirects User To My Home Page

I am trying to redirect a user who have been authenticated to another page other than the home page. I am using spring boot 1.5.6 and Oauth 2. User is authenticated but was redirected to the home page. I don't understand why this is happening. Please, someone should help me. Some answers to related problem on stackoverflow and the internet didn't help me.
Here is my SecurityConfig file
#Configuration
#EnableGlobalAuthentication
#EnableOAuth2Client
#EnableGlobalMethodSecurity(prePostEnabled = true)
#Order(2)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
protected final Log logger = LogFactory.getLog(getClass());
#Autowired
private OAuth2ClientContext oauth2ClientContext;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private GeneralConfig generalConfig;
#Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user*")
.access("hasRole('CUSTOMER')")
.and()
.formLogin()
.loginPage("/loginUser")
.loginProcessingUrl("/user_login")
.failureUrl("/loginUser?error=loginError")
.defaultSuccessUrl("/customer/dashboard")
.and()
.logout()
.logoutUrl("/user_logout")
.logoutSuccessUrl("/loginUser").permitAll()
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.csrf().disable()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).
passwordEncoder(bCryptPasswordEncoder());
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws
Exception {
auth.userDetailsService(userDetailsService);
}
#Bean
public FilterRegistrationBeanoauth2ClientFilterRegistration
(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter filter = new
OAuth2ClientAuthenticationProcessingFilter(path);
OAuth2RestTemplate template = new
OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
filter.setRestTemplate(template);
UserInfoTokenServices tokenServices = new
UserInfoTokenServices(client.getResource().getUserInfoUri(),
client.getClient().getClientId());
tokenServices.setRestTemplate(template);
filter.setTokenServices(tokenServices);
return filter;
}
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(ssoFilter(facebook(), "/signin/facebook"));
filters.add(ssoFilter(google(), "/signin/google"));
filter.setFilters(filters);
return filter;
}
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
#ConfigurationProperties("google")
public ClientResources google() {
return new ClientResources();
}
#Bean
#ConfigurationProperties("facebook")
public ClientResources facebook() {
return new ClientResources();
}
}
From the SecurityConfig I expect the user upon successful authentication to be redirected to customer/dashboard so that I can do further processing. I know the user is authenticated because I can access their data. It's not just redirecting to the right page
But instead it keep redirecting the user to the home page. What am I doing wrong? I also have another Security Config File for admin. I can provide it if required.
To change the default strategy, you have to set an AuthenticationSuccessHandler, see AbstractAuthenticationProcessingFilter#setAuthenticationSuccessHandler:
Sets the strategy used to handle a successful authentication. By default a SavedRequestAwareAuthenticationSuccessHandler is used.
Your modified code:
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
filter.setRestTemplate(template);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(),client.getClient().getClientId());
tokenServices.setRestTemplate(template);
filter.setTokenServices(tokenServices);
filter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/customer/dashboard")‌​;
return filter;
}

Can spring have multiple ConfigurerAdapter?

I need to add OAuth2 security using an ldap authentication.
I have first implemented ldap authenication and add a WebSecurityConfigurerAdapter instance.
#Configuration
#EnableWebSecurity
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.contextSource().url("ldaps://master:636/dc=domain,dc=com")
.managerDn("cn=readonly,dc=domain,dc=com").managerPassword("123456")
.and()
.userSearchFilter("(uid={0})");
}
}
I need to add OAuth2 resource server adapter ResourceServerConfigurerAdapter
#Configuration
#Import({ DatabaseConfig.class })
#EnableResourceServer
#Order(1)
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired DatabaseConfig databaseConfig;
#Override
public void configure(final HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests()
.anyRequest().authenticated();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// converter.setSigningKey("123");
final Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(databaseConfig.dataSource());
}
It seems like WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter conflicting when both configured.
I am playing with both configure() method but I can only get an access login through ldap using http://localhost:8080/login on my Rest API, and couldn't using my angular client using oauth http://localhost:8081/login
I have the following error when trying to access the resource:
Failed to find refresh token for token eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJqb2huIiwic2NvcGUiOlsiZm9vIiwicmVhZCIsIndyaXRlIl0sIm9yZ2FuaXphdGlvbiI6ImpvaG5vRnZiIiwiYXRpIjoiNDcyZTJiNDYtZjgxZS00NGJiLWEwNDMtMGYwZmRjMDMzY2U1IiwiZXhwIjoxNDc2NTQ5NjYzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiN2UwNzRkZDktOWI0ZC00MTU0LWJjMzktMDlkY2U4Y2UyZTg2IiwiY2xpZW50X2lkIjoiZm9vQ2xpZW50SWRQYXNzd29yZCJ9.fuarTPL1O00Yg6b3BPibwux1ZtlmrHaPCJkgjsJni_51B3NEHkdB9kqbABK3IkMWMlZdqY8xfR-zMpY9SxFkpRFDfyvosgLcsTZ...
Handling error: InvalidGrantException, Invalid refresh token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVC...
I have the same issue. May be my solution is not graceful, but it works for me.
I had tried OAuth2ResourceServerConfig which extends WebSecurityConfig and implements ResourceServerConfigurer.
Your OAuth2ResourceServerConfig must be like this
#Configuration
#Import({ DatabaseConfig.class })
#EnableResourceServer
#Order(1)
public class OAuth2ResourceServerConfig extends WebSecurityConfig implements ResourceServerConfigurer {
#Autowired DatabaseConfig databaseConfig;
#Override
public void configure(final HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests()
.anyRequest().authenticated();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// converter.setSigningKey("123");
final Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(databaseConfig.dataSource());
}
According this post, I think you can use the previous version by adding this to you config(yml or properties):
security:
oauth2:
resource:
filter-order: 3
And I tried adding #Order annotation to my source server config as you did, and get the same issue. So, I think #Order annotation doesn't take effect to ResourceServerConfigurerAdapter, but it works fine with WebSecurityConfig. I don't know is it a bug or intended.

Resources