Spring OAuth: Custom form for authenticating authorization endpoint - spring

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
}
}

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 boot oauth2 - cannot obtain access token when use Basic Auth

I have problem to get access token from my spring-boot server v.2.0.3.RELEASE. I use spring-security-oauth v.2.3.3.RELEASE.
When I use postman I can get access token and in log I see that BasicAuthenticateFilter is match. But when use angularjs/react, BasicAuthenticateFilter is ommited and I got 401 without any message.
AuthenticationServer
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
static final String CLIENT_ID = "client";
static final String CLIENT_SECRET = "$2a$04$AMTwWHtjscVAHH4gPHx04.82v/W80KVJptp0l/QUWrlkiWU7g7wbe";
static final String GRANT_TYPE = "password";
static final String AUTHORIZATION_CODE = "authorization_code";
static final String REFRESH_TOKEN = "refresh_token";
static final String IMPLICIT = "implicit";
static final String SCOPE_READ = "read";
static final String SCOPE_WRITE = "write";
static final String TRUST = "trust";
static int ACCESS_TOKEN_VALIDITY_SECONDS = 2*60*60;
static final int REFRESH_TOKEN_VALIDITY_SECONDS = 6*60*60;
#Autowired
private TokenStore tokenStore;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(CLIENT_ID)
.secret(CLIENT_SECRET)
.authorizedGrantTypes(GRANT_TYPE, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT)
.scopes(SCOPE_READ, SCOPE_WRITE, TRUST)
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
.refreshTokenValiditySeconds(REFRESH_TOKEN_VALIDITY_SECONDS);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.authenticationManager(authenticationManager);
}
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
return propertySourcesPlaceholderConfigurer;
}
}
SecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Resource(name = "userService")
private UserDetailsService userDetailsService;
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/oauth/token").permitAll()
.anyRequest().authenticated();
}
#Bean
public BCryptPasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(50);
return bean;
}
}
ResourceServer
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "resource_id";
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/h2-console/**").permitAll()
.antMatchers("/user/register","/user/login").permitAll()
.antMatchers("/**").authenticated()
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler())
.and().headers().frameOptions().disable();
}
}
angularjs code
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}])
.controller('View1Ctrl', ['$http','$httpParamSerializer', function($http, $httpParamSerializer) {
var ctrl = this;
this.data = {
grant_type:"password",
username: "",
password: "",
client_id: "client"
};
this.encoded = btoa("client:secret");
this.login = function() {
var req = {
method: 'POST',
url: "http://localhost:8080/api/oauth/token",
headers: {
"Authorization": "Basic " + ctrl.encoded,
"Content-type": "application/x-www-form-urlencoded; charset=utf-8"
},
data: $httpParamSerializer(ctrl.data)
}
$http(req).then(function(data){
console.log(data);
$http.defaults.headers.common.Authorization =
'Bearer ' + data.data.access_token;
$cookies.put("access_token", data.data.access_token);
window.location.href="index";
}, function(error) {
console.log(error);
});
}
}]);
This is my log from spring-boot
2018-06-22 19:01:45.134 INFO 23778 --- [nio-8080-exec-3] o.a.c.c.C.[Tomcat].[localhost].[/api] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-06-22 19:01:45.134 INFO 23778 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2018-06-22 19:01:45.143 INFO 23778 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 9 ms
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/token']
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.web.util.matcher.OrRequestMatcher : matched
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /oauth/token' doesn't match 'GET /logout
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /oauth/token' doesn't match 'POST /logout
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /oauth/token' doesn't match 'PUT /logout
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /oauth/token' doesn't match 'DELETE /logout
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2018-06-22 19:01:45.144 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#64454d87: 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'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy : /oauth/token at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2018-06-22 19:01:45.145 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#64454d87: 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
2018-06-22 19:01:45.146 DEBUG 23778 --- [nio-8080-exec-3] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#62efc6af, returned: -1
2018-06-22 19:01:45.153 DEBUG 23778 --- [nio-8080-exec-3] 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
I find out solution for my problem. Main problem was with send OPTIONS request to oauth/token. I change my CorsFilter and SecurityConfig.
SecurityConfig.java
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
}
SimpleCorsFilter.java
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {
public SimpleCorsFilter() {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
After this changes I got access token

Getting 404 after oauth2 authentication success and an anonymous token

I am using oauth2 with springboot 1.5.6.RELEASE and I am using jdbc authentication with oauth2.
I added the property: security.oauth2.resource.filter-order = 3
1- AuthorizationServerConfigurerAdapter:
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
#Lazy
private AuthenticationManager authenticationManager;
#Autowired
private Environment env;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);
endpoints.authenticationManager(authenticationManager);
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource());
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
return dataSource;
}
}
2- ResourceServerConfigurerAdapter
#EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/ws/**").authorizeRequests().anyRequest().authenticated();
}
}
3- SecurityConfig
#Configuration
#EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private CustomAuthenticationSuccessHandler successHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/", "/registerCompany", "/registerEmployee", "/jobs", "/returnPassword", "/resetPassword",
"/faces/public/**", "/resources/**", "/template/**", "/faces/fonts/*",
"/faces/javax.faces.resource/**", "/ws/**", "/login", "/oauth/**", "/error")
.permitAll().antMatchers("/admin/**", "/faces/admin/**").hasAuthority("ROLE_ADMIN")
.antMatchers("/employeeProfile", "/employeeMainPage", "/employeeAskJob").hasAuthority("ROLE_EMPLOYEE")
.antMatchers("/companyProfile", "/companyMainPage", "/companyPostJob", "/companySearch",
"/branchProfile")
.hasAnyAuthority("ROLE_COMPANY,ROLE_BRANCH,ROLE_ADMIN").anyRequest().fullyAuthenticated().and()
.formLogin().loginPage("/login").permitAll().successHandler(successHandler).failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password").and().logout().deleteCookies("JSESSIONID")
.logoutUrl("/logout").deleteCookies("remember-me").logoutSuccessUrl("/").permitAll().and().rememberMe();
// http.sessionManagement().invalidSessionUrl("/login?invalidSession");
// cache resources
http.headers().addHeaderWriter(new DelegatingRequestMatcherHeaderWriter(
new AntPathRequestMatcher("/javax.faces.resource/**"), new HeaderWriter() {
#Override
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
response.addHeader("Cache-Control", "private, max-age=86400");
}
})).defaultsDisabled();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(11);
}
}
I am trying to generate a token using postman with a post request to url http://localhost:8082/dawam2/oauth/token?grant_type=password
and I use basic authentication and set the username=myclient_id and password=myclient_secret. So the header (Authorization : Basic Basic bXljbGllbnRfaWQ6bXljbGllbnRfc2VjcmV0) was generated
and I set the header Content-Type: application/x-www-form-urlencoded; charset=utf-8.
The response I am getting instead of a generated token :
!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> Not Found</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/9.0.0.M18</h3></body></html>
Here are the debugging info:
2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token']
2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token'
2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - matched
2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-09-26 15:32:16,833 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#1d47c7a
2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET]
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/logout'
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST]
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /oauth/token' doesn't match 'POST /logout
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT]
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /oauth/token' doesn't match 'PUT /logout
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE]
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /oauth/token' doesn't match 'DELETE /logout
2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found
2017-09-26 15:32:16,834 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-09-26 15:32:16,834 DEBUG o.s.s.w.a.w.BasicAuthenticationFilter - Basic Authentication Authorization header found for user 'myclient_id'
2017-09-26 15:32:16,834 DEBUG o.s.s.a.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2017-09-26 15:32:16,849 DEBUG o.s.s.w.a.w.BasicAuthenticationFilter - Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#d9cf8114: Principal: org.springframework.security.core.userdetails.User#6a9879e3: Username: myclient_id; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_EMPLOYEE; 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_EMPLOYEE
2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken#d9cf8114: Principal: org.springframework.security.core.userdetails.User#6a9879e3: Username: myclient_id; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_EMPLOYEE; 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_EMPLOYEE'
2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy#15d6aaa
2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-09-26 15:32:16,850 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token'
2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token?grant_type=password; Attributes: [fullyAuthenticated]
2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#d9cf8114: Principal: org.springframework.security.core.userdetails.User#6a9879e3: Username: myclient_id; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_EMPLOYEE; 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_EMPLOYEE
2017-09-26 15:32:16,851 DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter#14cb584, returned: 1
2017-09-26 15:32:16,851 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
2017-09-26 15:32:16,851 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2017-09-26 15:32:16,851 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password reached end of additional filter chain; proceeding with original chain
2017-09-26 15:32:16,853 DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
2017-09-26 15:32:16,853 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token']
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/oauth/token'
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token_key']
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/oauth/token_key'
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/check_token']
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/oauth/check_token'
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found
2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-09-26 15:32:16,854 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
2017-09-26 15:32:16,854 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET]
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/logout'
2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST]
2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'POST /logout
2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT]
2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'PUT /logout
2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE]
2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'DELETE /logout
2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 5 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'POST /login
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 6 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 7 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 8 of 12 in additional filter chain; firing Filter: 'RememberMeAuthenticationFilter'
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-09-26 15:32:16,855 DEBUG 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: null; Granted Authorities: ROLE_ANONYMOUS'
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password reached end of additional filter chain; proceeding with original chain
2017-09-26 15:32:16,856 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-09-26 15:32:16,856 DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
2017-09-26 15:32:16,856 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
How can I fix this issue?
The issue was related to Jersey configuration, it was stealing requests from oauth2, i had to reconfigure it with #ApplicationPath("/ws")
so the configuration now looks like :
#Configuration
#ApplicationPath("/ws")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(DawamService.class);
}
}
and my webservice implementation class like :
#Component
#Path("/dawam")
public class DawamService extends DawamServiceBase {
#GET
#Produces({ MediaType.TEXT_HTML })
#Path("/test")
public String getHTML() {
System.out.println("##### Welcome to test webservice #########");
return "Welcome to test webservice";
}
}
I have the same problem and I can fixed it.
In my case the reason was in the following:
My servlet-mapping for dispather servlet in web.xml
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
It means the all http requests for access to your resources should be started with '/api' (ex. /api/user/2 or /api/login) even if #RequestMapping points as '/user/{id}' or /login. When you request a token by oauth2/token URL, spring or other filters handle it, but dispatcherServlet could not find any controller corresponding to your request and we have 404 error.
To resolve this, I just added the one method to endpoints in AuthorizationServerConfiguration class.
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter
...
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.prefix("/api") //<---- PREFIX WAS ADDED
.userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
}
...
}
I think the
.pathMapping("/oauth/token", "/api/oauth/token")
code instead of .prefix("/api") also can resolve the problem.
It changes request for getting the tokens.
After made change I get the tokens by URL
/api/oauth/token
Of course I can mistake but it works for me. Thanks.

Spring Boot Oauth Custom Login Form

I followed the spring tutorial "SSO with OAuth2: Angular JS and Spring Security Part V".
I converted the "authserver"-project from maven to gradle after that the custom login form doesn't work anymore.
Are the wro tasks in the pom.xml needed for the login form to work?
I also tried this tutorial but it didn't work in my scenario either:
http://docs.spring.io/spring-security/site/docs/3.2.x/guides/form.html
I hope that you can help me.
Logfile:
2016-05-18 11:14:53.667 DEBUG 22312 --- [nio-9999-exec-9] o.s.security.web.FilterChainProxy : /login at position 5 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
2016-05-18 11:14:53.667 DEBUG 22312 --- [nio-9999-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /logout
2016-05-18 11:14:53.667 DEBUG 22312 --- [nio-9999-exec-9] o.s.security.web.FilterChainProxy : /login at position 6 of 14 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2016-05-18 11:14:53.667 DEBUG 22312 --- [nio-9999-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /login
2016-05-18 11:14:53.667 DEBUG 22312 --- [nio-9999-exec-9] o.s.security.web.FilterChainProxy : /login at position 7 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
2016-05-18 11:14:53.667 DEBUG 22312 --- [nio-9999-exec-9] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
Code in the OAuth2ServerConfiguration:
#Override
public void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/login").permitAll()
.and().requestMatchers()
.antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.and().authorizeRequests()
.anyRequest().authenticated();
}
MainAuthserverApplication.java:
#ComponentScan
#SessionAttributes("authorizationRequest")
#EnableAutoConfiguration()
#EnableConfigurationProperties({AuthProperties.class})
public class MainAuthserverApplication extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
registry.addViewController("/oauth/confirm_access").setViewName("authorize");
}
I already fixed the problem myself:
It seems that these two methods have to be in the same class:
#Configuration
#Order(-20)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.formLogin().loginPage("/login").permitAll().and().requestMatchers()
.antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access").and().authorizeRequests()
.anyRequest().authenticated();
// #formatter:on
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager);
}
}

Resources