Announcement Announcement Module
Collapse
No announcement yet.
Proxy Tickets for services not working for me. Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Proxy Tickets for services not working for me.

    Here's my situation.

    I have a CAS web application and a ACEGI web application that also exposes web services to be protected by ACEGI. There is another application that uses CAS on a different machine that will make a web service call to my ACEGI web application. The CAS authentication is working fine, however the web service call does not.

    When a logged in user on the other machine makes a web service call, I get the following message in my logs:

    Authentication not added to ContextHolder (could not extract an authentication object from the container which is an instance of Authentication)

    and this error eventually occurs:

    DEBUG [2004-09-01 11:31:45,008] (SecurityEnforcementFilter.java:191) - Authentication failed - adding target URL to Session: https://hostname.domain.edu:8443/s3d...CuTZa9rVObSKjT
    net.sf.acegisecurity.AuthenticationCredentialsNotF oundException: A valid SecureContext was not provided in the RequestContext

    My guess is that the CASProcessingFilter is not getting run because the request does not end in /j_acegi_cas_security_check. Is that correct?

    How am I supossed to validate a proxy ticket for a web service using the ACEGI framework? Any suggestions would be greatly appreciated!

    Thanks,
    Matt

  • #2
    Workaround

    Okay, I was able to work around the problem. Here's how I did it...

    I modified the class net.sf.acegisecurity.ui.AbstractProcessingFilter the following ways:

    I changed (line 287) from

    Code:
    if (httpRequest.getRequestURL().toString().endsWith(httpRequest
                    .getContextPath() + filterProcessesUrl)){
    to

    Code:
    if (httpRequest.getRequestURL().toString().endsWith(httpRequest
                    .getContextPath() + filterProcessesUrl)
                    || httpRequest.getParameter("ticket") != null) {
    This allows the filter to run for every request containing a ticket.

    I also changed (line 363) from

    Code:
    httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
        
    return;
    to

    Code:
    if (httpRequest.getRequestURL().toString().endsWith(httpRequest
                        .getContextPath() + filterProcessesUrl)) {
                    httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
        
                    return;
                }
    This way the user is only redirected for the URL that is coming from the CAS service.

    Comment


    • #3
      How are you passing your CAS ticket to the web service?

      I have used CAS to authenticate a web service at work. I didn't use proxy tickets however so I'm not sure if my experience will be the same as yours.

      For service tickets, I passed the ACEGI stateless constant as the username and the CAS ticket as the password for a HTTP BASIC Authorization. ACEGI received the request, proccessed it and then allowed access without having to modify any source code for ACEGI.

      When exposing the web service, your ticket validation should not be dependent on your URL ending in /j_acegi_cas_security_check (or whatever you define). In fact for my web service, that url never gets called. It is only used to validate the service url of a service ticket.

      Comment


      • #4
        Hi,

        I,m using the CAS for remote application too. How can I get the CAS ticket and then use it in the remote application instead of using the username and password to login everytime?

        Moreover, what is the " ACEGI stateless constant" which used as username as descripted?

        Thanks

        Comment


        • #5
          When calling web services and wanting to rely on CAS you need to present in the BASIC authentication header the String defined against CasProcessingFilter.CAS_STATEFUL_IDENTIFIER as the username, and the service ticket as the password. From memory this is discussed in the "Advanced CAS Usage" section of the reference guide. When doing this you'll need to ensure a BasicProcessingFilterEntryPoint bean is defined for the SecurityEnforcementFilter.authenticationEntryPoint . Then you just define a CasAuthenticationProvider in your ProviderManager bean, so when the BASIC authentication header gets detected it will delegate through to CAS.

          Hope this makes sense. As Scott said, it works and you shouldn't need to touch Acegi Security source code.

          Comment


          • #6
            In fact, I have read the "Advanced CAS Usage" section of the reference guide" but it don't have mention how to set to let remote application (stateless) to use the CAS.

            I have tried to use the contacts client application and modify the applicationContext.xml of the contacts-cas like this:

            <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.Security EnforcementFilter">
            <property name="filterSecurityInterceptor"><ref bean="filterInvocationInterceptor"/></property>
            <property name="authenticationEntryPoint"><ref bean="basicProcessingFilterEntryPoint"/></property>
            </bean>

            I have also changed the client.properties with context "contacts-cas" but it still throw RemoteAccessException when run the contacts client application.

            Any idea?

            Thanks on advance

            Comment


            • #7
              Without looking into it in detail, your main problem is the Contact sample application's console application has no knowledge of what username and password to use when setting the BASIC authentication header of each web services request. It doesn't know how to do this because you first have to obtain the service ticket opaque value from the CAS server.

              Comment


              • #8
                For our application, we have created the idea of a CredentialSource for clients. A specific implementation of the credentials source is for Acegi/CAS. As part of the set up you give it a CAS username/password and when you call getCredentials() it returns to you the Acegi stateless constant CasProcessingFilter.CAS_STATELESS_IDENTIFIER and a service ticket that was retrieved from CAS. We have specific implementations to retrieve tickets from CAS via web service, html screen scraping, etc. We take these credentials and pass then via Basic HTTP authorization as the username and password.

                I can see if I can find our securityContext.xml if you want to see it.

                Comment

                Working...
                X