Restricted Access Using Scope in JWT and Spring - spring

Well, i have a JWT with scope definied in a claim called scp, see the peace of jwt:
"scp": "xpto_role user_impersonation",
So, in my Spring application i have the following Configuration:
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/urlabc/**").hasAuthority("abc")
.antMatchers("/urlabc/**").authenticated();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("xpto");
}
}
ANd in my restController:
#RestController
public class TestResourceOne {
#RequestMapping(value = "/endpoint001")
public Double endpoint001(#RequestParam("value") Double value) {
return Math.sqrt(value);
}
}
Look, my scope passed by JWT is "xpto_role" in claim scp. In my SpringApp i want to force a Access Denied so i putted a "abc" role in "hasAuthority" method, but user is allowed to access my endpoint anyway.
The configuration is correct ?
Edit 1:
After remove the "authenticated()" line and putted the correct role i got Access Denied yet, see the error:
2018-07-20 16:57:36.732 DEBUG 6828 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /calcsqrt?value=10.0 at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2018-07-20 16:57:36.732 DEBUG 6828 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.oauth2.provider.OAuth2Authentication#8f785707: Principal: null; Credentials: [PROTECTED]; Authenticated: true; Details: remoteAddress=127.0.0.1, tokenType=BearertokenValue=<TOKEN>; Not granted any authorities'
2018-07-20 16:57:36.732 DEBUG 6828 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /calcsqrt?value=10.0 at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2018-07-20 16:57:36.732 DEBUG 6828 --- [nio-8080-exec-1] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy#63dfada0
2018-07-20 16:57:36.732 DEBUG 6828 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /calcsqrt?value=10.0 at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2018-07-20 16:57:36.733 DEBUG 6828 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /calcsqrt?value=10.0 at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2018-07-20 16:57:36.733 DEBUG 6828 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/calcsqrt'; against '/calcsqrt/**'
2018-07-20 16:57:36.733 DEBUG 6828 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /calcsqrt?value=10.0; Attributes: [#oauth2.throwOnError(hasRole('ROLE_EXEC_CALCSQRT'))]
2018-07-20 16:57:36.733 DEBUG 6828 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.oauth2.provider.OAuth2Authentication#8f785707: Principal: null; Credentials: [PROTECTED]; Authenticated: true; Details: remoteAddress=127.0.0.1, tokenType=BearertokenValue=<TOKEN>; Not granted any authorities
2018-07-20 16:57:36.733 DEBUG 6828 --- [nio-8080-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#7475b738, returned: -1
2018-07-20 16:57:36.734 DEBUG 6828 --- [nio-8080-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-4.2.7.RELEASE.jar:4.2.7.RELEASE]

Related

Spring Security applying HttpSecurity filter before building user principal

I have a springboot application that is using Keycloak to handle JWT authentication. If I use #PreAuthorize on my controller method, everything works as expected, but the URL antMatcher pattern based HttpSecurity is not. From what I can tell, Spring is applying the security filter BEFORE building the user principal. In the logs, I see it testing against Anonymous, even though a valid Bearer token was passed, and I'm able to see the AuthenticationPrincipal inside the controller method.
Basically, HttpSecurity is running its rules against Anonymous, even though later a valid Principal is created and can be used by #PreAuthorize checks.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(
AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider
= keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakConfigResolver() {
#Override
public KeycloakDeployment resolve(HttpFacade.Request request) {
KeycloakDeployment deployment = null;
AdapterConfig adapterConfig = new AdapterConfig();
adapterConfig.setAuthServerUrl(System.getProperty("keycloak.auth-server-url"));
adapterConfig.setRealm(System.getProperty("keycloak.realm"));
adapterConfig.setResource(System.getProperty("keycloak.resource"));
// adapterConfig.setUseResourceRoleMappings(true);
adapterConfig.setSslRequired("external");
adapterConfig.setPublicClient(true);
deployment = KeycloakDeploymentBuilder.build(adapterConfig);
return deployment;
}
};
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(
new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues())
.and().csrf().disable()
.authorizeRequests()
.antMatchers("/api/public/*").permitAll()
.antMatchers("/api/admin/*").hasRole("admin")
.antMatchers("/api/*").authenticated()
;
}
}
The spring security logs look like
2020-11-28 10:00:45.659 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/condition at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-11-28 10:00:45.659 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/condition at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-11-28 10:00:45.660 DEBUG 25655 --- [nio-8180-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2020-11-28 10:00:45.660 DEBUG 25655 --- [nio-8180-exec-1] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2020-11-28 10:00:45.662 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/medical-condition at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-11-28 10:00:45.663 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/medical-condition at position 4 of 11 in additional filter chain; firing Filter: 'CorsFilter'
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/medical-condition at position 5 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /api/admin/condition' doesn't match 'GET /logout'
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/admin/condition'; against '/logout'
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /api/admin/condition' doesn't match 'PUT /logout'
2020-11-28 10:00:45.664 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2020-11-28 10:00:45.665 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /api/admin/condition' doesn't match 'DELETE /logout'
2020-11-28 10:00:45.665 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2020-11-28 10:00:45.665 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/condition at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2020-11-28 10:00:45.665 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.s.HttpSessionRequestCache : saved request doesn't match
2020-11-28 10:00:45.665 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/condition at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-11-28 10:00:45.666 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/condition at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-11-28 10:00:45.667 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken#2aa3a4a: 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'
2020-11-28 10:00:45.667 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/medical-condition at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-11-28 10:00:45.668 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.session.SessionManagementFilter : Requested session ID 8C6524CDA3CD92F69B885542B2E5DF1C is invalid.
2020-11-28 10:00:45.668 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/condition at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-11-28 10:00:45.668 DEBUG 25655 --- [nio-8180-exec-1] o.s.security.web.FilterChainProxy : /api/admin/condition at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-11-28 10:00:45.669 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/admin/condition'; against '/api/public/*'
2020-11-28 10:00:45.669 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/api/admin/condition'; against '/api/admin/*'
2020-11-28 10:00:45.669 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /api/admin/condition; Attributes: [hasRole('ROLE_admin')]
2020-11-28 10:00:45.669 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken#2aa3a4a: 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
2020-11-28 10:00:45.673 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#4e7d07d7, returned: -1
2020-11-28 10:00:45.679 DEBUG 25655 --- [nio-8180-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
Before you configure your own specific configuration, you need to call the Keycloak-configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http); // <----
http.... //
}
The configure method needs to called first and better option user principal would be to add an interceptor rather than filters..and please add super.configure(http);
Thanks!

Spring Security loadUserByUsername() method is not called and authentication is sucess for incorrect password

I am implementing HTTP Basic auth scheme for my REST services using custom DAO UserDetailsService. However this overridden method is not getting called and authentication succeeds even if i send incorrect password to the API (through POSTMAN). Any inputs will be helpful.
My Application class
#SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
#EnableNeo4jRepositories("galaxy.spring.data.neo4j.repositories")
#EnableWebSecurity
public class SampleMovieApplication extends WebSecurityConfigurerAdapter {
public static String REALM = "REALM";
#Autowired
private static UserService userService;
public static void main(String[] args) {
ConfigurableApplicationContext configContext =
SpringApplication.run(SampleMovieApplication.class, args);
configContext.getBean(RepoInit.class).fillWithTestdata();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and()
.authorizeRequests().anyRequest().fullyAuthenticated()
.antMatchers("/galaxy/appuser/**").hasAnyRole("ADMIN","USER")
.antMatchers("/galaxy/appadmin/**").hasRole("ADMIN")
.and().csrf().disable()
.httpBasic().realmName("REALM").authenticationEntryPoint(getBasicAuthEntryPoint());
}
#Bean
public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
return new CustomBasicAuthenticationEntryPoint();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("Calling authenticator");
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
}
#Bean
public UserDetailsService userDetailsService() {
System.out.println(userService == null ? " userservice is null " : "userservice is not null");
return new UserDetailsServiceImp(userService);
};
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
};
}
My custom UserDetailsService class
public class UserDetailsServiceImp implements UserDetailsService {
private UserService userService;
public UserDetailsServiceImp(UserService userService) {
this.userService = userService;
}
/*#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
DomainUser user = findUserbyUername(username);
UserBuilder builder = null;
if (user != null) {
builder = org.springframework.security.core.userdetails.User.withUsername(username);
builder.password(new BCryptPasswordEncoder().encode(user.getPassword()));
builder.roles("ROLE_" + user.getBelongsTo().get(0).getDomainUserGroup().getAuthorityname());
} else {
throw new UsernameNotFoundException("User not found.");
}
return builder.build();
} */
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("called load method");
DomainUser user = null;
Set<GrantedAuthority> grantedAuthorities = null;
try
{
user = findUserbyUername(username);
if(user == null)
throw new UsernameNotFoundException("User " + username + " not available");
grantedAuthorities = new HashSet<>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" +
user.getBelongsTo().get(0).getDomainUserGroup().getAuthorityname()));
}
catch(Exception exp) {
exp.printStackTrace();
}
System.out.println("Returning new userdetails");
return new
org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(), grantedAuthorities);
}
private DomainUser findUserbyUername(String username) {
return userService.findByName(username);
}
}
The SPRING SECURITY DEBUG LOG after posting a request
2020-05-03 11:06:12.884 INFO 19868 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-05-03 11:06:12.884 INFO 19868 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-05-03 11:06:12.906 INFO 19868 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 22 ms
2020-05-03 11:06:12.930 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-05-03 11:06:12.930 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-05-03 11:06:12.930 DEBUG 19868 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl#452579c9: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#452579c9: Principal: org.springframework.security.core.userdetails.User#586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; 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_ADMIN'
2020-05-03 11:06:12.930 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-05-03 11:06:12.930 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 4 of 12 in additional filter chain; firing Filter: 'CorsFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /galaxy/appadmin/usergroup' doesn't match 'GET /logout'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/galaxy/appadmin/usergroup'; against '/logout'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /galaxy/appadmin/usergroup' doesn't match 'PUT /logout'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /galaxy/appadmin/usergroup' doesn't match 'DELETE /logout'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'admin'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.s.HttpSessionRequestCache : saved request doesn't match
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken#452579c9: Principal: org.springframework.security.core.userdetails.User#586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; 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_ADMIN'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /galaxy/appadmin/usergroup; Attributes: [fullyAuthenticated]
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#452579c9: Principal: org.springframework.security.core.userdetails.User#586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; 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_ADMIN
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#6a8bc4e6, returned: 1
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2020-05-03 11:06:12.945 DEBUG 19868 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /galaxy/appadmin/usergroup reached end of additional filter chain; proceeding with original chain
DomainUserGroup request is testgroup3
2020-05-03 11:06:13.126 DEBUG 19868 --- [nio-8080-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2020-05-03 11:06:13.126 DEBUG 19868 --- [nio-8080-exec-1] 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#4aaae30c
2020-05-03 11:06:13.126 DEBUG 19868 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
Add this in SampleMovieApplication class...
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
}
Remove this:
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("Calling authenticator");
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
}
Solved the problem. It is very funny that we have to invalidate the session in the controller (like we are logging out) and clear the secuirty context programatically. Now it is consistent and authenticates every request.
#PostMapping("/galaxy/appadmin/usergroup")
public ResponseEntity<Object> createDomainUserGroup(#RequestBody
DomainUserGroup domainusergrp,HttpServletRequest request, HttpServletResponse response) {
System.out.println(" DomainUserGroup request is "+ domainusergrp.getName());
DomainUserGroup domainc = userGroupService.save(domainusergrp);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").
buildAndExpand(domainc.getId()).toUri();
SecurityContextHolder.clearContext();
HttpSession session= request.getSession(false);
if(session != null) {
session.invalidate();
}
return ResponseEntity.created(location).build();
}

Client Loading More times in token end point

Token api I am using http://localhost:8086/oauth/token with grant type password
Input:
username:user
password:password
grant_type:password
First hit After running the application:
1)Client is loading is 4 times (loadClientByClientId method from ClientDetailsService interface)
2)Authenticating user one time (authenticate method from AuthenticationManager interface)
3)Again Client Authenticating 3 times
From second hit:
Client is loading 4 times
Authenticating user one time
AuthorizationServerConfig:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private TokenStore tokenStore;
#Autowired
private MyAuthenticationManager authenticationManager;
#Autowired
MongoClientDetailsService clientdetailservice;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).authenticationManager(authenticationManager).tokenServices(tokenServices());
}
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore);
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setClientDetailsService(clientdetailservice);
return defaultTokenServices;
}
}
SecurityConfig:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().anonymous().disable().authorizeRequests().antMatchers("/**").permitAll();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
public PasswordEncoder encoder() {
return NoOpPasswordEncoder.getInstance();
}
}
MongoClientDetailsService:
#Primary
#Service
public class MongoClientDetailsService implements ClientDetailsService {
static final String CLIEN_ID = "web-client";
static final String CLIENT_SECRET = "web-client-secret";
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 final int ACCESS_TOKEN_VALIDITY_SECONDS = 1 * 6 * 60;
static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 6 * 60 * 60;
#Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
System.out.println("loadClientByClientId");
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId(CLIEN_ID);
clientDetails.setAuthorizedGrantTypes(Arrays.asList(GRANT_TYPE, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT));
clientDetails.setClientSecret(CLIENT_SECRET);
clientDetails.setScope(Arrays.asList(SCOPE_READ, SCOPE_WRITE, TRUST));
clientDetails.setAccessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS);
clientDetails.setRefreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS);
clientDetails.setAuthorities(getAuthority());
return clientDetails;
}
private List getAuthority() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
}
MyAuthenticationManager:
#Component
public class MyAuthenticationManager implements AuthenticationManager {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
System.out.println("authenticate");
return new UsernamePasswordAuthenticationToken("123", "123", getAuthority());
}
private List getAuthority() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
}
Logs after hitting api:
2020-01-17 00:17:26.204 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/token']
2020-01-17 00:17:26.204 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2020-01-17 00:17:26.205 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : matched
2020-01-17 00:17:26.205 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-01-17 00:17:26.206 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-01-17 00:17:26.207 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'GET /logout'
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/logout'
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'PUT /logout'
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'DELETE /logout'
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2020-01-17 00:17:26.209 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2020-01-17 00:17:26.210 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'web-client'
2020-01-17 00:17:26.211 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
loadClientByClientId
2020-01-17 00:17:26.214 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#8c4296e2: Principal: org.springframework.security.core.userdetails.User#cce1ec64: Username: web-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; 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_ADMIN
2020-01-17 00:17:26.214 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2020-01-17 00:17:26.214 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.s.HttpSessionRequestCache : saved request doesn't match
2020-01-17 00:17:26.214 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-01-17 00:17:26.215 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-01-17 00:17:26.216 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken#8c4296e2: Principal: org.springframework.security.core.userdetails.User#cce1ec64: Username: web-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; 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_ADMIN'
2020-01-17 00:17:26.216 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-01-17 00:17:26.216 DEBUG 6432 --- [nio-8086-exec-1] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy#248deced
2020-01-17 00:17:26.216 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-01-17 00:17:26.216 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-01-17 00:17:26.217 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2020-01-17 00:17:26.217 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2020-01-17 00:17:26.218 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#8c4296e2: Principal: org.springframework.security.core.userdetails.User#cce1ec64: Username: web-client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; 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_ADMIN
2020-01-17 00:17:26.222 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#484f35da, returned: 1
2020-01-17 00:17:26.222 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2020-01-17 00:17:26.222 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2020-01-17 00:17:26.222 DEBUG 6432 --- [nio-8086-exec-1] o.s.security.web.FilterChainProxy : /oauth/token reached end of additional filter chain; proceeding with original chain
2020-01-17 00:17:26.228 DEBUG 6432 --- [nio-8086-exec-1] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to org.springframework.security.oauth2.provider.endpoint.TokenEndpoint#postAccessToken(Principal, Map)
loadClientByClientId
loadClientByClientId
loadClientByClientId
2020-01-17 00:17:26.246 DEBUG 6432 --- [nio-8086-exec-1] .o.p.p.ResourceOwnerPasswordTokenGranter : Getting access token for: web-client
authenticate
loadClientByClientId
loadClientByClientId
loadClientByClientId
2020-01-17 00:17:26.299 DEBUG 6432 --- [nio-8086-exec-1] 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#4f98e90
2020-01-17 00:17:26.305 DEBUG 6432 --- [nio-8086-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2020-01-17 00:17:26.305 DEBUG 6432 --- [nio-8086-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
Yup. That's known. Spring Security hits your store a bunch of times during the authentication process.

Spring Boot 2 OAuth2 Resource Server Does not hit authorization server for access token validation

I have implemented Spring boot 2 + OAuth2 Oauthorization server.
I only want to use Client_credential to secure resource Server
I am able to get access token from Auth server, but when I pass this to access rest api, resource server does not validate it from authorization server and gives invalid access token error, I am using postman to get access token and to quest resource server.
Authorization Server
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class AuthorizationApplication {
public static void main(String[] args) {
SpringApplication.run(AuthorizationApplication.class, args);
}
}
Authorization server config
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private static final String SERVER_RESOURCE_ID = "oauth2-server";
private static InMemoryTokenStore tokenStore = new InMemoryTokenStore();
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("clientABC").secret("{noop}secretXYZ")
.authorizedGrantTypes("client_credentials")
.scopes("resource-server-read", "resource-server-write")
.resourceIds(SERVER_RESOURCE_ID);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
Authorization server web config
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
public class AuthorizationServerWebConfig extends WebSecurityConfigurerAdapter {
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll();
}
}
Controller
import java.security.Principal;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class AuthorizationServerController {
#RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
}
Application.yml
server:
port: 8090
logging:
file: /logs/AuthourizationServer.log
level:
org.springframework: DEBUG
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"
security:
basic:
enabled: false
Resource Server
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ResourceApplication {
public static void main(String[] args) {
SpringApplication.run(ResourceApplication.class, args);
}
}
Web security config
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
#EnableResourceServer
#Configuration
public class ResourceApplicationWebSecurityConfig extends ResourceServerConfigurerAdapter {
private static final String[] AUTH_WHITELIST = {
// -- swagger ui
"/v2/api-docs",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**"
// other public endpoints of your API may be appended to this array
};
#Autowired
private WebEndpointProperties webEndpointProperties;
#Override
public void configure(HttpSecurity http) throws Exception{
http.authorizeRequests().antMatchers(webEndpointProperties.getBasePath()+"/health").permitAll().and()
.authorizeRequests().antMatchers("/swagger-ui.html").permitAll().and()
.authorizeRequests().antMatchers(AUTH_WHITELIST).permitAll().and()
.authorizeRequests().antMatchers("/nonsecured").permitAll()
.anyRequest().authenticated();
}
}
Rest Controller
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ResourceServerController {
#RequestMapping(value = "/secured", method = RequestMethod.GET)
public String securedResource() {
return "This is Secured Resource";
}
#RequestMapping(value = "/nonsecured", method = RequestMethod.GET)
public String nonSecuredResource() {
return "This is Non Secured Resource";
}
}
Application.yml
server:
port: 8092
security:
oauth2:
resource:
user-info-uri: http://localhost:8090/user
basic:
enabled: false
logging:
file: /logs/ResourceServer.log
level:
org.springframework: DEBUG
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"
Postman : getting token from Authorization server
Postman : getting token from Authorization server
Querying secured service and getting erro
AuthorizationServer logs
2018-12-30 21:04:40.599 INFO 5144 --- [nio-8090-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2018-12-30 21:04:40.599 INFO 5144 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2018-12-30 21:04:40.599 DEBUG 5144 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet : Detected StandardServletMultipartResolver
2018-12-30 21:04:40.599 DEBUG 5144 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2018-12-30 21:04:40.599 INFO 5144 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/token']
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : matched
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'GET /logout'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/logout'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'PUT /logout'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'DELETE /logout'
2018-12-30 21:04:40.600 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2018-12-30 21:04:40.615 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2018-12-30 21:04:40.615 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'clientABC'
2018-12-30 21:04:40.631 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2018-12-30 21:04:40.742 DEBUG 5144 --- [nio-8090-exec-1] o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'scopedTarget.clientDetailsService'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=2018-12-30T20:04:40.758Z, principal=clientABC, type=AUTHENTICATION_SUCCESS, data={details=org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null}]
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#717e3c37: Principal: org.springframework.security.core.userdetails.User#8e817097: Username: clientABC; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Not granted any authorities
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.s.HttpSessionRequestCache : saved request doesn't match
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken#717e3c37: Principal: org.springframework.security.core.userdetails.User#8e817097: Username: clientABC; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Not granted any authorities'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy#5a1c3cb4
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2018-12-30 21:04:40.758 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#717e3c37: Principal: org.springframework.security.core.userdetails.User#8e817097: Username: clientABC; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Not granted any authorities
2018-12-30 21:04:40.773 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#76d8c502, returned: 1
2018-12-30 21:04:40.773 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2018-12-30 21:04:40.773 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2018-12-30 21:04:40.773 DEBUG 5144 --- [nio-8090-exec-1] o.s.security.web.FilterChainProxy : /oauth/token reached end of additional filter chain; proceeding with original chain
2018-12-30 21:04:40.789 DEBUG 5144 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet : POST "/oauth/token", parameters={masked}
2018-12-30 21:04:40.790 DEBUG 5144 --- [nio-8090-exec-1] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to 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
2018-12-30 21:04:40.842 DEBUG 5144 --- [nio-8090-exec-1] .s.s.o.p.c.ClientCredentialsTokenGranter : Getting access token for: clientABC
2018-12-30 21:04:40.858 DEBUG 5144 --- [nio-8090-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Found 'Content-Type:application/json;charset=UTF-8' in response
2018-12-30 21:04:40.905 DEBUG 5144 --- [nio-8090-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Writing [087b1986-b76e-4ff5-8e84-63ecd62e9583]
2018-12-30 21:04:40.920 DEBUG 5144 --- [nio-8090-exec-1] 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#38dba2a
2018-12-30 21:04:40.921 DEBUG 5144 --- [nio-8090-exec-1] o.s.web.servlet.DispatcherServlet : Completed 200 OK
2018-12-30 21:04:40.921 DEBUG 5144 --- [nio-8090-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2018-12-30 21:04:40.921 DEBUG 5144 --- [nio-8090-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
Resource Server logs
2018-12-30 21:04:54.158 INFO 8512 --- [nio-8092-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2018-12-30 21:04:54.158 INFO 8512 --- [nio-8092-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2018-12-30 21:04:54.158 DEBUG 8512 --- [nio-8092-exec-1] o.s.web.servlet.DispatcherServlet : Detected StandardServletMultipartResolver
2018-12-30 21:04:54.159 DEBUG 8512 --- [nio-8092-exec-1] o.s.web.servlet.DispatcherServlet : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2018-12-30 21:04:54.159 INFO 8512 --- [nio-8092-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.security.web.FilterChainProxy : /secured?access_token=087b1986-b76e-4ff5-8e84-63ecd62e9583 at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.security.web.FilterChainProxy : /secured?access_token=087b1986-b76e-4ff5-8e84-63ecd62e9583 at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.security.web.FilterChainProxy : /secured?access_token=087b1986-b76e-4ff5-8e84-63ecd62e9583 at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.security.web.FilterChainProxy : /secured?access_token=087b1986-b76e-4ff5-8e84-63ecd62e9583 at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/secured'; against '/logout'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /secured' doesn't match 'POST /logout'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /secured' doesn't match 'PUT /logout'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /secured' doesn't match 'DELETE /logout'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.security.web.FilterChainProxy : /secured?access_token=087b1986-b76e-4ff5-8e84-63ecd62e9583 at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
2018-12-30 21:04:54.190 DEBUG 8512 --- [nio-8092-exec-1] o.s.s.o.p.a.BearerTokenExtractor : Token not found in headers. Trying request parameters.
2018-12-30 21:04:54.206 DEBUG 8512 --- [nio-8092-exec-1] p.a.OAuth2AuthenticationProcessingFilter : Authentication request failed: error="invalid_token", error_description="Invalid access token: 087b1986-b76e-4ff5-8e84-63ecd62e9583"
2018-12-30 21:04:54.206 DEBUG 8512 --- [nio-8092-exec-1] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=2018-12-30T20:04:54.206Z, principal=access-token, type=AUTHENTICATION_FAILURE, data={type=org.springframework.security.authentication.BadCredentialsException, message=Invalid access token: 087b1986-b76e-4ff5-8e84-63ecd62e9583}]
2018-12-30 21:04:54.300 DEBUG 8512 --- [nio-8092-exec-1] 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#582fa201
2018-12-30 21:04:54.300 DEBUG 8512 --- [nio-8092-exec-1] s.s.o.p.e.DefaultOAuth2ExceptionRenderer : Written [error="invalid_token", error_description="Invalid access token: 087b1986-b76e-4ff5-8e84-63ecd62e9583"] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#29184e62]
2018-12-30 21:04:54.300 DEBUG 8512 --- [nio-8092-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
complete code is available in gihub
https://github.com/harsh-hardaha/springboot2Oauth2
Please ignore Admin server and swagger configuration code in github
After Some more inspection and debug I found Solution, I have to make below changes in resource server configuration
Application.yml
security:
oauth2:
client:
clientId: clientABC
clientSecret: secretXYZ
resource:
user-info-uri: http://localhost:8090/user
token-info-uri: http://localhost:8090/oauth/check_token
preferTokenInfo: true
filter-order: 3
basic:
enabled: false
included dependency in resource server
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
I faced similar issue and adding the spring-security-oauth2-autoconfigure dependency in resource server solved my problem.
My application.yml :
security:
oauth2:
resource:
userInfoUri: http://localhost:8901/auth/user

Spring Cloud Contract: Can the verifier Test not be run with SpringRunner.class ?

Hello I set up a basic Api Test like below:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
#ActiveProfiles("test")
public abstract class BaseMockMvcSpec {
public static Logger log = LoggerFactory.getLogger(BaseMockMvcSpec.class);
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mvc;
#Autowired
FilterChainProxy springSecurityFilterChain;
#Autowired
UserRepository users;
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
CustomClientDetailsService clientDetialsService;
#Mock SecurityContext mockSecurityContext;
#Before
public void setUp() {
RestAssuredMockMvc.standaloneSetup(new AccountDetailsController());
mvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurity(springSecurityFilterChain))
.build();
BaseClientDetails testClient = new ClientBuilder("testclient")
.secret("testclientsecret")
.authorizedGrantTypes("password")
.scopes("read", "wirte")
.autoApprove(true)
.build();
clientDetialsService.addClient(testClient);
User user = createDefaultUser("testuser", passwordEncoder.encode("testpassword"), "max", "Mustermann", new Email("test#lokata.de"));
users.deleteAll();
users.save(user);
log.info("setup BaseMockMvcSpec");
}
public String oauth(){
String token = "notValidToken";
try {
token = validAccessToken();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "Bearer " + token;
}
private String validAccessToken() throws Exception {
String username = "testuser";
String password = "testpassword";
MockHttpServletResponse response = mvc
.perform(post("/oauth/token")
.header("Authorization", "Basic "
+ new String(Base64Utils.encode(("testclient:testclientsecret")
.getBytes())))
.param("username", username)
.param("password", password)
.param("grant_type", "password"))
.andDo(print())
.andReturn().getResponse();
return new ObjectMapper()
.readValue(response.getContentAsByteArray(), OAuthToken.class)
.accessToken;
}
#JsonIgnoreProperties(ignoreUnknown = true)
private static class OAuthToken {
#JsonProperty("access_token")
public String accessToken;
}
}
I get the following output of the Test run:
2017-06-27 01:36:23.379 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Neither #ContextConfiguration nor #ContextHierarchy found for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest], using SpringBootContextLoader
2017-06-27 01:36:23.379 INFO 47446 --- [ Test worker] o.s.t.c.support.AbstractContextLoader : Could not detect default resource locations for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest]: no resource found for suffixes {-context.xml, Context.groovy}.
2017-06-27 01:36:23.379 INFO 47446 --- [ Test worker] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [de.example.microservice.authservice.verifier.tests.OauthserviceTest]: OauthserviceTest does not declare any static, non-private, non-final, nested classes annotated with #Configuration.
2017-06-27 01:36:23.383 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Found #SpringBootConfiguration de.example.microservice.authservice.AuthserverApplication for test class de.example.microservice.authservice.verifier.tests.OauthserviceTest
2017-06-27 01:36:23.385 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener]
2017-06-27 01:36:23.386 INFO 47446 --- [ Test worker] .b.t.c.SpringBootTestContextBootstrapper : Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener#2efec58d, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener#65dbe1b, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener#4d31ce57, org.springframework.test.context.support.DirtiesContextTestExecutionListener#750239e7, org.springframework.test.context.transaction.TransactionalTestExecutionListener#2d885867, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener#464e86ab, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener#54eab43, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener#6167770c, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener#ec35027, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener#3c0ae48a, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener#4cee44fb, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener#166b957d, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener#2bdadff]
2017-06-27 01:36:23.459 INFO 47446 --- [ Test worker] o.s.b.t.m.w.SpringBootMockServletContext : Initializing Spring FrameworkServlet ''
2017-06-27 01:36:23.459 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started
2017-06-27 01:36:23.462 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 3 ms
2017-06-27 01:36:23.540 INFO 47446 --- [ Test worker] d.l.m.authservice.BaseMockMvcSpec : setup BaseMockMvcSpec
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/oauth/token']
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : matched
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-06-27 01:36:23.564 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] 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#79e774c0
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'GET /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/logout'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'PUT /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'POST /oauth/token' doesn't match 'DELETE /logout
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 5 of 12 in additional filter chain; firing Filter: 'ClientCredentialsTokenEndpointFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'testclient'
2017-06-27 01:36:23.565 DEBUG 47446 --- [ Test worker] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.www.BasicAuthenticationFilter : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#7e2b6867: Principal: org.springframework.security.core.userdetails.User#81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.AnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken#7e2b6867: Principal: org.springframework.security.core.userdetails.User#81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy#b7217c5
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/oauth/token'; against '/oauth/token'
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2017-06-27 01:36:23.567 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#7e2b6867: Principal: org.springframework.security.core.userdetails.User#81d402dd: Username: testclient; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Not granted any authorities
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter#6b9626fc, returned: 1
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2017-06-27 01:36:23.568 DEBUG 47446 --- [ Test worker] o.s.security.web.FilterChainProxy : /oauth/token reached end of additional filter chain; proceeding with original chain
2017-06-27 01:36:23.569 DEBUG 47446 --- [ Test worker] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/token
2017-06-27 01:36:23.569 DEBUG 47446 --- [ Test worker] .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-06-27 01:36:23.572 DEBUG 47446 --- [ Test worker] .o.p.p.ResourceOwnerPasswordTokenGranter : Getting access token for: testclient
2017-06-27 01:36:23.572 DEBUG 47446 --- [ Test worker] o.s.s.authentication.ProviderManager : Authentication attempt using de.example.microservice.authservice.authentication.behavior.CustomAuthenticationProvider
2017-06-27 01:36:23.656 DEBUG 47446 --- [ Test worker] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2017-06-27 01:36:23.656 DEBUG 47446 --- [ Test worker] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
MockHttpServletRequest:
HTTP Method = POST
Request URI = /oauth/token
Parameters = {username=[testuser], password=[testpassword], grant_type=[password]}
Headers = {Authorization=[Basic dGVzdGNsaWVudDp0ZXN0Y2xpZW50c2VjcmV0]}
Handler:
Type = org.springframework.security.oauth2.provider.endpoint.TokenEndpoint
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
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY], Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOiJmZjgwODA4MTVjZTZjMzBkMDE1Y2U2YzM2MmYzMDAyNyIsInVzZXJfbmFtZSI6InRlc3R1c2VyIiwic2NvcGUiOlsicmVhZCIsIndpcnRlIl0sIm9yZ2FuaXNhdGlvbiI6ImRlZmF1bHQiLCJleHAiOjE0OTg1NjMzODMsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiJlZGRmZWUyZS01NTU2LTQ1YWItOTIwMC02NThiM2FkNmRiNWYiLCJjbGllbnRfaWQiOiJ0ZXN0Y2xpZW50In0.bL9mLo1Ao6oUBA3BxrIIEWTEXVlTml5GqeoeAKqA_pXDFBn-gIRafRH8ji3BceTg-cjih_-cYYAbRiVmjsCAUd0nE-chwIwhwPp2WSAfgz9OHd531VsDOX7l8-vkR_BUKY5X02pIf2W9ZlsqCZ-isarRzWI_AQpNgqwoIDcICDeuB1lNWqkwtwmI_f0cF3u0J2FuQBvye3Sj4xXmrQU0awCj0F891v6bPqkM0Wc5G6i8Mm-n-OnRbMqcckfxAsSqtDEYrDe3T6otFfREZ6AYTefMzQWYbYXDK0tCkohH46hNmKlbrXNWUrnwYLDeCZyOGm8bCrOihDzjYJgw5RshKQ","token_type":"bearer","expires_in":43199,"scope":"read wirte","accountId":"ff8080815ce6c30d015ce6c362f30027","organisation":"default","jti":"eddfee2e-5556-45ab-9200-658b3ad6db5f"}
Forwarded URL = null
Redirected URL = null
Cookies = []
2017-06-27 01:36:23.684 INFO 47446 --- [ Test worker] ilder$StaticRequestMappingHandlerMapping : Mapped "{[/api/me],methods=[GET],produces=[application/json;charset=UTF-8]}" onto public java.security.Principal de.example.microservice.authservice.rest.behavior.AccountDetailsController.user(java.security.Principal)
2017-06-27 01:36:23.692 INFO 47446 --- [ Test worker] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for #ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext#734a6c74
2017-06-27 01:36:23.696 INFO 47446 --- [ Test worker] o.s.mock.web.MockServletContext : Initializing Spring FrameworkServlet ''
2017-06-27 01:36:23.696 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization started
2017-06-27 01:36:23.696 INFO 47446 --- [ Test worker] o.s.t.web.servlet.TestDispatcherServlet : FrameworkServlet '': initialization completed in 0 ms
The TestException is
java.lang.IllegalArgumentException: json string can not be null or empty
at com.jayway.jsonpath.internal.Utils.notEmpty(Utils.java:386)
at com.jayway.jsonpath.internal.JsonContext.parse(JsonContext.java:81)
at com.jayway.jsonpath.JsonPath.parse(JsonPath.java:596)
at de.example.microservice.authservice.verifier.tests.OauthserviceTest.validate_shouldReturnAccountDetails(OauthserviceTest.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method
I guess the autogenerated Test is not executed but didn't know how to debug them. The get Oauth2 token works perfect and also the execution of the oath() method in the verifier Class.
I ended up with the following test setup:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
#ContextConfiguration
#WebAppConfiguration
#ActiveProfiles("test")
public abstract class UserDetailsControllerTestBase {
public static Logger log = LoggerFactory.getLogger(UserDetailsControllerTestBase.class);
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mvc;
#Autowired
FilterChainProxy springSecurityFilterChain;
#Mock SecurityContext mockSecurityContext;
#Before
public void setUp() {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
//RestAssured.baseURI="http://localhost";
//RestAssured.port = port;
mvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.defaultRequest(get("/api/me").with(user("user").roles("USER")))
.apply(springSecurity(springSecurityFilterChain))
.build();
RestAssuredMockMvc.mockMvc(mvc);
}
public String oauth(){
String token = "notValidToken";
try {
token = validAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
return "Bearer " + token;
}
public void assertIsNull(Object value){
assertThat(value, is(nullValue()));
}
private String validAccessToken() throws Exception {
String username = "user";
String password = "password";
MockHttpServletResponse response = mvc
.perform(post("/oauth/token")
.header("Authorization", "Basic "
+ new String(Base64Utils.encode(("client:clientsecret")
.getBytes())))
.param("username", username)
.param("password", password)
.param("grant_type", "password"))
.andDo(print())
.andReturn().getResponse();
return new ObjectMapper()
.readValue(response.getContentAsByteArray(), OAuthToken.class)
.accessToken;
}
#JsonIgnoreProperties(ignoreUnknown = true)
private static class OAuthToken {
#JsonProperty("access_token")
public String accessToken;
}
}
Check out the example Solution Repository for more details
Yes. Just run the plugin in EXPLICIT mode. That way you can configure restassured to shoot any URL and you'll be able to setup your base class however you want to. Example https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#features-context-paths

Resources