Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

jGuard with CAS

2009-12-25
2013-05-08
  • sweet yonce
    sweet yonce
    2009-12-25

    Hi,Everyone:
    There are some web applications used jguard in my tomcat web server (etc. ApplicationA,ApplicationB and so on),now I need setup a CAS(Center authentication service) server to manage authentication of all these applications,according to demo of CAS,I added a filter to every application's web.xml like this:

        <filter>
        <filter-name>CAS Filter</filter-name>
        <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class>
        <init-param>
        <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name>
        <param-value>https://sweet:8443/cas/login</param-value>
        </init-param>
        <init-param>
        <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
        <param-value>https://sweet:8443/cas/serviceValidate</param-value>
        </init-param>
        <init-param>
        <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
        <param-value>sweet:8088</param-value>
        </init-param>
        </filter>
       
        <filter-mapping>
        <filter-name>CAS Filter</filter-name>
        <url-pattern>/*</url-pattern>
        </filter-mapping>

    now, they look like worked very well when I visit them,for example,I visit the ApplicationA with "http://sweet:8088/ApplicationA",then the IE will turn to "https://sweet:8433/cas/login",CAS server will authentication current user after inputing into username and password,and then turn back http://sweet:8088/ApplicationA" with a ticket, but there is a LoginProcess in ApplicationA with jguard.
    How can I tell jguard in ApplicationA that current user has be authenticated by CAS? then jguard will not autenticate the subject again, and continue to authorizate it.

    Thanks a lot!

    And Merry Christma,Everyone!

     
  • Hi sweet yangiz,

    I guess the best approach is write a LoginModule that authenticate the user through this ticket instead of a login/password. The authentication process don't need the user direct interaction and will be transparent.

    's

    Vinícius Pitta Lima de Araújo

    http://www.viniciusaraujo.net

     
  • sweet yonce
    sweet yonce
    2009-12-29

    Hello vinipitta:
    Thanks for your help,I'm agree with you,and I think it's a good idea, so I tried to do it like that you said,but I used the user login value in HttpSession instead of the ticket form CAS server for authentication , I want to tell you how I did it:

    Modified the "index.jsp" of all Applications in tomcat webapps folder like this:

    1.Add "style" attribute with "display:none" for body tag to hide whole page content,so application user will see nothing on index.jsp;

    2.And add "value" attribute for login input with "<%= (String) request.getSession.getAttribute("edu.yale.its.tp.cas.client.filter.user") %>" value,because there is a attribute with "edu.yale.its.tp.cas.client.filter.user" value in this HttpSession after authenticating by CAS server;

    3.Then and follow javascript code into the end of the index.jsp like this:

        <script language="javascript">
                //alert('auto logon');
                  document.generalForm.submit();
        </script>

    because I hope that the index.jsp will be submit automaticly;

    4.Implement a CASLoginModule like this:

            …
            private boolean validatePassword(String cryptedPassword)
                                    throws LoginException {
                            System.out.println("CAS authenticated login is :" + this.login);
                            if (this.login != null && !this.login.trim().equals(""))
        //if the login is not null,it indicate that the user has been authenticated by CAS Serve
                                    return true;
                            else
                                    throw new LoginException("authentication failure.");
                    }
            …

    and it work OK,but I think that this is not a good way, it is not enough secure,can you help me to improve it?

    Thank you very much!

     
  • Yangyz,
    You are right about the security of this solution. There is no guarantee that the user have been previously authenticated. Anyone can simple insert this attribute with any value on the page and 'login'.

    What is the idea behind the ticket? I assume that when you authenticate a user you generate an ticket (eg a string based on the current time + a random number and user login). This ticket is temporary and fit only this user+session. So you can store the ticket in a cookie. This is the first part of authentication process.

    Now, when an authenticated user try to access one of your apps, you can redirect it to the loginURI and have a action that retrieve the ticket from the cookie and store associated to the user session. So your login module will look for the ticket and check it on some central control (eg DB).

    I hope my explanation is enough clear. :)

    's

    Vinícius Pitta Lima de Araújo

    http://www.viniciusaraujo.net

     
  • sweet yonce
    sweet yonce
    2009-12-30

    Hi,vinipitta
    Thanks for your suggestion and your clear explanation, I did it follow what you said, it is a perfect solution really, hehe :)
    so I tell you what I did:

    I implements a new CASLoginModel , it's "validatePassword" method has been modified like this:

        …
        private boolean validatePassword(String cryptedPassword)
        throws LoginException {
        System.out.println("CAS authenticated login is :" + this.login);
        if (this.login != null && !this.login.trim().equals(""))
        return true;
        else
        throw new LoginException("authentication failure.");
        }
        …

    I add a new AuthSchema in jGuard, it named "COOKIE_OR_SESSION", so I specify the "COOKIE_OR_SESSION" authSchema will be used in jGuardFilter.xml,and specified "/LogonProcess.do" as the "logonURI" value instead of "/Logon.do" , so user will not see login page of any sub application when the authentication has be finished by CAS server, and I add a "grabCookieAndSessionCredentials(HttpServletRequest request,Callback callbacks) " method into class  "HttpCallbackHandler",this method will be implemented like this:

        private boolean grabCookieAndSessionCredentials(HttpServletRequest request,
        Callback callbacks) {
        boolean result = false;
        // HttpSession session = request.getSession();
       
        for (int i = 0; i < callbacks.length; i++) {
        if (callbacks_ instanceof NameCallback) {
        NameCallback nc = (NameCallback) callbacks;
        String login = (String) httpRequest.getSession().getAttribute(
        "edu.yale.its.tp.cas.client.filter.user");
        nc.setName(login);
        } else if (callbacks instanceof PasswordCallback) {
        //Cookie cookies = request.getCookies();
        //for (int j = 0; j < cookies.length; j++) {
        //Cookie c = cookies;
        //logger.debug(c.getName() + ":" + c.getValue());
        //}
        PasswordCallback pc = (PasswordCallback) callbacks;
        String strPwd = "";
        if (strPwd != null && !strPwd.trim().equals("")) {
        pc.setPassword(strPwd.toCharArray());
        } else {
        pc.setPassword(null);
        }
        }
        }
        result = true;
       
        return result;
        }

    I find no cookie with user ticket ,so I can't get any ticket from cookies,and I get some login user information from session instead of cookies, :(

    At last,I add a static field "COOKIE_AND_SESSION_AUTH" into class "HttpConstants" like this:
    public final static String COOKIE_AND_SESSION_AUTH = "COOKIE_AND_SESSION";
    so jGuard will know that there is a new authentication schema in it.

    it is all, hehe :) ,it work very happy,I hope you can give me mmore  suggestions to improve this sulotion,Thanks again.
    _

     
  • Hi Yangz,

    I happen to see that you achieve a fast solution. I guess if you lapidate it maybe Charles can add it to the jGuard ext package. :)

    About the cookie, I actually don't get it. :) I mean, what you want to say with 'find no cookie'? The idea is that you generate it on the centralized login app and store in a cookie, but not mandatory as you already figured out. :)

    The real matter is to put the authentication data on each new user session because each app has it own session. I prefer to use a ticket on this approach to not expose the user private credentials (mainly password).

    Anyway, my tips are only for improvement as you already get it working! Congratulations by the work! If we not get in touch again before it: I wish and all jGuard team I happy new year. :)

    's

    Vinícius Pitta Lima de Araújo

    http://www.viniciusaraujo.net

     
  • Ops! I mean: "I am happy to see…"

     
  • Charles Lescot
    Charles Lescot
    2010-01-02

    Hi,
    happy new year and thanks for your contribution about CAS support !
    i've updated the feature request about supporting CAS (https://sourceforge.net/tracker/index.php?func=detail&aid=1641505&group_id=107276&atid=).
    when the jguard 2.0 will be out, CAS support will be part of the top items added to 2.x releases.
    about jguard 2.0 development:
    a new infrastructure has been added for a better flexibility (always relying on java security).
    more unit tests has been written for a better code quality.
    Guice 2.0 (IOC container) integration is almost finished.
    jdbcAuthorizationManager replacement by a JPA implementation need to be done.
    more news about jguard 2.0 release will be published very soon.

    thanks for your contribution and feedback.

    cheers,

    Charles.