Redirecting to login page instead of returning a token - spring

I am implementing OAuth 2 using Spring Security 3.2 and Spring Security OAuth 1.0.5. It worked with an xml-based configuration. Now I try to migrate to java-based configuration and I'm facing the problem that instead of returning a token, it redirected me to login page! Below are the configurations:
SecurityInitializer.java
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
/**
* This class configure spring security
*
* #author tuan.dang
*
*/
#Configuration
#EnableWebMvcSecurity
#Order
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DBAuthenticationProvider dbAuthenticationProvider;
#Autowired
private MyWebAuthenticationDetailsSource myWebAuthenticationDetailsSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(dbAuthenticationProvider);
}
#Bean(name = "org.springframework.security.authenticationManager")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(WebSecurity web) throws Exception {
// #formatter:off
web.ignoring()
.antMatchers("/oauth/cache_approvals")
.antMatchers("/oauth/uncache_approvals");
// #formatter:on
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login-processing-url")
.usernameParameter("j_username")
.passwordParameter("j_password")
.authenticationDetailsSource(myWebAuthenticationDetailsSource)
.defaultSuccessUrl("/welcome")
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.deleteCookies()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", RequestMethod.GET.name()))
.logoutSuccessUrl("/login")
.permitAll();
// #formatter:on
}
}
/**
*
* #author tuan.dang
*
*/
#Configuration
#EnableWebMvcSecurity
#Order(10)
public static class AuthorizeServer extends WebSecurityConfigurerAdapter {
#Autowired
ClientDetailsService clientDetails;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(new ClientDetailsUserDetailsService(clientDetails));
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.requestMatchers()
.antMatchers("/oauth/token")
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/oauth/token").authenticated()
.and()
.anonymous().disable()
.httpBasic()
.authenticationEntryPoint(getClientAuthenticationEntryPoint())
.and()
.addFilterAfter(getClientCredentialsTokenEndpointFilter(), BasicAuthenticationFilter.class)
.addFilterBefore(new RequestContextFilter(), BasicAuthenticationFilter.class)
.exceptionHandling()
.accessDeniedHandler(new OAuth2AccessDeniedHandler());
// #formatter:on
}
#Bean(name = "clientAuthenticationManager")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
private Filter getClientCredentialsTokenEndpointFilter() throws Exception {
AbstractAuthenticationProcessingFilter filter = new ClientCredentialsTokenEndpointFilter();
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
private AuthenticationEntryPoint getClientAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
entryPoint.setTypeName("Basic");
entryPoint.setRealmName("AuthorizationServer");
return entryPoint;
}
}
}
WebInitializer.java
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebAppConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
/**
* This class replaces dispatcher-servlet.xml file
*
* #author tuan.dang
*
*/
#Configuration
#EnableWebMvc
#ImportResource("classpath:oauth2/oauth2-config.xml")
#ComponentScan(basePackages = { "net.dntuan.training.spring" })
public static class WebAppConfig extends WebMvcConfigurerAdapter {
/**
* Configure an internalResouceViewResolver. This resolver is required to use Spring MVC with jsp view
*
* #return InternalResourceViewResolver
*/
#Bean
public InternalResourceViewResolver configureInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
}
I tried to turn up logging, I got the following:
[DEBUG] [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/oauth/token'; against '/oauth/token' (AntPathRequestMatcher.java:145)
[DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] - Secure object: FilterInvocation: URL: /oauth/token?client_id=epos-frontend&grant_type=password&username=user&password=bypass&app_id=3; Attributes: [authenticated] (AbstractSecurityInterceptor.java:194)
[DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#fea1daa6: Principal: org.springframework.security.core.userdetails.User#89854e50: Username: epos-frontend; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_APP_CLIENT; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_APP_CLIENT (AbstractSecurityInterceptor.java:310)
[DEBUG] [org.springframework.security.access.vote.AffirmativeBased] - Voter: org.springframework.security.web.access.expression.WebExpressionVoter#2868d4f8, returned: 1 (AffirmativeBased.java:65)
[DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] - Authorization successful (AbstractSecurityInterceptor.java:215)
[DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] - RunAsManager did not change Authentication object (AbstractSecurityInterceptor.java:227)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - /oauth/token?client_id=epos-frontend&grant_type=password&username=user&password=bypass&app_id=3 reached end of additional filter chain; proceeding with original chain (FilterChainProxy.java:323)
[DEBUG] [org.springframework.web.servlet.DispatcherServlet] - DispatcherServlet with name 'dispatcher' processing GET request for [/javabased-oauth2/oauth/token] (DispatcherServlet.java:843)
[DEBUG] [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Looking up handler method for path /oauth/token (AbstractHandlerMethodMapping.java:222)
[DEBUG] [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.lang.String,java.util.Map<java.lang.String, java.lang.String>)] (AbstractHandlerMethodMapping.java:229)
[DEBUG] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'oauth2TokenEndpoint' (AbstractBeanFactory.java:249)
[DEBUG] [org.springframework.web.servlet.DispatcherServlet] - Last-Modified value for [/javabased-oauth2/oauth/token] is: -1 (DispatcherServlet.java:932)
[DEBUG] [org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter] - Getting access token for: epos-frontend (AbstractTokenGranter.java:59)
[DEBUG] [org.springframework.security.authentication.ProviderManager] - Authentication attempt using net.dntuan.training.spring.security.DBAuthenticationProvider (ProviderManager.java:152)
[DEBUG] [net.dntuan.training.spring.security.DBAuthenticationProvider] - entered username: user (DBAuthenticationProvider.java:40)
[DEBUG] [net.dntuan.training.spring.security.DBAuthenticationProvider] - entered password: bypass (DBAuthenticationProvider.java:41)
[DEBUG] [net.dntuan.training.spring.security.DBAuthenticationProvider] - appId: 3 (DBAuthenticationProvider.java:42)
[DEBUG] [org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor] - Written [409d7529-2f54-4ec0-8439-3f2730e89e3c] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#510b6523] (AbstractMessageConverterMethodProcessor.java:150)
[DEBUG] [org.springframework.web.servlet.DispatcherServlet] - Null ModelAndView returned to DispatcherServlet with name 'dispatcher': assuming HandlerAdapter completed request handling (DispatcherServlet.java:1019)
[DEBUG] [org.springframework.web.servlet.DispatcherServlet] - Successfully completed request (FrameworkServlet.java:961)
[DEBUG] [org.springframework.security.web.access.ExceptionTranslationFilter] - Chain processed normally (ExceptionTranslationFilter.java:115)
[DEBUG] [org.springframework.web.filter.RequestContextFilter] - Cleared thread-bound request context: FirewalledRequest[ org.apache.catalina.connector.RequestFacade#14738593] (RequestContextFilter.java:104)
[DEBUG] [org.springframework.security.web.context.SecurityContextPersistenceFilter] - SecurityContextHolder now cleared, as request processing completed (SecurityContextPersistenceFilter.java:97)
<!-- continue with new filter chain -->
[DEBUG] [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/'; against '/oauth/cache_approvals' (AntPathRequestMatcher.java:145)
[DEBUG] [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/'; against '/oauth/uncache_approvals' (AntPathRequestMatcher.java:145)
[DEBUG] [org.springframework.security.web.util.matcher.OrRequestMatcher] - Trying to match using Ant [pattern='/oauth/token'] (OrRequestMatcher.java:65)
[DEBUG] [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/'; against '/oauth/token' (AntPathRequestMatcher.java:145)
[DEBUG] [org.springframework.security.web.util.matcher.OrRequestMatcher] - No matches found (OrRequestMatcher.java:72)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] - No HttpSession currently exists (HttpSessionSecurityContextRepository.java:136)
[DEBUG] [org.springframework.security.web.context.HttpSessionSecurityContextRepository] - No SecurityContext was available from the HttpSession: null. A new one will be created. (HttpSessionSecurityContextRepository.java:90)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.header.writers.HstsHeaderWriter] - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#5688e4ae (HstsHeaderWriter.java:129)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/'; against '/logout' (AntPathRequestMatcher.java:145)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Request 'GET /' doesn't match 'POST /login-processing-url (AntPathRequestMatcher.java:127)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.authentication.AnonymousAuthenticationFilter] - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS' (AnonymousAuthenticationFilter.java:102)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.FilterChainProxy] - / at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' (FilterChainProxy.java:337)
[DEBUG] [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/'; against '/logout' (AntPathRequestMatcher.java:145)
[DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] - Secure object: FilterInvocation: URL: /; Attributes: [authenticated] (AbstractSecurityInterceptor.java:194)
[DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS (AbstractSecurityInterceptor.java:310)
[DEBUG] [org.springframework.security.access.vote.AffirmativeBased] - Voter: org.springframework.security.web.access.expression.WebExpressionVoter#f84a51b, returned: -1 (AffirmativeBased.java:65)
[DEBUG] [org.springframework.security.web.access.ExceptionTranslationFilter] - Access is denied (user is anonymous); redirecting to authentication entry point (ExceptionTranslationFilter.java:165)
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
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.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
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:108)
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:108)
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:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
I see that the token is generated Written [409d7529-2f54-4ec0-8439-3f2730e89e3c] as "application/json;charset=UTF-8" but why it redirects to login page instead of returning json?
Anyone please let me know what I'm wrong? Any help would be appreciated!
Update: the problem seems that a new filter chain is started as you can see in logs. But what is the cause???

Related

CustomAuthenticationProvider doesn't get called spring-security 5.2

I have converted an app to use spring and spring security I am using version 5.2. When I try and login my CustomAuthProvider doesn't get called. It does hit the security endpoint 'login' in the jsp and has an anonymous role. Below are the relevant configs.
#ComponentScan(basePackages = {"com.example"})
#Import({com.example.Configuration.class, WebSecurityConfig.class})
public class AppConfig {
servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/mvc/*");
Register the DelegatingFilterProxy
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
The WebSecurity class
#Configuration
#EnableWebSecurity(debug = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider)
.userDetailsService(new UserDetails());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().
authorizeRequests(a ->
a.antMatchers(
"/resources/js/**",
"/resources/scripts/**",
"/login",
"/resources/styles/**",
"/resources/images/**",
"/resources/loginPage.jsp",
"/resources/forgotUserName.jsp",
"/resources/forgotPassword.jsp",
"/mvc/jsonInitialResponse/**")
.permitAll()
.antMatchers(
"/resources/resetPassword.jsp",
"/mvc/jsonResponse/**",
"/mvc/download/**",
"/resources/**"
).authenticated())
.formLogin()
.loginPage("/resources/loginPage.jsp")
.successHandler(new CustomeAuthenticationSuccessHandler())
.failureUrl("/resources/loginPage.jsp?error=true")
.and().anonymous()
.and()
.logout()
.logoutSuccessUrl("/resources/loginPage.jsp")
.permitAll()
.and()
.csrf().disable().cors().disable();
}
}
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(final Authentication authentication) {......}
#Override
public boolean supports(Class<?> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
Any thoughts on what I may be missing? The CustomAuthenticationProvider isn't being called and either is the supports() method.
2020-10-06 12:26:29 DEBUG DefaultSavedRequest:359 - pathInfo: both null (property equals)
2020-10-06 12:26:29 DEBUG DefaultSavedRequest:359 - queryString: both null (property equals)
2020-10-06 12:26:29 DEBUG DefaultSavedRequest:383 - requestURI: arg1=/reinsurance-service-ui-war/resources/login; arg2=/reinsurance-service-ui-war/resources/images/icn-lock.png (property not equals)
2020-10-06 12:26:29 DEBUG HttpSessionRequestCache:95 - saved request doesn't match
2020-10-06 12:26:29 DEBUG FilterChainProxy:328 - /resources/images/icn-lock.png at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-10-06 12:26:29 DEBUG FilterChainProxy:328 - /resources/images/icn-lock.png at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-10-06 12:26:29 DEBUG AnonymousAuthenticationFilter:100 - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#418e8a7d: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#fffbcba8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 4503EBEA550D56CD4AF5506BC88E7576; Granted Authorities: ROLE_ANONYMOUS'
2020-10-06 12:26:29 DEBUG FilterChainProxy:328 - /resources/images/icn-lock.png at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-10-06 12:26:29 DEBUG FilterChainProxy:328 - /resources/images/icn-lock.png at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-10-06 12:26:29 DEBUG FilterChainProxy:328 - /resources/images/icn-lock.png at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-10-06 12:26:29 DEBUG AntPathRequestMatcher:177 - Checking match of request : '/resources/images/icn-lock.png'; against '/resources/js/**'
2020-10-06 12:26:29 DEBUG AntPathRequestMatcher:177 - Checking match of request : '/resources/images/icn-lock.png'; against '/resources/scripts/**'
2020-10-06 12:26:29 DEBUG AntPathRequestMatcher:177 - Checking match of request : '/resources/images/icn-lock.png'; against '/resources/styles/**'
2020-10-06 12:26:29 DEBUG AntPathRequestMatcher:177 - Checking match of request : '/resources/images/icn-lock.png'; against '/resources/images/**'
2020-10-06 12:26:29 DEBUG FilterSecurityInterceptor:219 - Secure object: FilterInvocation: URL: /resources/images/icn-lock.png; Attributes: [anonymous]
2020-10-06 12:26:29 DEBUG FilterChainProxy:313 - /resources/images/icn-pencil.png reached end of additional filter chain; proceeding with original chain
2020-10-06 12:26:29 DEBUG FilterSecurityInterceptor:348 - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#418e8a7d: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#fffbcba8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 4503EBEA550D56CD4AF5506BC88E7576; Granted Authorities: ROLE_ANONYMOUS
2020-10-06 12:26:29 DEBUG HstsHeaderWriter:169 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#51ca55f0
2020-10-06 12:26:29 DEBUG HttpSessionSecurityContextRepository:351 - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-10-06 12:26:29 DEBUG ExceptionTranslationFilter:120 - Chain processed normally
2020-10-06 12:26:29 DEBUG SecurityContextPersistenceFilter:119 - SecurityContextHolder now cleared, as request processing completed
2020-10-06 12:26:29 DEBUG AffirmativeBased:66 - Voter: org.springframework.security.web.access.expression.WebExpressionVoter#3fe8aa9d, returned: 1
2020-10-06 12:26:29 DEBUG FilterSecurityInterceptor:243 - Authorization successful
2020-10-06 12:26:29 DEBUG FilterSecurityInterceptor:256 - RunAsManager did not change Authentication object
2020-10-06 12:26:29 DEBUG FilterChainProxy:313 - /resources/images/icn-lock.png reached end of additional filter chain; proceeding with original chain
2020-10-06 12:26:29 DEBUG HstsHeaderWriter:169 - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#51ca55f0
2020-10-06 12:26:29 DEBUG HttpSessionSecurityContextRepository:351 - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-10-06 12:26:29 DEBUG ExceptionTranslationFilter:120 - Chain processed normally
2020-10-06 12:26:29 DEBUG SecurityContextPersistenceFilter:119 - SecurityContextHolder now cleared, as request processing completed```

Filter gets executed even if pattern does not match, Spring Security

The current security configuration I'm using:
#Configuration
public class SecurityConfig {
/**
* Default order of 3 as per Spring documentation.
*/
#Configuration
#EnableWebSecurity
#EnableResourceServer
public static class OAuth2SecurityConfiguration extends ResourceServerConfigurerAdapter {
private final TokenStore tokenStore;
#Autowired
public OAuth2SecurityConfiguration(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.apply(CommonSecurityConfiguration
.commonSecurityConfiguration())
.and()
.authorizeRequests().anyRequest()
.authenticated();
}
}
#Configuration
#Order(1)
public static class SecretAuthSecurityConfiguration extends WebSecurityConfigurerAdapter {
private JPAAuthenticationProvider authenticationProvider;
#Autowired
public void setAuthenticationProvider(JPAAuthenticationProvider authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider);
}
#Bean
public FilterRegistrationBean<Filter> secretFilterRegistrationBean() {
var filterRegistrationBean =
new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(
new SecretFilter();
return filterRegistrationBean;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/resource1/api/**", "/resource2/api/**")
.and()
.addFilterAfter(this.secretFilterRegistrationBean().getFilter(),
LogoutFilter.class)
.apply(CommonSecurityConfiguration
.commonSecurityConfiguration());
}
}
public static class CommonSecurityConfiguration
extends AbstractHttpConfigurer<CommonSecurityConfiguration, HttpSecurity> {
#Override
public void init(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable();
}
public static CommonSecurityConfiguration commonSecurityConfiguration() {
return new CommonSecurityConfiguration();
}
}
}
I'm pretty new to Spring Security and my goal is to build an application that allows different types of authentications for different paths within my application.
As far as I understood from articles and Spring documentation, you have a lot of flexibility in managing your filter chains, using ANT matchers and things alike.
In the code snippet above I tried to configure 2 filter chains - each one corresponds to a type of authentication:
OAuth2, token-based security configuration - described in the static class OAuth2SecurityConfiguration - where I used the annotation #EnableResourceServer, which automatically adds the org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter to a new filter chain. As per Spring documentation about #EnableResourceServer:
The annotation creates a WebSecurityConfigurerAdapter with a hard-coded Order (of 3).
A custom authentication type, which is based on a custom filter. What this filter does? It checks a header from the incoming request and it verifies if there is a trusted secret within that header, nothing too special. Here is the core of the filter:
public class SecretFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
FilterChain filterChain)
throws IOException, ServletException {
log.info("Inside SecretFilter.");
String secret = this.resolveSecret(httpServletRequest);
if (secret.isValid()) {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(null, null, null));
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
/**
* Clearing the security context after the request is made.
*/
SecurityContextHolder.getContext().setAuthentication(null);
}
The resulted filter chains:
o.s.s.web.DefaultSecurityFilterChain: Creating filter chain:a OrRequestMatcher [requestMatchers=[Ant [pattern='/resource1/api/star.star'], Ant [pattern='/resource2/api/star.star']]]
- WebAsyncManagerIntegrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- CorsFilter
- LogoutFilter
- SecretFilter <------- here is my filter
- RequestCacheAwareFilter
- SecurityContextHolderAwareRequestFilter
- AnonymousAuthenticationFilter
- SessionManagementFilter
- ExceptionTranslationFilter
o.s.s.web.DefaultSecurityFilterChain: Creating filter chain: org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration$NotOAuthRequestMatcher
- WebAsyncManagerIntegrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- CorsFilter
- LogoutFilter
- OAuth2AuthenticationProcessingFilter
- RequestCacheAwareFilter
- SecurityContextHolderAwareRequestFilter
- AnonymousAuthenticationFilter
- SessionManagementFilter
- ExceptionTranslationFilter
- FilterSecurityInterceptor
The static configuration class that should handle this type of authentication have been marked with #Order(1) annotation, because I want requests to pass first through the filter chain with the custom filter, otherwise, if requests are not intended to the specified paths, like /resource1/api/**, then pass through the OAuth filter chain.
When I do a normal request to a path /resource1/api/X for example, everything goes well, and the filter chain gets executed. But when a request on a path other than those specified above comes in, the console shows me this:
2020-09-22 01:00:03.698 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-09-22 01:00:03.698 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-09-22 01:00:03.698 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-09-22 01:00:03.698 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 4 of 12 in additional filter chain; firing Filter: 'CorsFilter'
2020-09-22 01:00:03.703 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2020-09-22 01:00:03.703 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 6 of 12 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
2020-09-22 01:00:03.715 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2020-09-22 01:00:03.715 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-09-22 01:00:03.715 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-09-22 01:00:03.715 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-09-22 01:00:03.715 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-09-22 01:00:03.716 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-09-22 01:00:03.717 DEBUG 928 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : /profile/?date=2020-09-21T22:00:03Z reached end of additional filter chain; proceeding with original chain
2020-09-22 01:00:03.718 INFO 928 --- [nio-8080-exec-4] c.s.p.s.filters.SecretFilter : Inside SecretFilter.
Why the SecretFilter gets executed at the end of the OAuth filter chain? It is not annotated with #Order annotation or anything else. My path should not be matched, so the filter chain that contains the filter should not get fired. It looks all so clear, but it is this little thing that I cannot get.
My intuition says that the filter gets registered and placed somehow with the default Ordered.LOWEST_PRECEDENCE order and it is executed after the FilterChainProxy finishes its job with the current multiplexed chain.
Any help or references to read more about it would be really appreciated.

Spring OAuth2 Full authentication is required to access this resource

Before we get started, I have looked at many of the posts regarding this topic, but none of the posts seemed to have anything that could help.
I am trying to configure my Spring Rest API to use OAuth Password Grant authentication.
Here is my current security config. currently i have no limitations on which endpoints are permitAll() or authenticated, but I had it setup previously to permit non authenticated access to /oauth/** but still had the same issue. After reading documentation, this seems like a bad thing to do because the /oauth/token endpoint should be protected with http basic authentication where the username/password are the client ID and client secret. I also tried to have it setup to have anyRequest().authenticated() and got the same issue as I am having.
#Configuration
#EnableWebSecurity
#ComponentScan({ "com.mergg.webapp.security", "com.mergg.common.web" })
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private IUserService userService;
#Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
Here is my current setup for AuthorizationServerConfig. Please note that I have tried to create an in memory client where the secret was passwordEncoder.encode("secret"). Same problem occurred. Not sure which is best practice to use, but thats a topic for another time.
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private DataSource dataSource;
#Autowired
private BCryptPasswordEncoder passwordEncoder;
public AuthorizationServerConfiguration() {
super();
}
#Bean
public TokenStore tokenStore() {
// return new JdbcTokenStore(dataSource);
return new InMemoryTokenStore();
}
// config
#Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.passwordEncoder(this.passwordEncoder)
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
// clients.jdbc(dataSource)
// .passwordEncoder(passwordEncoder)
// .withClient("mergg_mobile")
// .secret(passwordEncoder.encode("secret"))
// .authorizedGrantTypes("password");
clients.inMemory()
.withClient("test")
.secret("secret")
.authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(3600);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(tokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
Here is my ResourceServerConfiguration. I have played around with the http security element the same way that i did with the one in my security configuration. I also toyed with a stateless vs if needed session creation policy. No luck.
#Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
//#formatter:off
http
.authorizeRequests()
.antMatchers("/roles/**").hasRole("INTERNAL")
.antMatchers("/priveleges/**").hasRole("INTERNAL")
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//#formatter:on
}
}
Here are a few examples of requests I have made (with curl and postman):
curl -u test:secret -X POST localhost:5000/oauth/token\?grant_type=password\&username=test\&password=password
curl -u test:password -X POST localhost:5000/oauth/token\?grant_type=password\&username=test\&password=password
curl -X POST -vu test:secret http://localhost:5000/oauth/token -H "Accept: application/json" -d "password=password&username=test&grant_type=password&client_secret=secret&client_id=test"
curl -X POST -vu test:password http://localhost:5000/oauth/token -H "Accept: application/json" -d "password=password&username=test&grant_type=password&client_secret=secret&client_id=test"
Note that the oauth client id is test and its secret is secret. One user is test with password password
Here is the console output when I try to request a token:
23:07:36.571 [http-nio-5000-exec-2] INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet'
23:07:36.625 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
23:07:36.627 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
23:07:36.627 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
23:07:36.629 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
23:07:36.629 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET]
23:07:36.630 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'POST /oauth/token' doesn't match 'GET /logout'
23:07:36.630 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST]
23:07:36.630 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/logout'
23:07:36.630 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT]
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'POST /oauth/token' doesn't match 'PUT /logout'
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE]
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'POST /oauth/token' doesn't match 'DELETE /logout'
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.s.o.p.a.BearerTokenExtractor - Token not found in headers. Trying request parameters.
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.s.o.p.a.BearerTokenExtractor - Token not found in request parameters. Not an OAuth2 request.
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.s.o.p.a.OAuth2AuthenticationProcessingFilter - No token in request, will continue chain.
23:07:36.631 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
23:07:36.633 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
23:07:36.635 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
23:07:36.637 [http-nio-5000-exec-2] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#ad1846c9: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
23:07:36.637 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
23:07:36.637 [http-nio-5000-exec-2] DEBUG o.s.s.w.s.SessionManagementFilter - Requested session ID 61EE2368B212EC609873DFB621D5166A is invalid.
23:07:36.637 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
23:07:36.637 [http-nio-5000-exec-2] DEBUG o.s.security.web.FilterChainProxy - /oauth/token?password=password&username=test&grant_type=token at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
23:07:36.638 [http-nio-5000-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token?password=password&username=test&grant_type=token; Attributes: [#oauth2.throwOnError(authenticated)]
23:07:36.638 [http-nio-5000-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#ad1846c9: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
23:07:36.645 [http-nio-5000-exec-2] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter#73ac552e, returned: -1
23:07:36.652 [http-nio-5000-exec-2] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
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.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.mergg.webapp.security.SimpleCorsFilter.doFilter(SimpleCorsFilter.java:40)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:844)
23:07:36.660 [http-nio-5000-exec-2] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Calling Authentication entry point.
23:07:36.712 [http-nio-5000-exec-2] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#5bf2a0a6
23:07:36.716 [http-nio-5000-exec-2] DEBUG o.s.s.o.p.e.DefaultOAuth2ExceptionRenderer - Written [error="unauthorized", error_description="Full authentication is required to access this resource"] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#3b1af7db]
23:07:36.716 [http-nio-5000-exec-2] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
Here is the response I get in postman:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}

Spring Boot: Oauth2: Access is denied (user is anonymous); redirecting to authentication entry point

I am trying to use spring boot oauth2 to accomplish stateless authentication and authorisation. However, I am struggling to it working.
Here is my code:
#EnableAutoConfiguration
#ComponentScan
//#EnableEurekaClient
//#EnableZuulProxy
#Configuration
public class AuthServiceApp {
public static void main(String[] args) {
SpringApplication.run(AuthServiceApp.class, args);
}
}
Authorisation Config:
#Configuration
#EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager auth;
#Autowired
private DataSource dataSource;
#Autowired
private CustomUserDetailsService userDetailService;
#Autowired
private ClientDetailsService clientDetailsService;
#Bean
public JdbcTokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// #OFF
endpoints
.authorizationCodeServices(authorizationCodeServices())
.authenticationManager(auth)
.userDetailsService(userDetailService)
.tokenStore(tokenStore());
// #ON
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// #OFF
clients.jdbc(dataSource)
.withClient("client")
.secret("secret")
.authorizedGrantTypes("password","refresh_token", "client_credentials")
.authorities("USER")
.scopes("read", "write")
.autoApprove(true)
.accessTokenValiditySeconds(60)
.refreshTokenValiditySeconds(300);
// #ON
}
}
Resource Server Config:
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
#Autowired
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
#Override
public void configure(HttpSecurity http) throws Exception {
// #OFF
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint)
.and()
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
.csrf()
// .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
.disable()
.headers()
.frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers("/identity/**").authenticated();
// #ON
}
}
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #OFF
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
// #ON
}
}
Controller:
#RestController
#RequestMapping("/")
public class AuthController {
#PreAuthorize("#oauth2.hasScope('read')")
#GetMapping("/user")
public Principal getUser(Principal user) {
return user;
}
}
I can get the access token using POSTMAN. I am using the same access token in the header to get the user details as http://localhost:8082/identity/user before it gets expired. However, I get login page html response with following log on console:
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 301C6EDD36372CF9C553FCFCD4AA47E3; Granted Authorities: ROLE_ANONYMOUS'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy : /user at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy : /user at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy : /user at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/user'; against '/login'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /user; Attributes: [authenticated]
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 301C6EDD36372CF9C553FCFCD4AA47E3; Granted Authorities: ROLE_ANONYMOUS
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#55b4f25d, returned: -1
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]
But it seems like I have been authenticated when making first call to get the access token to oauth/token:
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#50c8f5e8: Principal: org.springframework.security.core.userdetails.User#af12f3cb: Username: client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 2F070B741A55BD1E47933621D9127780; Granted Authorities: USER
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#61f8721f, returned: 1
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.security.web.FilterChainProxy : /oauth/token reached end of additional filter chain; proceeding with original chain
2017-05-24 22:54:35.967 DEBUG 16899 --- [nio-8082-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/token
2017-05-24 22:54:35.968 DEBUG 16899 --- [nio-8082-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException]
2017-05-24 22:54:35.975 DEBUG 16899 --- [nio-8082-exec-6] .o.p.p.ResourceOwnerPasswordTokenGranter : Getting access token for: client
2017-05-24 22:54:35.975 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
Hibernate: select user0_.id as id1_1_, user0_.enabled as enabled2_1_, user0_.name as name3_1_, user0_.password as password4_1_, user0_.username as username5_1_ from user user0_ where user0_.username=?
Hibernate: select roles0_.user_id as user_id1_2_0_, roles0_.role_id as role_id2_2_0_, role1_.id as id1_0_1_, role1_.role as role2_0_1_ from user_role roles0_ inner join role role1_ on roles0_.role_id=role1_.id where roles0_.user_id=?
2017-05-24 22:54:36.125 INFO 16899 --- [nio-8082-exec-6] o.s.s.o.p.token.store.JdbcTokenStore : Failed to find access token for token 180c2528-b712-4088-9cce-71e9cc7ccb94
2017-05-24 22:54:36.232 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2017-05-24 22:54:36.232 DEBUG 16899 --- [nio-8082-exec-6] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
May be I am configuring something wrong. What am I missing here?
I had a similar issue and found that the OAuth2AuthenticationProcessingFilter was not getting invoked by the filter chain and because of which, user was not getting authenticated and hence treated as anonymous.
Am using Spring-boot 1.5.3 version and I added below line in application.yml to fix the ordering.
security.oauth2.resource.filter-order=3
There must be a log statement present which shows that its getting invoked
DEBUG 34386 --- [nio-8082-exec-1] o.s.security.web.FilterChainProxy : /foo at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
Reference - https://github.com/spring-projects/spring-security-oauth/issues/993
To use
.authorizedGrantTypes("password","refresh_token", "client_credentials")
you need to open access to
/auth/token
in security configuration of your Authorization Server
#Override
protected void configure(HttpSecurity http) throws Exception {
code...
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.anyRequest().authenticated()
code...
}
I was facing the same problem and managed to fix it by explicitly disabling some spring autoconfiguration:
#EnableAutoConfiguration(exclude = [OAuth2AutoConfiguration::class,
SecurityAutoConfiguration::class, SecurityFilterAutoConfiguration::class])
Also check if you are using multiple OAuth2 filters coming from multiple auth-related dependices/libraries.
In my case I was using
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
Along with another custom OAuth2 library used in my organization, which caused the spring library to attempt to authenticate before the custom (correct) one, and with no credentials fed to it of course throwing this exact exception.
My service calls worked once I removed the Spring OAuth2 dependency.

Spring OAuth: Custom form for authenticating authorization endpoint

How can I set up a custom login form to protect my /oauth/authorize endpoint in an Spring Boot Application that is both a Authorization and Resource Server? I want to achieve that a user has to log in to make requests to /oauth/authorize. All resources, that are not /login and /oauth/** should be handled as secured resources protected by OAuth (requiring a valid access token)
So when a user calls localhost:1234/oauth/authorize?client_id=client&response_type=token&redirect_uri=http://localhost:5678 he is first redirected to the login form and after successfully loggin in redirect to the /oauth/authorize endpoint where the implicit OAuth flow proceeds.
When I try the following it works, using the standard basic authentication popup window
#Configuration
#EnableAuthorizationServer
public class OAuthConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory()
.withClient("client")
.authorizedGrantTypes("implicit", "refresh_token")
.scopes("read");
}
}
The Resource config
#Configuration
#EnableResourceServer
public class ResourceConfiguration
extends ResourceServerConfigurerAdapter
{
#Override
public void configure(final HttpSecurity http) throws Exception {
// #formatter:off
http.authorizeRequests().antMatchers("/login").permitAll().and()
.authorizeRequests().anyRequest().authenticated();
// #formatter:on
}
}
The Web Security config
#Configuration
public class WebSecurityConfiguration
extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/oauth/authorize").authenticated().and()
.authorizeRequests().anyRequest().permitAll().and().httpBasic();
}
}
but as soon as I replace httpBasic() with the following it fails:
#Configuration
public class WebSecurityConfiguration
extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/oauth/authorize").authenticated().and()
.authorizeRequests().anyRequest().permitAll().and().formLogin().loginPage("/login").and().csrf()
.disable();
}
}
and my POST from the login Page is not redirected, it always just returns to /login
The output from the console is as following
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/css/**'
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/js/**'
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/images/**'
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/**/favicon.ico'
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/error'
o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/token']
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/oauth/token'
o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/token_key']
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/oauth/token_key'
o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/check_token']
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/oauth/check_token'
o.s.s.web.util.matcher.OrRequestMatcher : No matches found
o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration$NotOAuthRequestMatcher#5fe3eb5f
o.s.s.web.util.matcher.OrRequestMatcher : matched
o.s.security.web.FilterChainProxy : /login at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
o.s.security.web.FilterChainProxy : /login at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
o.s.security.web.FilterChainProxy : /login at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#51c78264
o.s.security.web.FilterChainProxy : /login at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/logout'
o.s.security.web.FilterChainProxy : /login at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
o.s.s.o.p.a.BearerTokenExtractor : Token not found in headers. Trying request parameters.
o.s.s.o.p.a.BearerTokenExtractor : Token not found in request parameters. Not an OAuth2 request.
p.a.OAuth2AuthenticationProcessingFilter : No token in request, will continue chain.
o.s.security.web.FilterChainProxy : /login at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
o.s.security.web.FilterChainProxy : /login at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
o.s.security.web.FilterChainProxy : /login at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#90541710: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: BDCE2D7EA7252AEA2506633726B8BA19; Granted Authorities: ROLE_ANONYMOUS'
o.s.security.web.FilterChainProxy : /login at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
o.s.security.web.FilterChainProxy : /login at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
o.s.security.web.FilterChainProxy : /login at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/login'
o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /login; Attributes: [#oauth2.throwOnError(permitAll)]
o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#90541710: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: BDCE2D7EA7252AEA2506633726B8BA19; Granted Authorities: ROLE_ANONYMOUS
o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#bba9bfc, returned: 1
o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
o.s.security.web.FilterChainProxy : /login reached end of additional filter chain; proceeding with original chain
o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
Adding an #Order(-10) to the WebSecurityConfig resolves the issue. I think this annoation ensures that the WebSecurityConfig is used before the ResourceConfig. My final configuration looks like this:
#Configuration
#Order(-10)
public class WebSecurityConfig
extends WebSecurityConfigurerAdapter
{
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.authorizeRequests().antMatchers("/oauth/authorize").authenticated()
.and()
.authorizeRequests().anyRequest().permitAll()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.csrf().disable();
// #formatter:on
}
}

Resources