Tuesday 24 February 2015

snLibrary with Jasig CAS (v9.0 11 Aug 2010)

snLibrary with Jasig CAS

We all know that the implementation of Central Authentication System (CAS) by JASIG is one of the most popular ones thanks to its simplicity and ease of implementation. 

When many web applications started mushrooming, the next necessity that evolved might not be by design but by desire was CAS as a means for Single Sign-On to all those small and big web-applications.

After a few days of R&D on different methods of Single Sign-On, I came across Jasig-CAS.  Later on, I found that an easy & simple implementation of the Jasig Server was the RubyCAS (https://rubycas.github.io/) by Matt Zukowski.  Though I was not well versed in Ruby, I had heard about it and had a few encounters with it while implementing SSMS (Servo Stockist Management System) a miniERP which we got developed through outsourcing.  The simplicity of the language and the enormous potential it has for the future gives me goose-bumps (or should I say porcupine bumps!!).
Basic CAS Single Sign-On Diagram
But what has snLibrary got to do with CAS implementation since JASIG CAS implementation is fairly straightforward and simple??.

My little experience in software development &testing drove me to implementing a facility even for CAS.  The requirement was that as a developer, I should not be required to be actually authenticated to the domain during that phase.  For instance, many of the developers could be some outsourced men/women who needn't have to be provided with userid/passwords of our employees.

Thus it was indeed necessary that by a setting a flag in the configuration file, I should be able to manage the login.  Thus, was implemented the method:- 'isCASenabled()' in the snLibrary.  This would check whether CAS is to be effected for the implementation of the web-application.
However, in the production site, the snConfigFile contained 'CAS Enabled=1' so that the application security could be taken care.

Few other additional parameters were also included for session time out and for redirecting upon logout.

File:-c:/snConfig/snConfigMyApplication.ini
CAS Enabled=1
CAS Config Properties File Name=c:/snConfig/SSO/snCASCfg.ini
Home URL=http://spandan.indianoil.co.in/myApplication/

File:-c:/snConfig/SSO/snCASCfg.ini
CAS-Server URL Prefix=JaanasiMaamVaa
CAS-Server Login Servlet=login
CAS-Server Logout Servlet=logout

CAS-Server Logout Service Parameter=/?service=
CAS-Server Logout Default Home URL=http://www.indianoil.co.in

Web-Server Protocol Prefix=http://
Web-Server Host Address=localhost
Web-Server Port=8084

#CAS-Server Protocol Prefix=http://
#CAS-Server Host Address=10.146.64.153
#CAS-Server Port=8080

CAS-Server Protocol Prefix=http://
CAS-Server Host Address=spandan.indianoil.co.in
CAS-Server Port=

In case of SSL configuration, the same could be as follows:-
File:-c:/snConfig/SSO/snCASCfg.ini
CAS-Server Logout Service Parameter=?service=
CAS-Server Logout Default Home URL=http://www.indianoil.co.in

CAS-Server Protocol Prefix=https://
CAS-Server Host Address=spandan.indianoil.co.in
CAS-Server Port=

CAS-Server URL Prefix=JaanasiMaamVaa
CAS-Server Login Servlet=login
CAS-Server Logout Servlet=logout

Web-Server Protocol Prefix=http://
Web-Server Host Address=10.146.65.10
Web-Server Port=80

Needless to say, the standard filter for the web.xml for Jasig-CAS remains the same and would be something as follows:
File:-WEB-INF/web.xml 
  <!--
  <filter>
      <filter-name>CAS Authentication Filter</filter-name>
      <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
      <init-param>
          <param-name>casServerLoginUrl</param-name>
          <param-value>http://webapp.indianoil.co.in/JaanasiMaamVaa/login</param-value>
      </init-param>
      <init-param>
          <param-name>serverName</param-name>
          <param-value>http://localhost:8084</param-value>
      </init-param>
  </filter>
  <filter>
      <filter-name>CAS Validation Filter</filter-name>
      <filter-class>org.jasig.cas.client.validation.Cas10TicketValidationFilter</filter-class>
      <init-param>
          <param-name>casServerUrlPrefix</param-name>
          <param-value>http://webapp.indianoil.co.in/JaanasiMaamVaa/</param-value>
      </init-param>
      <init-param>
          <param-name>serverName</param-name>
          <param-value>http://localhost:8084</param-value>
      </init-param>
      <init-param>
          <param-name>redirectAfterValidation</param-name>
          <param-value>true</param-value>
      </init-param>
  </filter>
  <filter>
      <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
      <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>CAS Authentication Filter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter-mapping>
      <filter-name>CAS Validation Filter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter-mapping>
      <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  -->

In the implementation of the source-code, the following would be of guidance. 
File:-ValidateUser.java
import sessions.snAuthentications;
import config.snConfigVars;

// ... Some code goes here ...

  snConfigVars V = snConfigVars.getInstance();

  if (V.isCASenabled()) {
    //String authIdStr = request.getUserPrincipal().getName();
    String authIdStr = snAuthentications.getAuthenticationId_Numeric(request);
    try {
      authId = Integer.parseInt(authIdStr);
    } catch (Exception ee) {
      authId = 0;
    }
  }
 if (authId > 0) {
    GlobalVariables GV = new GlobalVariables();
    //String uid = null;
    //uid = Long.toString(authId);
    hV = (Hashtable) session.getAttribute(GV.JGURUJI);
    if (hV == null) {
      JGUser user = new JGUser(authId);  // Create a User Class from the authId.
      if (user != null) {
        hV = new Hashtable();
        session.setAttribute(GV.JGURUJI, hV);
        hV.put(GV.USER, user);
        //logger.info("");
        log.info("User: {} {}", authId, " Successfully Logged in.");
        successLogin = true;
      } else {
        successLogin = false;
        session.removeAttribute(GV.JGURUJI);
        log.info("User: {} {}", authId, " Login Failed.");
      }
    }
  }
  String forwardURL = "error.jsp";
  if (!successLogin || hV == null) {
    RequestDispatcher rd = request.getRequestDispatcher(forwardURL);
    if (rd != null) {
      rd.forward(request, response);
    }
  } else {
     if (successLogin) {
          snAuthentications.properlyLoggedIn(request, response);
     }
  }

And this is what you would get for the Single Sign-On !!. 





I had initially used the following codelet for the login page so that it was possible to have a separate authentication route for the developer/tester and another for the tester/end-user.  Here, if CAS was set to be enabled, then it would use the CAS credentials.  However, if otherwise, then it would throw up a Challenge screen for Authentication through the login page.

<%@ page import="config.snConfigVars" import="sessions.snAuthentications" %>
// ...
// ...  Some HTML page code goes here....
// ...
<form action='validate.jsp'   method='POST' >
<table >
      <%
      String user_id = "";
      snConfigVars V = snConfigVars.getInstance();
      long authId = 0L;
      if (V.isCASenabled()) {
        user_id = (new snAuthentications()).getAuthenticationId_Numeric(request);
        try {
          authId = Long.parseLong(user_id);
        } catch (Exception ee) {
          authId = 0L;
        }
      }
      if (authId > 0) {
      %>
      <input name="user_id" type="hidden" id="user_id"  value="<%=authId %>" size="15" maxlength="10">
      <input name="passwd" type="hidden" id="passwd"  value="snpassword" size="15" maxlength="15">
      <% 
      } else {
    
%>
    <tr valign="top"> 
      <td width="20%" bgcolor="#F0F0F0"> <div align="right"><font size="2" face="Verdana, Arial, Helvetica, sans-serif">User ID :</font></div></td>
      <td width="29%" bgcolor="#F0F0F0"> <input name="user_id" type="text" id="user_id" size="15" maxlength="10"></td>
    </tr>
    <tr valign="top"> 
      <td bgcolor="#F0F0F0"> <div align="right"><font size="2" face="Verdana, Arial, Helvetica, sans-serif">Password 
          :</font></div></td>
      <td bgcolor="#F0F0F0"> <input name="passwd" type="password" id="passwd" size="15" maxlength="15"></td>
    </tr>
      <%
      }
      %>
<tr><td>
<input name="submit" type="submit" value="<%=(authId > 0) ? "Continue" : "Submit"%>" />
</td></tr>
</table>
</form>

And further inside the validate.jsp, you can validate the authId only if CAS is not enabled (using isCASenabled() method).




No comments:

Post a Comment