Skip to end of metadata
Go to start of metadata
Table of Contents

Replaced by Soulwing CAS Client

Icon

I have developed a replacement solution for Confluence and JIRA. You're welcome to continue to using
this crufty little number if you like, but I no longer support it. Visit http://www.soulwing.org for a better solution.
– Carl Harris, 12 April 2007

Version Compatibility

Icon

This client supports Confluence 2.1 and 2.2. For earlier versions of Confluence you'll probably want to refer to Seraph as CAS Client.

Disclaimer

Confluence is the name of a product by Atlassian. This client package is not a product of Atlassian. It was developed by Carl Harris at Virginia Tech. Please contact Carl (or simply add a comment to this page) for support, if needed.

Acknowledgements

The author of this client package wishes to acknowledge those responsible for the Yale Java CAS client and the Seraph Authenticator for CAS from which this work was derived.

Overview

Confluence 2.1 wiki software from Atlassian can be easily integrated with CAS. The client package described here provides a complete Confluence CAS solution including optional support for the following in addition to the basic CAS login authentication:

  • CAS bypass for any selected Confluence paths; e.g. the SOAP/XML-RPC interface path /rpc can bypass CAS.
  • Ability to support non-CAS login via the /login.action path.
  • Global CAS logout via the /logout.action path.

Using this client package is a simple matter of installing a couple of jar files into your Confluence installation, and modifying a couple of configuration files.

Background

CAS authentication in Confluence requires two components:

  1. A servlet filter that examines every request made to Confluence to check for an existing CAS receipt in the session attributes. If no valid receipt exists, this filter performs the CAS authentication by redirecting the user's browser to the CAS server in the usual manner. This filter also sets the CAS_FILTER_USER session attribute containing the authenticated user's login name. This filter is placed in the chain just before the normal Confluence login filter.
  2. A subclass of com.atlassian.confluence.user.ConfluenceAuthenticator. This subclass overrides the getUser, login, and logout methods of ConfluenceAuthenticator. For getUser and login it checks for the existence of the CAS_FILTER_USER session attribute. If this attribute doesn't exist our class delegates authentication to the superclass (ConfluenceAuthenticator). If CAS_FILTER_USER does exist, the authenticator subclass sets the Confluence LOGGED_IN_KEY and LOGGED_OUT_KEY attributes in the manner prescribed for ConfluenceAuthenticator. When the normal Confluence login filter sees these attributes, it assumes that the user has already been authenticated. In the logout method, the authenticator subclass updates the LOGGED_IN_KEY and LOGGED_OUT_KEY attributes in an appropriate manner to end the user's Confluence session.

The CASFilter provided by the Yale Java Client provides the basis for our servlet filter. It checks for the CAS receipt in the session attributes, redirects the user to the CAS server for authentication. It sets the CAS_FILTER_USER attribute to the authenticated user's login name. However, by extending the basic CASFilter, we can improve the integration of CAS with Confluence as discussed below.

The CasSeraphAuthenticator Java class described in Seraph as CAS Client extends the Seraph DefaultAuthenticator class used by Confluence versions prior to 2.1. In Confluence 2.1, Atlassian integrated the new Atlassian-user functionality. Because of this change, integrating CAS with Confluence 2.1 requires a class that extends com.atlassian.confluence.user.ConfluenceAuthenticator. The ConfluenceCasAuthenticator provided in this package was derived from the CasSeraphAuthenticator class but it extends ConfluenceAuthenticator instead of DefaultAuthenticator.

In Confluence, there are some paths that you really don't want to use with CAS. The SOAP/XML-RPC interface, for example is located at path /rpc. SOAP and XML-RPC client programs can't CAS-authenticate, so applying CAS to this path makes the API inaccessible. The Java servlet specification doesn't provide a means to apply a filter to all URLs except those matching a pattern. This makes it difficult to apply a filter like CASFilter to only some of the paths in Confluence. It seems unwise and manageable to try to identify all of the paths that should use CAS and apply the CASFilter only to those paths.

Providing an easy-to-configure CAS bypass capability was accomplished by subclassing CASFilter. The ConfluenceCasFilter provided in this package uses filter initialization parameters to identify paths (e.g. /rpc) that should bypass CAS. When a request is made for a URL that matches one of the defined bypass prefixes, ConfluenceCasFilter sets the CAS_FILTER_BYPASS attribute in the session context and bypasses the CASFilter. For all other requests, ConfluenceCasFilter delegates the real authentication work to CASFilter.

No-CAS Paths

These paths should be configured to bypass CAS:

  • /rpc — SOAP/XML RPC interface
  • /images — icons and other image content, linked-to in Confluence HTML e-mail
  • /createrssfeed.action — RSS feeds (few readers can deal with CAS redirects)

CAS is also bypassed for the /login.action path in Confluence. This allows users without accounts in your CAS service to login to Confluence via the Atlassian-user model, using locally configured usernames or LDAP. The CAS_BYPASS_FLAG ensures that ConfluenceCasFilter will continue to bypass CAS for a user who has authenticated via /login.action for the duration of the user's session.

To implement global logout, ConfluenceCasFilter looks for a requested path that matches the configured logout path (typically this is /logout.action). When this path is matched, if the CAS_FILTER_BYPASS session attribute is not set, the filter redirects the browser to the configured CAS global logout URL with the user's ticket appended as a parameter. The filter also removes all CAS-related session attributes when the logout path is requested.

Installing the Confluence CAS Package

Installation requires you to install a couple of jar files, edit the seraph-config.xml configuration file, and edit the web.xml deployment descriptor.

Icon

Making changes to the deployed Confluence application may cause the application server to try to reinitialize Confluence. This is definitely the case for the "standalone" Confluence running under Tomcat. It's best to shut down Confluence while making these changes.

Installing the Jar Files

  1. Download the Yale Java CAS Client from the JA-SIG CAS Downloads page. Copy casclient.jar from the dist directory of the client distribution into the confluence/WEB-INF/lib directory of your Confluence installation.
  2. Download the CAS:Confluence CAS Client package from the attachments section of this page. Copy confluence-cas.jar from the dist directory of the client distribution into the confluence/WEB-INF/lib directory of your Confluence installation.

Configuring Seraph

To replace the default ConfluenceAuthenticator with our ConfluenceCasAuthenticator, we need to
edit the confluence/WEB-INF/classes/seraph-config.xml file in your Confluence installation. It's a very good idea to make a copy of this file before you begin to edit it. Find the existing <authenticator> element and wrap it in XML comment markers. Then add a new <authenticator> element that identifies our ConfluenceCasAuthenticator. It should look like this when you're done.

Configuring web.xml

We need to edit the confluence/WEB-INF/web.xml file in your Confluence installation. It's a very good idea to make a copy of this file before you begin to edit it. Add the following configuration elements with the other <filter> elements in the file. Note that this configuration is similar but not identical to what is used with Yale's CASFilter. The name of the filter class used here is different, and there are a couple of extra initialization parameters. You'll need to replace the values specified for the CASFilter parameters with settings that are appropriate for your CAS service.

Find the <filter-mapping> element containing <filter-name>login</filter-name>. This element sends all URL paths through the Atlassian-user filter for normal Confluence authentication. We want CAS authentication to occur just before the normal authentication filter gains control, so add the following element just above the existing filter mapping for the login filter:

About Certificates

Many CAS installations are using certificates signed by their own CAs or even self-signed certificates. You need to make sure that the Java Runtime Environment used by your Confluence installation is properly configured to trust the certificates used by your CAS server. Typically this involves adding trusted CA certificates or a trusted certificate (for self-signers) into the JRE's trust keystore.

If you see javax.net.ssl exceptions in your application server's log file after configuring Confluence CAS authentication, it's a sure sign that you've got certificate trust problems.

Confluence CAS-ified

With the jar files in place and the configuration files edited, you're ready to restart Confluence and see the magic of CAS:

  • No labels

21 Comments

  1. Hi Carl,

    Is your authenticator usable with JIRA as well? I know JIRA has some substantial differences in architecture under the hood from Confluence. Do they share similar auth frameworks? Do you know of any other work being done in this regard?

    Thanks, Graham.

    1. Funny you should ask this now... Just last week, we started evaluating JIRA for use in our organization, and I started cutting a new version that will work with the current version of JIRA. Should be available within the next week.

      1. Hi carl,

         Did you guys ended up using CAS for SSO integrating JIRA and Confluence? Or have plans of doing so?  This is something I am very interested in.

        Thanks!

        -Hellmut

        1. I have developed a JIRA module, I just haven't released it for two reasons:

          1. There are some peculiarities/differences in the way JIRA handles login/logout. The CAS module works, but login/logout isn't exactly as I'd like it to be.
          2. The module duplicates a good bit of code from the Confluence CAS filter. I need to refactor the code into a single module so that I don't have to maintain the same code in two places.

          If you'd like a preview, I'll be happy to give you what I have, but I'd prefer not to post it here.

          1. Carl,

            Thanks for the Confluence CAS client.

            Can you please pass me a copy of your JIRA CAS client as well?

             
            Thanks,

             Hongbo

            1. Carl, Hongbo:

              Any newsregarding the JIRA CAS Client? The new implementation (a.k.a. soulwing) is being problematic for me.

              Thank you so much!

              unai 

  2. Posted version 1.2.2 to fix a problem with bypassed paths and global CAS logout.

  3. Tested version 1.2.2. successfully with Confluence 2.2.1, 2.2.1a, and 2.2.2... works as expected.

  4. Hi Carl,

    I'm now facing an unexpected gaining access to my Confluence pages after passing CAS authentication by another user who does NOT have his/her Confluence account.

    The exact sequences to reproduce are like this:

    1. Access my Confluence pages by using CAS authentication.
    2. Logout Confluence by using "logout" link on the top-right screen.
    (This indicates that I logout CAS and also Confluence, I hope)
    3. Access Confluence by using CAS with another user's ID. Due to the failure of gaining Confluence access (no Confluence ID for the user!), Confluence's normal login page is displayed.

    At this moment, Confluence thinks that I am accessing to Confluence....

    This might be the result of failure for deleting JSESSIONID cookie in step 2 above. Do you have any thoughts to address this problem?

    I hope the following could be hints:

    a. the Confluence path is https://HOGE/wiki/, not just https://HOGE/
    b. my JSESSIONID is remaining even if I loged out
    c. Web load-balancer is decoding HTTPS so that Confluence is accessed by HTTP internally.

    Best regards,
    Shoji

    1. I'll have to try to reproduce this.

  5. Carl,

     I'm following your instructions for setting up Confluence 2.2.4 with CAS. When I start up Tomcat I get the following exception:

    When I tried to compile the confluence-cas-1.2.2 project to resolve this issue (please tell me if this is not the path to tread), its seems that jdk1.5 is needed. Currently, we are using 1.4.XX and this is what our Tomcat server runs on as well. Is the confluence-cas-1.2.2 project based on 1.5? Is using 1.4 the heart of my original problem.

    BTW, we've been using CAS with Confluence 1.4 up to now and I really like the improvements you've made in integrating CAS with Confluence. Thanks for your effort.

    Thanks,

  6. Good day.

    Have a new problem with global logout

    using now casclient1.2.2 and Confluence 2.2.5 and own CAS server

    using filter is :

    <filter>
        <filter-name>ConfluenceCasFilter</filter-name>
        <filter-class>org.soulwing.confluence.cas.ConfluenceCasFilter</filter-class>
        <!--
          These are the usual CASFilter parameters
        -->
        <init-param>
            <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>
            <param-value>https://cas.compassplus.ru:9444/login.jsp</param-value>
        </init-param>
        <init-param>
            <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
            <param-value>https://cas.compassplus.ru:9444/validate.jsp</param-value>
        </init-param>
        <!-- Change this to the server that the CAS client is running on
             NOTE: This is REQUIRED. If there is a comma/space delimited list, this is automatically
             matched from the HTTP Host header. If no match is found, the first entry is used. If only
             a single entry is present, that is always used.  -->
        <init-param>
            <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
            <param-value>test1.employees.compassplus.ru:8080</param-value>
        </init-param>
        <!--
          These are parameters specific to the ConfluenceCasFilter   
        -->
     <!--
        <init-param>

           <param-name>org.soulwing.confluence.cas.filter.loginPath</param-name>
           <param-value>/login.action</param-value>
        </init-param>
    -->
        <init-param>

           <param-name>org.soulwing.confluence.cas.filter.logoutPath</param-name>
           <param-value>/logout.action</param-value>
        </init-param>

         <init-param>

           <param-name>org.soulwing.confluence.cas.filter.logoutUrl</param-name>
           <param-value>https://cas.compassplus.ru:9444/logout.jsp</param-value>
        </init-param>

    <!--     <init-param>

           <param-name>org.soulwing.confluence.cas.filter.bypassPrefixes</param-name>
           <param-value>/rpc</param-value>
        </init-param>
    -->
    </filter>

    Now will try to tell you how can you see this problem

    what to do - step by step

    1)browse instance of confluence (through CAS auth)

    2)browse instance (the same) of confluence at new page (or tab) (CAS pass me to it without auth)

    3) logout at first tab (All is ok - redirected to a CAS server)
    4) logout at second tab (Message "You have been successfully logged out and any automatic logins removed.Log in again?
    ") 

    or another example (more fantastic and inexplicable )
     

    1)browse instance of confluence (through CAS auth)

    2)browse instance of JIRA at next tab (same server but another port) (CAS pass me to it without auth)

    3)logout at first tab (and see the same message)

     can you help me to configure confluense (its logout) to work correct?

    1. Your first example, is actually the expected behavior with the current code. Once you've logged out of the first tab, the global logout from CAS has been completed. As far as CAS and the ConfluenceCasFilter are concerned you are no longer authenticated via CAS. The state for your authentication has been removed from the browser's session cache. So when you go to the second tab and Log Out, the filter sees that you're not logged in via CAS so it shows you the usual Confluence logout page (as if you bypassed CAS login in the first place).

      What behavior would you prefer to see for this case?

      I'm not sure I'm following your second example.

  7. I had Cas working with Confluence 2.2.10 but have just upgraded to version 2.3 and now Cas no longer works. I have followed the steps associated with this site in order to upgrade and install Cas into Confluence 2.3 but I get startup errors.

    Anyone else having this problem?

    Shawn

    1. Your Java version may be the problem, version 1.5 being needed. We have CAS working on Confluence v2.3.1 with Java 1.5.09

  8. There are steps for this Authenticator for upgrading to Confluence 2.3? Could someone please direct me to them?

    Thanks!

  9. Hi,

    I've reading about the "patch" or package for using CAS with JIRA JIRA but I couldn't find it ...

    Could you send me the link to use CAS with JIRA+CONFLUENCE? ( jean [dot] verger [at]  gmail [dot] com )

    thanks

  10. Hi,

    Thanks for this easily laid out solution for integrating Confluence with CAS! It's very much appreciated!

    I need to also integrate JIRA with CAS and I understand that it can be done somewhat using the Seraph as CAS client, but I would VERY much appreciate it if you could send me your JIRA CAS Client (in whatever state it may be)?

    Thanks again,
    Karl Varga
    kjvarga at hotmail dot com

  11. I'm using Confluence 2.2.9 and 1.2.2 of the CAS Client.

    When I click the "Logout" link in Confluence, I get this:

    java.lang.IllegalStateException: Can't sendRedirect() after data has committed to the client.
    at com.caucho.server.http.Response.sendRedirect(Response.java:632)
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:123)
    at org.soulwing.confluence.cas.ConfluenceCasFilter.logout(Unknown Source)
    at org.soulwing.confluence.cas.ConfluenceCasFilter.doFilter(Unknown Source)
    [... and so on ...]

    Login works fine.  Clearly there's some very minor misconfiguration.  The only interesting wrinkle on my configuration is that CAS URLs (except for the serviceValidate URL) go through a rewrite proxy, so the Confluence configuration looks something like this:

    Confluence URL: http://testproxy/confluence

    loginURL: http://testproxy/cas/login&nbsp;(rewritten by the proxy to http://server:8080/cas/login)
    serverName: testproxy
    validateURL: https://server:8443/cas/serviceValidate
    logoutURL: http://testproxy/cas/logout

    (We're skipping HTTPS for now, since our production proxy does the HTTPS for us.)  Any ideas?

    1. This seems to be a Resin problem; I redeployed Confluence under Tomcat 5.5 and the problem magically went away.

  12. Is there any way to allow anonymous access to the Confluence server, but to bring up CAS when the login link is hit?