Why AuthenticationManager is throwing StackOverflowError? - spring

I am getting StackOverflowError while calling authenticationManger.authenticate()
java.lang.StackOverflowError: null at
org.apache.commons.logging.LogAdapter$Slf4jLog.isDebugEnabled(LogAdapter.java:300)
~[spring-jcl-5.1.10.RELEASE.jar:5.1.10.RELEASE] at
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:162)
~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE] at
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:503)
~[spring-security-config-5.1.6.RELEASE.jar:5.1.6.RELEASE]
I am trying to implement JWT in my application. I have created JWTTOkenUtil, Filter, Controller. But only Authentication manager is not working. I have tried with CustomAuthenticationManger as well but same error.
File AppConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppConfig extends WebSecurityConfigurerAdapter{
#Autowired
private JwtUserDetailService jwtUserDetailService;
#Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
//auth.userDetailsService(jwtUserDetailService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/version").permitAll()
.anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Bean
public JwtRequestFilter jwtRequestFilter() {
return new JwtRequestFilter();
}
}

authenticationManager() and authenticationManagerBean() of WebSecurityConfigurerAdapter are two different methods, and you are calling authenticationManagerBean() method of your super class, which, as far as I know, depends on authenticationManager() method. This, in return creates a cyclic calls of methods, which finally results in StackOverflowError exception.
You could try just not override AuthenticationManager authenticationManager() method, or return a solid implementation when doing so.

You are overiding the wrong method authenticationManager(), it should be authenticationManagerBean() instead.

Instead overriding authenticationManager() method, you need to override authenticationManagerBean() method of WebSecurityConfigurerAdapter class.
This is a working configuration for me.
#RequiredArgsConstructor
#EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
private final CustomUserDetailsService customUserDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
}
#Override
protected void configure (HttpSecurity http) throws Exception{
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
.anyRequest().authenticated();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception{
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}

Related

Error with multiple spring boot security config

I have a spring boot application already secured with JWT and I want to secure the spring actuator endpoint with basic auth in-memory user so I modified the Security config class to include 2 methods
Spring version 2.6.4
The problem
when I set the "ActuatorSecurityConfigurerAdapter" order to -1 and test with user1:user1 I get this error and my API becomes unsecured
JwtAuthenticationEntryPoint: Responding with unauthorized error. Message - Full authentication is required to access this resource
when I set the "ActuatorSecurityConfigurerAdapter" order to 2 i can access both endpoints with JWT
Security Config Class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true)
public class SecurityConfig {
#Order(1)
#Configuration
public class ApiSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private final CustomUserDetailsServiceImpl customUserDetailsService;
private final JwtAuthenticationEntryPoint unauthorizedHandler;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
public ApiSecurityConfigurationAdapter(CustomUserDetailsServiceImpl customUserDetailsService, JwtAuthenticationEntryPoint unauthorizedHandler, JwtAuthenticationFilter jwtAuthenticationFilter) {
this.customUserDetailsService = customUserDetailsService;
this.unauthorizedHandler = unauthorizedHandler;
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(Endpoints.AUTH_ENDPOINT+"/**").permitAll()
.anyRequest()
.authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
}
#Order(2)
#Configuration
public class ActuatorSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
AuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/actuator/**").hasRole("MODERATOR")
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1")
.password(passwordEncoder().encode("user1"))
.authorities("MODERATOR");
}
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Problem Solved
I put Order(1) for the actuator security and Order(2) for the rest of my API
To use the in-memory user I had to add "ROLE_" prefix for the authorities like ROLE_MODERATOR and in the HTTP security method I just added .hasRole("MODERATOR")
and this is the final SecurityConfig.class
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true)
public class SecurityConfig {
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Order(2)
#Configuration
public class ApiSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private final CustomUserDetailsServiceImpl customUserDetailsService;
private final JwtAuthenticationEntryPoint unauthorizedHandler;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
public ApiSecurityConfigurationAdapter(CustomUserDetailsServiceImpl customUserDetailsService, JwtAuthenticationEntryPoint unauthorizedHandler, JwtAuthenticationFilter jwtAuthenticationFilter) {
this.customUserDetailsService = customUserDetailsService;
this.unauthorizedHandler = unauthorizedHandler;
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(Endpoints.AUTH_ENDPOINT + "/**").permitAll()
.anyRequest()
.authenticated();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
}
#Order(1)
#Configuration
public class ActuatorSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
JwtAuthenticationEntryPoint actuatorAuthenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable().
exceptionHandling().authenticationEntryPoint(actuatorAuthenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.antMatcher(Endpoints.ACTUATOR_ENDPOINT+"/**")
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1")
.password(passwordEncoder().encode("user1"))
.authorities("ROLE_ADMIN");
}
}
}

“error”: “invalid_grant”, “error_description”: “Bad credentials”

enter image description here
enter image description here
Photo 1: This is the error that appears in the postman when trying to validate
¨Photo 2 : In the Authorization I do not get the preview request
This is the code in Spring for the AuthorizationServerConfig class, code:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
#Autowired
public BCryptPasswordEncoder passwordEncoder;
#Autowired
#Qualifier("authenticationManager")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("angularapp")
.secret(passwordEncoder.encode("12345"))
.scopes("read", "write")
.authorizedGrantTypes("password","refresh_token")
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(3600);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
return jwtAccessTokenConverter;
}
#Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
}
This is the ResourceServerCoonfig class in spring attached code just in case this error:
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter{
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(HttpMethod.GET,"/api/eventos").permitAll()
.anyRequest().authenticated();
}
}
and this is the code of the SpringSecurityConfig class, I also attach code:
#Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
private UserDetailsService usuarioService;
#Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
#Override
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.usuarioService).passwordEncoder(passwordEncoder());
}
#Bean("authenticationManager")
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager(); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
.secret("{bcrypt}$2a$10$kwz.jnLVLwJOYTAp2r/oG.8tfAN/EC5dK1w5beLgfpuFT6Puprgq.")
use something like this, spring security changed plain text passwords to bcrypt
Check here

How to Control Sequence of Bean Creating and Component Scanning In Spring Boot

Updated
I am Beginner to Spring and I tried to implement spring security application using Java Based Configuration. But now I have to Control sequence of bean creating and component scanning of application.
This is my configuration class
#EnableWebSecurity
#Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public Md5PasswordEncoder passwordEncoder() {
return new Md5PasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authProxy").permitAll()
.antMatchers(HttpMethod.POST,"/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JWTLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
and here is the JWTLoginFilter
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
private TokenAuthenticationService tokenAuthenticationService;
public JWTLoginFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/login"));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws AuthenticationException, IOException, ServletException {
AccountCredentials credentials = new ObjectMapper().readValue(httpServletRequest.getInputStream(), AccountCredentials.class);
final Authentication authentication = getAuthenticationManager()
.authenticate(new UsernamePasswordAuthenticationToken(credentials.getUsername(),
credentials.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
return getAuthenticationManager().authenticate(token);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication)
throws IOException, ServletException {
String name = authentication.getName();
tokenAuthenticationService.addAuthentication(response, name);
}
}
This is working fine.
But all thing going wrong When I try to declare JWTLoginFilter as service with #Service annotation and while I am trying to Autowire that.
The Changes that I did as Follows.
this is configuration class.
#EnableWebSecurity
#Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public Md5PasswordEncoder passwordEncoder() {
return new Md5PasswordEncoder();
}
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
JWTLoginFilter jwtLoginFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authProxy").permitAll()
.antMatchers(HttpMethod.POST,"/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtLoginFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
And this is my new JWTLoginFilter
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
#Autowired
AuthenticationManager authenticationManager;
private TokenAuthenticationService tokenAuthenticationService;
public JWTLoginFilter() {
super(new AntPathRequestMatcher("/login"));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws AuthenticationException, IOException, ServletException {
AccountCredentials credentials = new ObjectMapper().readValue(httpServletRequest.getInputStream(), AccountCredentials.class);
final Authentication authentication = getAuthenticationManager()
.authenticate(new UsernamePasswordAuthenticationToken(credentials.getUsername(),
credentials.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
return getAuthenticationManager().authenticate(token);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication)
throws IOException, ServletException {
String name = authentication.getName();
tokenAuthenticationService.addAuthentication(response, name);
}
}
This Code gives runtime error called
Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'JWTLoginFilter' defined in file [/media/dilanka/Stuff/CODEBASE/Inspection-Application/Inspection-AuthProxy/target/classes/com/shipxpress/inspection/security/jwt/JWTLoginFilter.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
The error is as my thought at the beginning, ComponentScan Scanning and initiating JWTLoginFilter. But at that time AuthenticationManager bean has not created. So It is not auto wiring.
So I have to create AuthenticationManager bean before scanning JWTLoginFilter, But It is not possible because it has to create in class that extended by WebSecurityConfigurerAdapter and spring allows one WebSecurityConfigurerAdapter extended class. So I can't initiate it in another class.
Also
#Override
protected void configure(HttpSecurity http) throws Exception {}
has to declare in WebSecurityConfigurerAdapter extended class and this method use jwtLoginFilter. So all
#Autowired
JWTLoginFilter jwtLoginFilter;
and
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
and
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authProxy").permitAll()
.antMatchers(HttpMethod.POST,"/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtLoginFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
has to define it in WebSecurityConfig extends WebSecurityConfigurerAdapter class and has to Control sequence of bean creating and component scanning of the application. Does anyone have an idea? please help me.
updated-->
I Tried to implement JWTLoginFilter as follows,
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
public JWTLoginFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/login"));
}
...
}
But it gives the following error
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| JWTLoginFilter defined in file [/media/dilanka/Stuff/CODEBASE/Inspection-Application/DR-136812421-dbchangesSendAsMail/Inspection-Application/Inspection-AuthProxy/target/classes/com/shipxpress/inspection/security/jwt/JWTLoginFilter.class]
↑ ↓
| webSecurityConfig (field com.shipxpress.inspection.security.jwt.JWTLoginFilter com.shipxpress.inspection.config.WebSecurityConfig.jwtLoginFilter)
└─────┘
I think the problem is, If we auto wire Constructor as above, Then JWTLoginFilter can't create without creating Configuration beans creating. But Configuration beans needs JWTLoginFilter bean. So it can't create without JWTLoginFilter bean.
Thanks.
#Autowired annotation will be processed after constructor of bean has been called. So your exception does not depend on the sequence of bean creating. If you need to invoke setAuthenticationManager from constructor you can apply #Autowired to the constructor:
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
AuthenticationManager authenticationManager;
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
public JWTLoginFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager; //if you will need this instance in future
super(new AntPathRequestMatcher("/login"));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
...
}
Then appropriate bean will be passed to the constructor automatically.
Another solution is to make all initialization in the #PostConstruct method. This method will be called just after #Autowired annotation has been processed:
#Service
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
#Autowired
AuthenticationManager authenticationManager;
private TokenAuthenticationService tokenAuthenticationService;
public JWTLoginFilter(){
super(new AntPathRequestMatcher("/login"));
}
#PostConstruct
public void postConstruct() {
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
...
}
Spring Boot has multiple conditional annotations to use like #ConditionalOnBean to control the sequencing of bean creation
Look into package org.springframework.boot.autoconfigure.condition for all the conditionals available
For the your example, best way is to have constructor injection of AuthenticationManager in JWTLoginFilter

How do i get a reference to an AuthenticationManager using a Spring java security configuration?

I’m using Spring 4.1.5.RELEASE and Spring Security 3.2.5.RELEASE. I’m doing all security configuration through Java (as opposed to XML). I’m struggling to get a reference to the AuthenticationManager for use with my custom usernamepassword authentication filter …
#Configuration
#EnableWebSecurity
#ComponentScan(basePackages="com.mainco", excludeFilters=#ComponentScan.Filter(Controller.class))
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String ROLE3 = "ROLE3";
private static final String ROLE2 = "ROLE2";
private static final String ROLE1 = "ROLE1";
#Resource(name="userDetailsService")
private UserDetailsService userDetailsService;
#Resource(name="myAuthenticationSuccessHandler")
private MyAuthenticationSuccessHandler authSuccessHandler;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(authenticationFilter(), MyUsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/403").permitAll()
.antMatchers("/login/**").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/ROLE1/**").hasRole(ROLE1)
.antMatchers("/common/**").hasAnyRole(ROLE1, ROLE2, ROLE3)
.antMatchers("/ROLE3/**").hasAnyRole(ROLE1, ROLE2, ROLE3)
.antMatchers("/ROLE2/**").hasAnyRole(ROLE1, ROLE2)
.antMatchers("/*/**").fullyAuthenticated()
.and().formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.usernameParameter("username")
.passwordParameter("password")
.successHandler(authSuccessHandler)
.and().logout().logoutSuccessUrl("/login?logout")
.and().exceptionHandling().accessDeniedPage("/403")
.and().csrf().disable();
}
#Bean(name="passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new StandardPasswordEncoder();
}
#Bean
public JSONUsernamePasswordAuthenticationFilter authenticationFilter() {
final MyUsernamePasswordAuthenticationFilter authFilter = new MyUsernamePasswordAuthenticationFilter();
authFilter.setAuthenticationSuccessHandler(authSuccessHandler);
authFilter.setUsernameParameter("username");
authFilter.setPasswordParameter("password");
return authFilter;
}
This configuration fails upon startup with the message
“Caused by: java.lang.IllegalArgumentException: authenticationManager must be specified”.
How do I get a reference to the AuthenticationManager for use with my filter?
You can override authenticationManagerBean() method from WebSecurityConfigurerAdapter to expose AuthenticationManager as a bean like so:
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}

A dependency cycle was detected when trying to resolve the AuthenticationManager (Spring Security and Oauth)

I'm getting following error when configuring spring security, can anyone help me? The current configuration have resource server and authentication servers in same server for testing, may this causing conflicts.
Caused by: org.springframework.beans.FatalBeanException: A dependency cycle was detected when trying to resolve the AuthenticationManager. Please ensure you have configured authentication.
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.validateBeanCycle(WebSecurityConfigurerAdapter.java:462)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.<init>(WebSecurityConfigurerAdapter.java:430)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.authenticationManagerBean(WebSecurityConfigurerAdapter.java:220)
at org.blanc.whiteboard.security.configuration.SecurityConfig$ApiWebSecurityConfig.configure(SecurityConfig.java:110)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.getHttp(WebSecurityConfigurerAdapter.java:199)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:283)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:68)
at org.blanc.whiteboard.security.configuration.SecurityConfig$ApiWebSecurityConfig$$EnhancerBySpringCGLIB$$2cbb9c9d.init(<generated>)
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:367)
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:320)
at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:39)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:92)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$d6effe0e.CGLIB$springSecurityFilterChain$4(<generated>)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$d6effe0e$$FastClassBySpringCGLIB$$3d548252.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$d6effe0e.springSecurityFilterChain(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
... 30 more
Web security
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler(){
return new OAuth2AccessDeniedHandler();
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
private UserRepository userRepository;
#Autowired
private Validator validator;
#Bean
public PasswordEncoder passwordEncoder(){
return new StandardPasswordEncoder();
}
#Autowired
private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;
#Autowired
private ClientDetailsService clientDetailsService;
#Bean
public OAuthRestEntryPoint oauthRestEntryPoint()
{
return new OAuthRestEntryPoint();
}
// #Bean(name = "authenticationManager")
// #Override
// public AuthenticationManager authenticationManagerBean()
// throws Exception {
// return super.authenticationManagerBean();
// }
#Bean
public ClientDetailsUserDetailsService clientDetailsUserDetailsService(){
return new ClientDetailsUserDetailsService(clientDetailsService);
}
#Bean
public UserDetailsService userDetailsService() {
return new UserServiceImpl(userRepository, validator, passwordEncoder());
}
#Bean
protected AuthenticationEntryPoint authenticationEntryPoint(){
OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
entryPoint.setTypeName("Basic");
entryPoint.setRealmName("test");
return entryPoint;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.anonymous().disable()
.antMatcher("/oauth/token")
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(oauthRestEntryPoint())
.and()
.csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable()
.exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.afterPropertiesSet();
http.addFilterBefore(filter, BasicAuthenticationFilter.class);
http.addFilterAfter(filter, SpringCrossOriginResourceSharingFilter.class);
}
}
#Configuration
#Order(2)
protected static class ResourceServerConfig extends WebSecurityConfigurerAdapter{
#Bean(name = "clientAuthenticationManager")
#Override
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
#Autowired
private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;
#Bean
public OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint(){
OAuth2AuthenticationEntryPoint clientAuthenticationEntrypoint = new OAuth2AuthenticationEntryPoint();
clientAuthenticationEntrypoint.setTypeName("Basic");
return clientAuthenticationEntrypoint;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.anonymous().disable().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler)
.authenticationEntryPoint(clientAuthenticationEntryPoint())
.and()
.requestMatchers().antMatchers("/v1.0/users")
.and()
.authorizeRequests().antMatchers(HttpMethod.POST, "/v1.0/users").permitAll()
.and()
.csrf().disable();
}
}
}
Oauthserver config
#Configuration
#ComponentScan
#EnableResourceServer
#Import(SecurityConfig.class)
#ImportResource({
"classpath:META-INF/spring/oauth/client-details.xml"
})
public class OAuth2ServerConfig {
#Configuration
#EnableAuthorizationServer
protected static class OAuth2Config extends
AuthorizationServerConfigurerAdapter {
// #Autowired
// private AuthenticationManager authenticationManager;
#Autowired
private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter(){
ClientCredentialsTokenEndpointFilter clientFilter = new ClientCredentialsTokenEndpointFilter();
// clientFilter.setAuthenticationManager(authenticationManager);
return clientFilter;
}
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
public OAuth2AccessTokenRepository oAuth2AccessTokenRepository;
#Autowired
public OAuth2RefreshTokenRepository oAuth2RefreshTokenRepository;
#Bean
public DefaultTokenServices tokenServices(){
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setReuseRefreshToken(true);
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setClientDetailsService(clientDetailsService);
return defaultTokenServices;
}
#Bean
public OAuth2RepositoryTokenStore tokenStore() {
return new OAuth2RepositoryTokenStore(oAuth2AccessTokenRepository,
oAuth2RefreshTokenRepository);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception {
oauthServer.tokenKeyAccess(
"isAnonymous || hasAuthority('ROLE_TRUSTED_CLIENT')")
.realm("test");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.withClientDetails(clientDetailsService);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
// .authenticationManager(authenticationManager)
.clientDetailsService(clientDetailsService).tokenServices(tokenServices())
.tokenStore(tokenStore());
}
}
}
In your ResourceServerConfig, you've overridden authenticationManagerBean() but never configured the authenticationManager as instructed in the api reference, specifically
Override this method to expose the AuthenticationManager from
configure(AuthenticationManagerBuilder) to be exposed as a Bean.
For example ...
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new MyCustomAuthProvider());
}
See the configure(AuthenticationManagerBuilder) reference for details.

Resources