I have a Restful APIs developed using Springboot. Also, I have implementioned external ldap authentication. http://localhost:8080/login?username=test&password=test goes through the ldap authentication and it is working fine as expected.
My Spring security implementation is below. I am restricting all the API calls and needs to be authenticated.
@Configuration
@EnableWebSecurity
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
...
...
}
My login request works and all the API calls are not getting authenticated, even after the successful login. I can see the logs show that ldap authentication is success and creates the SecurityContext. And my next API call does not have this SecurityContext created in the previous login request. My logs are below.
2019-10-11 02:22:31.567 DEBUG 39216 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login?username=test&password=test at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2019-10-11 02:22:31.567 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/login' 2019-10-11 02:22:31.567 DEBUG 39216 --- [nio-8080-exec-1] w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication 2019-10-11 02:22:31.570 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.authentication.ProviderManager : Authentication attempt using portal.services.security.CustomActiveDirectoryLdapAuthenticationProvider 2019-10-11 02:22:32.767 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.ldap.SpringSecurityLdapTemplate : Searching for entry under DN '', base = 'dc=abc,dc=com', filter = '(&(objectClass=Person) ((sAMAccountName=12323)))' 2019-10-11 02:22:32.777 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.ldap.SpringSecurityLdapTemplate : Found DN: CN=Test Name,OU=Users,DC=com 2019-10-11 02:22:32.779 INFO 39216 --- [nio-8080-exec-1] o.s.s.ldap.SpringSecurityLdapTemplate : Ignoring PartialResultException 2019-10-11 02:22:32.896 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.l.u.LdapUserDetailsMapper : Mapping user details from context with DN: CN=test name,OU=Users,DC=com 2019-10-11 02:22:32.899 DEBUG 39216 --- [nio-8080-exec-1] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@45a4b042 2019-10-11 02:22:32.899 DEBUG 39216 --- [nio-8080-exec-1] w.a.UsernamePasswordAuthenticationFilter : Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ff0ce9d1: Principal: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl@7a480d2: Dn: CN=Test name,OU=Users,DC=com; Username: test; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: Users; Granted Authorities: ADMIN 2019-10-11 02:22:33.117 DEBUG 39216 --- [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@17741df1 2019-10-11 02:22:33.117 DEBUG 39216 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed 2019-10-11 02:22:33.650 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 2019-10-11 02:22:33.650 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2019-10-11 02:22:33.654 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter' 2019-10-11 02:22:33.654 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter' 2019-10-11 02:22:33.654 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET] 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'GET /logout 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST] 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'POST /logout 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT] 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'PUT /logout 2019-10-11 02:22:33.656 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE] 2019-10-11 02:22:33.656 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'DELETE /logout 2019-10-11 02:22:33.656 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : No matches found 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'POST /login 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 2019-10-11 02:22:33.659 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 2019-10-11 02:22:33.660 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@25109219: 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' 2019-10-11 02:22:33.661 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter' 2019-10-11 02:22:33.662 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 2019-10-11 02:22:33.671 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy
: /admin/getCutOffDays at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 2019-10-11 02:22:33.673 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/admin/getCutOffDays'; against '/login' 2019-10-11 02:22:33.674 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /admin/getCutOffDays; Attributes: [authenticated] 2019-10-11 02:22:33.674 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@25109219: 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 2019-10-11 02:22:33.688 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@74f28afc, returned: -1 2019-10-11 02:22:33.696 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry pointorg.springframework.security.access.AccessDeniedException: Access is denied at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.0.8.RELEASE.jar!/:5.0.8.RELEASE]
I am expecting my request to /admin/getCutOffDays should retrieve the data as it is authenticated in the previous login request.
Below is my Controller.
@RequestMapping("/admin")
@RestController
public class AdminController {
@PreAuthorize("hasAuthority('ADMIN')")
@GetMapping("/getCutOffDays")
public long getCutOffDays() {
return adminService.getSequenceId(CUT_OFF_DAYS);
}
}
Can anyone help me figure out what am I missing here.