we have a Grails 3.3.2 app that is using Spring Security Core and Spring Security CAS plugins. With a custom userDetailsService class for getting the user information from a Oracle Database. This app logs in through CAS just fine when hitting the internal URL of the tomcat server where an instance of the app is deployed, but we are getting a redirect loop and errors when trying to access the app through a load balancer.
This is the setup. We have two instances; one is configured to be accessed directly on the app server, the other through a load balancer which acts as a reverse proxy. Accessing the one directly on the server works fine (Redirects to CAS, you log in, CAS redirects back, and you're in). The one through the load balancer redirects to CAS, you log in, CAS redirects you back, the credential is passed correctly, but then something in Groovy anonymizes it and you get an Access Denied, and circle back to CAS. But the CAS ticket is valid, so CAS sends you back, and the cycle repeats. It repeats 5 or 6 times before the browser determines there's an error and stops it.
With the logging set to Debug we can kinda of see where this is going wrong, but cannot figure out why.
2020-07-16 12:07:46.179 DEBUG --- [io-8443-exec-21] o.s.security.web.FilterChainProxy : / at position 9 of 11 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2020-07-16 12:07:46.179 DEBUG --- [io-8443-exec-21] w.f.GrailsRememberMeAuthenticationFilter : SecurityContextHolder not populated with remember-me token, as it already contained: 'grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@dc4d198: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@7798: RemoteIpAddress: XXX.XXX.XX.XXX; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
When it works on the instance of our app only on the internal server our custom userDetailsService is used as the principal instead of grails.anonymous.user.
2020-07-16 12:07:46.947 DEBUG --- [nio-8443-exec-6] o.s.security.web.FilterChainProxy : / at position 9 of 11 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2020-07-16 12:07:46.947 DEBUG --- [nio-8443-exec-6] w.f.GrailsRememberMeAuthenticationFilter : SecurityContextHolder not populated with remember-me token, as it already contained: 'org.springframework.security.cas.authentication.CasAuthenticationToken@a53948f3: Principal: edu.utica.grails.security.UticaUserDetails@6e9a437b: Username: XXXXXX; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_FINAID,ROLE_STUDENT,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: XXX.XX.XXXX.XX; SessionId: CFC5F608B6E1A847F43BD18FC91480F2; Granted Authorities: ROLE_ADMIN, ROLE_FINAID, ROLE_STUDENT, ROLE_USER Assertion: org.jasig.cas.client.validation.AssertionImpl@7c7827d0 Credentials (Service/Proxy Ticket): ST-eff75341bc2e4124b1563d16823ce021-XXX.XXXX.XXX'
Can anyone tell me why in one instance SecurityContextHolder is getting the principal from our userDetailsService and CAS works fine, and in the other instance behind the load balancer the SecurityContextHolder is getting 'grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@dc4d198: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: grails.anonymous.user;
Thank you, Mike