Spring Security exclude url patterns in security annotation configurartion - spring

I have spring web application with Spring security configured using java config approach. I want to exclude some URL patterns from authentication(eg: static resources etc..). I have done this earlier with spring security xml config but couldn't figure out with java config as adding antmatchers doesn't help.
The following is my code added in security config class extending WebSecurityConfigurerAdapter
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/authFailure")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.and()
.authenticationProvider(_provider)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(authFilter())
.addFilterAfter(executionContextFilter(),
TokenBasedSecurityFilter.class).csrf().disable();
}
The spring security version that I use is 3.2.0.
Edit:
The stacktrace that I got while hitting the excluded URL,
org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request
at com.inventory.ricemill.tba.spring.TokenBasedSecurityFilter.doFilter(TokenBasedSecurityFilter.java:59)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Apr 01, 2014 10:18:41 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Inventory] in context with path [/ricemill] threw exception [Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request] with root cause
org.springframework.security.authentication.AuthenticationServiceException: Authorization Header is not available in the request
at com.inventory.ricemill.tba.spring.TokenBasedSecurityFilter.doFilter(TokenBasedSecurityFilter.java:59)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
The request goes through the filters registered in spring security filter chain, while it shouldn't as the request is ignored with antmatcher

Found the solution in Spring security examples posted in Github.
WebSecurityConfigurerAdapter has a overloaded configure message that takes WebSecurity as argument which accepts ant matchers on requests to be ignored.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/authFailure");
}
See Spring Security Samples for more details

Where are you configuring your authenticated URL pattern(s)? I only see one uri in your code.
Do you have multiple configure(HttpSecurity) methods or just one? It looks like you need all your URIs in the one method.
I have a site which requires authentication to access everything so I want to protect /*. However in order to authenticate I obviously want to not protect /login. I also have static assets I'd like to allow access to (so I can make the login page pretty) and a healthcheck page that shouldn't require auth.
In addition I have a resource, /admin, which requires higher privledges than the rest of the site.
The following is working for me.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login**").permitAll()
.antMatchers("/healthcheck**").permitAll()
.antMatchers("/static/**").permitAll()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.antMatchers("/**").access("hasRole('ROLE_USER')")
.and()
.formLogin().loginPage("/login").failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
NOTE: This is a first match wins so you may need to play with the order.
For example, I originally had /** first:
.antMatchers("/**").access("hasRole('ROLE_USER')")
.antMatchers("/login**").permitAll()
.antMatchers("/healthcheck**").permitAll()
Which caused the site to continually redirect all requests for /login back to /login. Likewise I had /admin/** last:
.antMatchers("/**").access("hasRole('ROLE_USER')")
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
Which resulted in my unprivledged test user "guest" having access to the admin interface (yikes!)

When you say adding antMatchers doesnt help - what do you mean? antMatchers is exactly how you do it. Something like the following should work (obviously changing your URL appropriately):
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/authFailure").permitAll()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
If you are still not having any joy, then you will need to provide more details/stacktrace etc.
Details of XML to Java config switch is here

specifying the "antMatcher" before "authorizeRequests()" like below will restrict the authenticaiton to only those URLs specified in "antMatcher"
http.csrf().disable()
.antMatcher("/apiurlneedsauth/**").authorizeRequests().

And in more modern way it's should looks like:
#Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/authFailure");
}

I found all of the solutions above outdated...
This is the solution I ended up with
#Configuration
#EnableWebSecurity/*(debug = true)*/
#RequiredArgsConstructor
#EnableMethodSecurity
public class SecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// #formatter:off
return http
.csrf()
.disable()
.headers().frameOptions().disable()
.and()
// Enable CORS at Spring Security level
.cors()
.and()
.authorizeHttpRequests()
.requestMatchers("/login/**", "/api/noAuth/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new CustomJwtAuthenticationConverter(new UserDetailsConverter()))
.and()
.and().build();
// #formatter:on
}
}

Addition to answers already given here.
There seems to be a lot of confusion about the difference between authentication and authorization.
Spring Security executes authentication first, only then authorization, which makes sense.
This means that it will first execute the authentication filters, followed by verification of the authorized endpoints only after.
To circumvent custom authentication filters, permitAll will not work, because this concerns authorization, and NOT authentication.
Spring Security 5.7.0-M2 deprecated the WebSecurityConfigurerAdapter.
Authentication filters can be ignored using:
#Bean
public WebSecurityCustomizer ignoringCustomizer() {
return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
}
Or by using antMatchers.

Related

Getting 403 Forbidden error in Spring Boot security despite CSRF being disabled

For some reason I'm getting a 403 Forbidden error from Spring Boot when I try to do anything with it. I currently have the following in my configure method of my SecurityConfiguration class:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/*", "/console").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and().addFilterBefore(new LoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new AuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
I'm new to this part of Spring boot so not sure if this is what's causing it.
Turns out... I'm an idiot. This isn't caused by CSRF at all... It was caused by the fact I'm British and I spell what should be Authorization as Authorisation in my AuthenticationFilter which was choking up everything else.

Spring Security + Thymeleaf - TemplateInputException after a second login

I have a navbar with LOGIN, PROFILE, and LOGOUT.
My goal is to remove the LOGIN and show only PROFILE and LOGOUT
after the user is logged in.
I have the controller checking for authenticated users:
#Controller
public class LoginController {
#GetMapping("/login")
private String loginRender(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken){
return "login";
}else {
return "redirect:/";
}
}
}
The Thymeleaf template looks like this:
<ul class="logout-ul top-links-container">
<li class="top-links-item text-center" sec:authorize="!isAuthenticated()"> <i class="icon-user4" style="color: #e35f5f"></i>Login</li>
<li class="top-links-item text-center" sec:authorize="isAuthenticated()"><i class="icon-user4" style="color: #e35f5f"></i>Profile</li>
<li class="text-center logout" sec:authorize="isAuthenticated()"><form th:action="#{/logout}" th:method="post"><button title="LOGOUT" class="btn" type="submit"><i class="icon-off"></i></button></form></li>
</ul>
Configuration:
http
.authorizeRequests()
.antMatchers("/login", "/", "register",
"/custom-transfers/**", "/about-us", "/information/**", "/support/**").permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/admin").hasRole(UserRoleEnum.ADMIN.name())
.antMatchers("/**").authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY)
.passwordParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY)
.defaultSuccessUrl("/user/profile")
//TODO validation page
.failureForwardUrl("/login")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
ISSUE
It all works when the user first logs in. When logouts and log in again, Thymleaf shows a TemplateInputException.
Exception:
ERROR 26304 --- [nio-8080-exec-9] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/login] and exception [An error happened during template parsing (template: "class path resource [templates/login.html]")] as the response has already been committed. As a result, the response may have the wrong status code.
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/login.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.12.RELEASE.jar:3.0.12.RELEASE]
at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:366) ~[thymeleaf-spring5-3.0.12.RELEASE.jar:3.0.12.RELEASE]
at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:190) ~[thymeleaf-spring5-3.0.12.RELEASE.jar:3.0.12.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1400) ~[spring-webmvc-5.3.10.jar:5.3.10]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1145) ~[spring-webmvc-5.3.10.jar:5.3.10]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1084) ~[spring-webmvc-5.3.10.jar:5.3.10]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.10.jar:5.3.10]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.10.jar:5.3.10]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.10.jar:5.3.10]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.53.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.10.jar:5.3.10]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.53.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.53.jar:9.0.53]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327) ~[spring-security-web-5.5.2.jar:5.5.2]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[spring-security-web-5.5.2.jar:5.5.2]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81) ~[spring-security-web-5.5.2.jar:5.5.2]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121) ~[spring-security-web-5.5.2.jar:5.5.2]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) ~[spring-security-web-5.5.2.jar:5.5.2]
I tried placing sec:authorize="!isAuthenticated()" outside in a <div>, tried to pass a boolean to the template with a RedirectAttribute and Model, but I can't still fix the issue.
It works when I add:
<li class="top-links-item" sec:authorize="!isAuthenticated()">TEST</li>
so I assume is because I use sec:authorize for a login page, which is managed by Spring Security. Could there be any relation?
UPDATE I found that after logout the Cookie destroys and it doesn't creates a new one for a second login. Also the issue is only of logout form in the html when I add sec:authorize=isAuthenticated(). Therefore the problem is connected to the logout instead of the login page. Why could this happen?
This occurs only when I use isAuthenticated() in Thyemleaf.
What am I doing wrong?
I would really appreciate your help.
Thank you.
I think that what happens here is the following:
Your logout form is managed by Thymeleaf which means that under the hood Thymeleaf will try to create a hidden field with the CSRF token inside. This normally works and it requires existing or new session.
The problem is that Thymeleaf is designed to minimize latencies by producing template output as your template is being processed. Thus when a page is longer in size (as it is in your case) by the time when the engine reaches your logout <form> tag some of the output MAY HAVE BEEN streamed to the client and the server starts to consider your response as committed. Once the response is marked as committed Thymeleaf will fail to access/create a session. I guess this is an architectural constraint.
So I'm not sure what exactly to advise you here. Maybe try to output the logout button earlier in your templates or optionally try to eagerly initialize the CSRF token. This setting in HttpSecurity will possibly do it:
.and()
.csrf()
.csrfTokenRepository(new HttpSessionCsrfTokenRepository())

Springboot and KeycloakWebSecurityConfigurerAdapter

I'm trying to plug in Keycloak authentication in my web application on Springboot with KeycloakAdapter. But when i trying to login from application homepage, i get 401 error. Logfile contains this error:
2021-10-05 18:34:39,839 [http-nio-0.0.0.0-9090-exec-3] DEBUG o.k.a.s.f.KeycloakAuthenticationProcessingFilter - Request is to process authentication
2021-10-05 18:34:39,839 [http-nio-0.0.0.0-9090-exec-3] DEBUG o.k.a.s.f.KeycloakAuthenticationProcessingFilter - Attempting Keycloak authentication
2021-10-05 18:34:39,839 [http-nio-0.0.0.0-9090-exec-3] DEBUG o.apache.tomcat.util.http.Parameters - Set encoding to UTF-8
2021-10-05 18:34:39,839 [http-nio-0.0.0.0-9090-exec-3] DEBUG o.k.adapters.RequestAuthenticator - NOT_ATTEMPTED: bearer only
2021-10-05 18:34:39,839 [http-nio-0.0.0.0-9090-exec-3] DEBUG o.k.a.s.f.KeycloakAuthenticationProcessingFilter - Auth outcome: NOT_ATTEMPTED
2021-10-05 18:34:39,839 [http-nio-0.0.0.0-9090-exec-3] DEBUG o.k.a.s.f.KeycloakAuthenticationProcessingFilter - Authentication request failed: org.keycloak.adapters.springsecurity.KeycloakAuthenticationException: Authorization header not found, see WWW-Authenticate header
org.keycloak.adapters.springsecurity.KeycloakAuthenticationException: Authorization header not found, see WWW-Authenticate header
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.attemptAuthentication(KeycloakAuthenticationProcessingFilter.java:168)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:86)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
I think i need to get authorization token from Keycloak and call login endpoint with it, but i cant understand where and how to do this. And its starange, that i need authenticate before authenticate... Seems like I do something wrong. Colleagues, who integarates Keycloak with Springboot, give me a hand with this please.
My config:
#KeycloakConfiguration
#ComponentScan(
basePackageClasses = {KeycloakSecurityComponents.class},
excludeFilters = #ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
super.configure(http);
http
.csrf().disable()
.authorizeRequests()
.antMatchers(WEBJARS_ENTRY_POINT).permitAll()
.antMatchers(DEVICE_API_ENTRY_POINT).permitAll()
.antMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll()
.antMatchers(PUBLIC_LOGIN_ENTRY_POINT).permitAll()
.antMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll()
.antMatchers(NON_TOKEN_BASED_AUTH_ENTRY_POINTS).permitAll()
.and()
.authorizeRequests()
.antMatchers(WS_TOKEN_BASED_AUTH_ENTRY_POINT).authenticated()
.antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated();
// #formatter:on
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
}
And .yml
keycloak:
realm: "myRealm"
auth-server-url: "http://localhost:18080/auth"
ssl-required: "external"
resource: "myResource"
credentials:
secret: "xxxxxxxxxxxxxxxxxxxxxxxxx"
use-resource-role-mappings: "true"
bearer-only: "true"
I found the problem. It works if change parameter bearer-only to false in .yml
keycloak:
realm: "myRealm"
auth-server-url: "http://localhost:18080/auth"
ssl-required: "external"
resource: "myResource"
credentials:
secret: "xxxxxxxxxxxxxxxxxxxxxxxxx"
use-resource-role-mappings: "true"
bearer-only: "false"

Protecting REST API with OAuth2: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active

I've been working for a few days to attempt to implement oauth2 protection on a REST API. I've tried a ton of different configurations but still haven't managed to get it to work.
I'm proving the code that I have right now, but I'm in no way married to this implementation. If you can show me some radically different way to accomplish what I want to accomplish, great.
My flow looks like this:
Client checks Auth Server, gets token.
Client sends token to Resource Server.
Resource Server uses Auth Server to make sure that token is valid.
The Auth Server works fine. I'm having trouble configuring the Resource Server.
Configs on Resource Server
Here's some of my configs. I have this bean:
Ouath Rest Template
#EnableOAuth2Client
#Configuration
#Import({PropertiesConfig.class}) //Imports properties from properties files.
public class OauthRestTemplateConfig {
#Bean
public OAuth2RestTemplate oAuth2RestTemplate(OAuth2ClientContext oauth2ClientContext) {
OAuth2RestTemplate template = new OAuth2RestTemplate(oauth2ResourceDetails(), oauth2ClientContext);
return template;
}
#Bean
OAuth2ProtectedResourceDetails oauth2ResourceDetails() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("theOauth");
details.setClientId("clientID");
details.setClientSecret("SecretKey");
details.setAccessTokenUri("https://theAuthenticationServer.com/oauthserver/oauth2/token");
details.setUserAuthorizationUri("https://theAuthenticationServer.com/oauthserver/oauth2/token");
details.setTokenName("oauth_token");
details.setPreEstablishedRedirectUri("http://localhost/login");
details.setUseCurrentUri(true);
return details;
}
}
Security Config
I use that bean in my main security config in Resource Server:
#Slf4j
#Configuration
#EnableWebSecurity
#EnableOAuth2Client
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true, proxyTargetClass = true)
#Import({PropertiesConfig.class, OauthRestTemplateConfig.class})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("oAuth2RestTemplate")
private OAuth2RestTemplate oAuth2RestTemplate;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.accessDecisionManager(accessDecisionManager()) //This is a WebExpressionVoter. I don't think it's related to the problem so didn't include the source.
.antMatchers("/login").permitAll()
.antMatchers("/api/**").authenticated()
.anyRequest().authenticated();
http
.exceptionHandling()
.authenticationEntryPoint(delegatingAuthenticationEntryPoint());
http
.addFilterBefore(new OAuth2ClientContextFilter(), BasicAuthenticationFilter.class)
.addFilterAfter(oauth2ClientAuthenticationProcessingFilter(), OAuth2ClientContextFilter.class)
;
}
private OAuth2ClientAuthenticationProcessingFilter oauth2ClientAuthenticationProcessingFilter() {
OAuth2ClientAuthenticationProcessingFilter
daFilter = new OAuth2ClientAuthenticationProcessingFilter("/api/**");
daFilter.setRestTemplate(oAuth2RestTemplate);
daFilter.setTokenServices(inMemoryTokenServices());
return daFilter;
}
private DefaultTokenServices inMemoryTokenServices() {
InMemoryTokenStore tok = new InMemoryTokenStore();
DefaultTokenServices tokenService = new DefaultTokenServices();
tokenService.setTokenStore(tok);
return tokenService;
}
}
Extra stuff in Security Config
Aaand, some of the beans which I believe are less relevant, but here they are in case you need them:
#Bean
public DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint() {
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> matchers =
Maps.newLinkedHashMap();
//Match all HTTP methods
matchers.put(new RegexRequestMatcher("\\/api\\/v\\d+\\/.*", null), oAuth2AuthenticationEntryPoint());
matchers.put(AnyRequestMatcher.INSTANCE, casAuthenticationEntryPoint());
DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(matchers);
entryPoint.setDefaultEntryPoint(casAuthenticationEntryPoint());
return entryPoint;
}
#Bean(name = "casEntryPoint")
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
casAuthenticationEntryPoint.setLoginUrl(casUrl + "/login");
casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
return casAuthenticationEntryPoint;
}
Error
Resource Server starts up just fine. Client gets its auth token from theAuthenticationServer.com and sends it in the request header to an api url. And I get the following error:
HTTP Status 500 - Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Exception report
Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
The server encountered an internal error that prevented it from fulfilling this request.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:355)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:187)
com.sun.proxy.$Proxy26.getAccessToken(Unknown Source)
org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:169)
org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:94)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
root cause
<pre>java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
org.springframework.web.context.request.SessionScope.get(SessionScope.java:91)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:187)
com.sun.proxy.$Proxy26.getAccessToken(Unknown Source)
org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:169)
org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:94)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
I've tried a lot of different configs, looked up a ton of resources online, and I've gotten nowhere. Am I using the right classes? Any idea what configs I might need to change?
An even easier way to enable the request context listener is to add a bean annotation into your app.
#Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
I ended up resolving this thing after looking into Spring documentation.
It turned out that the scope context didn't actually exist in my app, because I hadn't initialized it.
I initialized it by adding this listener:
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
I'm proving the code that I have right now, but I'm in no way married
to this implementation. If you can show me some radically different
way to accomplish what I want to accomplish, great
If your main problem is implementing the Resource Server and also, you are open to totally different solutions, you can use Spring Boot's resource server auto configurations. This way you would have a ResourceServerConfiguration such as following:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated();
// you can put your application specific configurations here
// here i'm just authenticating every request
}
}
With an application.yml config file in your src/main/resources:
security:
oauth2:
client:
client-id: client
client-secret: secret
resource:
token-info-uri: http://localhost:8888/oauth/check_token
You should add your client-id, client-secret and token-info-uri there. token-info-uri is the endpoint on Authorization Server that our resource server is going to consult about the validity of passed Access Tokens.
With these arrangements, if the client fire a request to, say, /api/greet API:
GET /api/greet HTTP/1.1
Host: localhost:8080
Authorization: bearer cef63a29-f9aa-4dcf-9155-41fb035a6cdb
Our resource server will extract the Bearer access token from the request and send the following request to the authorization server to validate the access token:
GET /oauth/check_token?token=cef63a29-f9aa-4dcf-9155-41fb035a6cdb HTTP/1.1
Host: localhost:8888
Authorization: basic base64(client-id:client-secret)
If token was valid, authorization server send a 200 OK response with a JSON body like following:
{"exp":1457684735,"user_name":"me","authorities":["ROLE_USER"],"client_id":"client","scope":["auth"]}
Otherwise, it will return a 4xx Client Error.
This was a maven project with a pom.xml like following:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
</dependencies>
And a typical Application class:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
You can check out the spring boot documentation on resource server auto configurations here.
I believe that the root of issue is that you create the OAuth2ClientAuthenticationProcessingFilter and OAuth2ClientContextFilter with new operator.
If you look at the stacktrace
org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
org.springframework.web.context.request.SessionScope.get(SessionScope.java:91)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:187)
com.sun.proxy.$Proxy26.getAccessToken(Unknown Source)
org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:169)
org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:94)
there's a chain how it goes from OAuth2ClientAuthenticationProcessingFilter to JdkDynamicAopProxy and tries to get the bean. And I can assume because of that bean was created out of Spring container, it can't get the bean from the session scope.
Try to wrap your filters into #Bean annotation so to put them into context. Also, i believe it worth being set the correct scope: the request would match best here.
I faced the same problem when using spring-boot 1.4.1 with spock-spring 1.1-groovy-2.4-rc-2. The easiest way to fix it is to use Spock 1.0.
There is a bug reported already:
https://github.com/spockframework/spock/issues/655
public class ContextAwareCallable implements Callable {
private Callable<T> task;
private RequestAttributes context;
public ContextAwareCallable(Callable<T> task, RequestAttributes context) {
this.task = task;
this.context = cloneRequestAttributes(context);
}
#Override
public T call() throws Exception {
if (context != null) {
RequestContextHolder.setRequestAttributes(context);
}
try {
return task.call();
} finally {
RequestContextHolder.resetRequestAttributes();
}
}
private RequestAttributes cloneRequestAttributes(RequestAttributes requestAttributes) {
RequestAttributes clonedRequestAttribute = null;
try {
clonedRequestAttribute =
new ServletRequestAttributes(((ServletRequestAttributes) requestAttributes).getRequest(),
((ServletRequestAttributes) requestAttributes).getResponse());
if (requestAttributes.getAttributeNames(RequestAttributes.SCOPE_REQUEST).length > 0) {
for (String name : requestAttributes.getAttributeNames(RequestAttributes.SCOPE_REQUEST)) {
clonedRequestAttribute.setAttribute(name,
requestAttributes.getAttribute(name, RequestAttributes.SCOPE_REQUEST),
RequestAttributes.SCOPE_REQUEST);
}
}
return clonedRequestAttribute;
} catch (Exception e) {
return requestAttributes;
}
}
}
Then create executor
public class ContextAwarePoolExecutor extends ThreadPoolTaskExecutor {
#Override
public <T> Future<T> submit(Callable<T> task) {
return super.submit(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()));
}
#Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
return super.submitListenable(new ContextAwareCallable(task, RequestContextHolder.currentRequestAttributes()));
}
}

Add Spring security Java Config to Spring config

i'm working on a spring application lately, and i wanted to add spring security to my app.
I had a simple page containing a login form working like a charm, but when i wanted to add the spring security configuration to the app i get an error.
Here's the code of my SecurityConfig file :
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/*#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
/*.antMatchers("/infermier*//**").hasRole("INFERMIER")
.antMatchers("/docteur*//**").hasRole("DOCTEUR")
.antMatchers("/user*//**").hasRole("USER")*/
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.permitAll();
}
}
And here's the log :
Error invoking ServletContainerInitializer org.springframework.web.SpringServletContainerInitializer
java.lang.NoClassDefFoundError: org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.glassfish.web.loader.WebappClassLoader.findClass(WebappClassLoader.java:1183)
at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1728)
at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1611)
at configuration.WebInitializer.getRootConfigClasses(WebInitializer.java:12)
at org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer.createRootApplicationContext(AbstractAnnotationConfigDispatcherServletInitializer.java:50)
at org.springframework.web.context.AbstractContextLoaderInitializer.registerContextLoaderListener(AbstractContextLoaderInitializer.java:57)
at org.springframework.web.context.AbstractContextLoaderInitializer.onStartup(AbstractContextLoaderInitializer.java:47)
at org.springframework.web.servlet.support.AbstractDispatcherServletInitializer.onStartup(AbstractDispatcherServletInitializer.java:66)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
at org.apache.catalina.core.StandardContext.callServletContainerInitializers(StandardContext.java:5997)
at com.sun.enterprise.web.WebModule.callServletContainerInitializers(WebModule.java:774)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5895)
at com.sun.enterprise.web.WebModule.start(WebModule.java:691)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1041)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:1024)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:747)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2278)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1924)
at com.sun.enterprise.web.WebApplication.start(WebApplication.java:139)
at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122)
Startup of context /servicemed failed due to previous errors]]
[2014-08-13T12:57:16.429+0100] [glassfish 4.0] [SEVERE] [AS-WEB-CORE-00175] [javax.enterprise.web.core] [tid: _ThreadID=37 _ThreadName=admin-listener(4)] [timeMillis: 1407931036429] [levelValue: 1000] [[
Exception during cleanup after start failed
org.apache.catalina.LifecycleException: Manager has not yet been started
at org.apache.catalina.session.StandardManager.stop(StandardManager.java:934)
at org.apache.catalina.core.StandardContext.stop(StandardContext.java:6099)
at com.sun.enterprise.web.WebModule.stop(WebModule.java:720)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5916)
at com.sun.enterprise.web.WebModule.start(WebModule.java:691)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1041)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:1024)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:747)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2278)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1924)
at com.sun.enterprise.web.WebApplication.start(WebApplication.java:139)
at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122)
org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.lang.NoClassDefFoundError: org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5920)
at com.sun.enterprise.web.WebModule.start(WebModule.java:691)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1041)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:1024)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:747)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2278)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1924)
at com.sun.enterprise.web.WebApplication.start(WebApplication.java:139)
at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122)
PS: I did added it to the MVCInitializer :
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class,SecurityConfig.class};
}
Make sure you have spring-security-config in your classpath. Obviously it is missing at the runtime.
In such case running mvn clean install prior to running your application can fix the problem.
java.lang.NoClassDefFoundError ... That means a class of name XYZ has not been found on your classpath. Add spring-security-config.jar to your classpath.
#idursun gave me a solution and a nice explanation, there was nothing wrong with the configuration i made (it actually worked afterwards), and the problem was that the target
folder got messed up, so i cleaned it using the maven projects tool and installed everything all over again (using the same tool), and voila, everything is good
It was a wrong maven project packaging type, in my case:
<packaging>pom</packaging>
instead of
<packaging>war</packaging>

Resources