I am working with a project involving CAS server works with other Spring-based projects using Single-Sign On (SSO), but I am receiving a redirect loop involving the Grails spring-security-cas plugin (version: ":spring-security-cas:2.0-RC1"). I've looked at the plugin's documentation. I know CAS redirect questions appear common, but I have yet to find a posting related to this type of situation. I am new-ish to the Grails and CAS worlds, so thank you in advance for any push in the right direction.
Accessing a secured page on the grails app initially redirects to the CAS server login page correctly, with the appropriate service parameter: https:// example.com:8443/cas/login?service=http:// example.com:8080/grailsapp/j_spring_cas_security_check
The problem occurs after the user logs in successfully and CAS redirects back to the service. The j_spring_cas_security_check in the grails app is redirecting back to the https://example.com:8443/cas login page, which sees the TGC and redirects back to the service j_spring_cas_security_check page, which redirects ad infinitum [until the browser gives the redirect loop error]. It also looks like new service tickets are getting created each iteration.
My Config.groovy has:
grails.plugin.springsecurity.cas.loginUri = /login
grails.plugin.springsecurity.cas.serviceUrl = http://example.com:8080/grailsapp/j_spring_cas_security_check
grails.plugin.springsecurity.cas.serverUrlPrefix = https://example.com:8443/cas
# we aren't using cas with proxy
# logout details not shown here
Unsuccessful attempts already tried based on other questions/answers:
The cas server's logs include:
=============================================================
WHO: [username: sampleuser]
WHAT: supplied credentials: [username: sampleuser]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Fri Jan 03 23:52:41 GMT 2014
CLIENT IP ADDRESS: XXX.XXX.XXX.XXX
SERVER IP ADDRESS: example.com
=============================================================
=============================================================
WHO: [username: sampleuser]
WHAT: TGT-24-Rttmt5i5raWcV1Z5wZavVopigQc4xeIckEUfMKdG3EwEzI3LUI-cas.service
ACTION: TICKET_GRANTING_TICKET_CREATED
APPLICATION: CAS
WHEN: Fri Jan 03 23:52:41 GMT 2014
CLIENT IP ADDRESS: XXX.XXX.XXX.XXX
SERVER IP ADDRESS: example.com
=============================================================
INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-77-cneJOIwmnoOdKqkscaiy-cas.service] for service [http://example.com:8080/grailsapp/j_spring_cas_security_check] for user [sampleuser]>
####### FIRST ITERATION OF LOOP BELOW #############
=============================================================
WHO: sampleuser
WHAT: ST-77-cneJOIwmnoOdKqkscaiy-cas.service for http://example.com:8080/grailsapp/j_spring_cas_security_check
ACTION: SERVICE_TICKET_CREATED
APPLICATION: CAS
WHEN: Fri Jan 03 23:52:41 GMT 2014
CLIENT IP ADDRESS: XXX.XXX.XXX.XXX
SERVER IP ADDRESS: example.com
=============================================================
=============================================================
WHO: audit:unknown
WHAT: ST-77-cneJOIwmnoOdKqkscaiy-cas.service
ACTION: SERVICE_TICKET_VALIDATED
APPLICATION: CAS
WHEN: Fri Jan 03 23:52:41 GMT 2014
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: example.com
=============================================================
DEBUG [org.jasig.cas.web.flow.InitialFlowSetupAction] - <Placing service in FlowScope: http://example.com:8080/grailsapp/j_spring_cas_security_check>
INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-78-6qsbaVNNOess4VhGOQE4-cas.service] for service [http://example.com:8080/grailsapp/j_spring_cas_security_check] for user [sampleuser]>
####### SERVICE_TICKET_CREATED and SERVICE_TICKET_VALIDATED LOOP CONTINUES A FEW MORE TIMES BEFORE BROWSER GIVES UP #############
In addition to overwriting UserDetailsService
I had to configure filterProcessesUrl
in Config.groovy
grails.plugin.springsecurity.cas.filterProcessesUrl = "/user/login" // same as uri part of serviceUrl
grails.plugin.springsecurity.cas.serviceUrl = "http://yoursite.com/user/login"
for CasAuthenticationFilter to kick in after authentication on CAS. Following are source code reference links:
You can also look at the source for CasAuthenticationFilter.java
see the serviceTicketRequest
and super.requiresAuthentication
methods.
The issue was that in the Grails client I did not create a userDetailsService. I implemented a custom class within Grails' services folder (See http://grails-plugins.github.io/grails-spring-security-core/guide/userDetailsService.html):
public class MyUserDetailsService implements UserDetailsService {
// Required methods here
}
then referenced this in resources.groovy:
beans = {
userDetailsService(MyUserDetailsService)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With