Vous êtes sur la page 1sur 16

Vidyayug Soft Technologies Private Limited

6-3-597/A/1/A,
Venkatramana Colony, Khairatabad,
Hyderabad - 500004.
Date: 25th August 2010
Document Type: CAS Documentation
Author: Ravi Kumar Dhara & Chandrasekhar

Version
1.0

Modified By
Chandrasekhar and Ravi Kumar

Modified Date
25-08-2010

Comments
---

Contents

CENTRAL AUTHENTICATION SERVICE (CAS) with Liferay..................................................2


Setting up CAS server................................................................................................... 2
Step 1: Download cas-web.war.................................................................................2
Step 2: Copy cas-web.war file into tomcat\webapps..................................................2
Step 3: Edit server.xml ( tomcat/conf/server.xml)......................................................2
Step 4: Set up in properties files...............................................................................3
system-ext.properties............................................................................................. 3
portal-ext.properties............................................................................................... 3
Step 5: Password in Plain Text................................................................................... 3
Step 6: Configure the SSL port no and certificate information..................................3
Step 7: Database Configuration : CAS with lportal database....................................4
Step 8: Enabling the Single Sign Out in argumentExtractorsConfiguration.xml........5
Step 9: Single Sign Out............................................................................................. 5
Step 10: ADD the necessary jar files on lib folder of CAS Server..............................5
Step 11: Configuring the CAS properties through GUI...............................................6
Step 12: Modify the following classes accordingly.....................................................6
CASAutoLogin:........................................................................................................ 7
CASFilter:.............................................................................................................. 11
Step 13: Add the new action path in struts-config.xml..........................................14
Page 1 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited

CENTRAL AUTHENTICATION SERVICE (CAS) with Liferay


CAS is an authentication system that was originally created at Yale University. It is a widely-used
open source single sign-on solution, and was the first SSO product to be supported by Liferay.
The CAS Server application requires a properly configured Secure Socket Layer certificate on your
server in order to work.
If you wish to generate one yourself, you will need to use the keytool utility that comes with the
JDK. Your first step is to generate the key. Next, you export the key into a file. Finally, you import the key
into your local Java key store.

Setting up CAS server


Step 1: Download cas-web.war
Step 2: Copy cas-web.war file into tomcat\webapps
Step 3: Edit server.xml ( tomcat/conf/server.xml)
Uncomment this part :
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
Replace the above line with the following:
<Connector SSLEnabled="true" clientAuth="false" keystoreFile="D:/cygwin/java/jdk/jdk1_6_0_16/bin/ityug.keystore" keystorePass="ityug123" maxThreads="150" port="8443"
protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS"/>
Generate the SSL cert with Java keytool
Go to tomcat/webapps/Root in command prompt, enter the command:
keytool -genkey -alias localhost -keypass changeit -keyalg RSA
Note: Be sure to use the keytool that comes with the Java VM (%JAVA_HOME%/jre/bin/keytool), as on
some systems the default points to the GNU version of keytool, where the two seem incompatible.

Answer the questions in command prompt : (note that your firstname and lastname MUST be
hostname of your server and cannot be a IP address; this is very important as an IP address will fail
client hostname verification even if it is correct)
Enter keystore password: changeit
What is your first and last name?
[Unknown]: localhost
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
Page 2 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown,
C=Unknown correct?
[no]: yes

Finally import the cert into Java's keystore with this command. Tomcat uses the keystore in
your JRE (%JAVA_HOME%/jre/lib/security/cacerts)
keytool -import -alias tomcat -file %FILE_NAME% -keypass changeit -keystore "C:/Program
Files/ Java/jdk1.6/jre/lib/security/cacerts"
OR
keytool importkeystore srcalias tomcat srckeystore <location file>
-srckeypass changeit destkeystore /java/jdkl1.6/./lib/security/cacerts
Creating the certificate:

See the created certificate:

Page 3 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited

Import the created certificate into java cacerts:

See the created list of certificates:

Step 4: Set up in properties files


system-ext.properties
#
# The CAS filter will redirect the user to the CAS login page for SSO.
# See [http://www.ja-sig.org/products/cas] for more information.
#
com.liferay.filters.sso.cas.CASFilter=true

portal-ext.properties
Put this in portal-ext.properties.

Page 4 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


For Liferay-5.1.2:
-----------------------cas.auth.enabled=true
auto.login.hooks=com.liferay.portal.security.auth.RememberMeAutoLogin,
com.liferay.portal.security.auth.CASAutoLogin
For Liferay-5.2.3:
-------------------------cas.auth.enabled=true
auto.login.hooks=com.liferay.portal.security.auth.BasicAuthHeaderAutoLogin,com.liferay.portal.secu
rity.auth.CASAutoLogin

Step 5: Password in Plain Text


(For testing the cas initially we need to configure password to store in plain text)
Put this in portal-ext.properties.
Passwords are stored in the plain text on lportal database.
##
## Passwords
##
passwords.encrypted=false
passwords.encryption.algorithm=NONE

Step 6: Configure the SSL port no and certificate information.


(location: tomcat/conf/server.xml )
<Connector SSLEnabled="true" clientAuth="false" keystoreFile="D:/cygwin/java/jdk/jdk1_6_0_16/bin/localhost.keystore" keystorePass="changeit" maxThreads="150" port="8443"
protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS"/>

Step 7: Database Configuration : CAS with lportal database


Comment the following line : SimpleTestUsername
<bean
class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /
>
To read the simple plain text as password
<bean id="SearchModeSearchDatabaseAuthenticationHandler"
class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler" abstract="false"
singleton="true" lazy-init="default" autowire="default" dependency-check="default">
<property name="tableUsers">
Page 5 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


<value>user_</value>
</property>
<property name="fieldUser">
<value>emailAddress</value>
</property>
<property name="fieldPassword">
<value>password_</value>
</property>
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="select password from some_table where
lower(username) = lower(?)" />
</bean>
To read the encrypted password:
For reading encrypted password we need to write the out own class with SHA encrypted algorithm
and place the class(QueryDatabaseAuthenticationSHA1Base64) in the following package of the cas-client :
(org.jasig.cas.adaptors.jdbc)
Add the following database information on deployerConfigContext.xml of CAS
(location: tomcat\webapps\cas-web\WEB-INF)
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationSHA1Base64">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="select password_ from user_ where lower(emailAddress) =
lower(?)" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/lportal</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>ityug123</value>
</property>
</bean>

Step 8: Enabling the Single Sign Out in


argumentExtractorsConfiguration.xml
(location: tomcat\webapps\cas-web\WEB-INF\spring-configuration)
Page 6 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


<bean id="casArgumentExtractor"
class="org.jasig.cas.web.support.CasArgumentExtractor" />
Replace the above with the following for enabling the Single Sign Out.
<bean id="casArgumentExtractor" class="org.jasig.cas.web.support.CasArgumentExtractor" >
<property name="disableSingleSignOut">
<value>false</value>
</property>
</bean>

Step 9: Single Sign Out


Update the web.xml file for Single Sign Out: /tomcat-6.0.16/webapps/ROOT/WEB-INF/web.xml
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>

Step 10: ADD the necessary jar files on lib folder of CAS Server
Liferay needs the cas-client-core-3.1.6.jar in the portal classpath for setting the Single Sign Out.. Download
the cas client form the following path:
(http://www.ja-sig.org/downloads/cas-clients/).

Page 7 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited

Step 11: Configuring the CAS properties through GUI

Step 12: Modify the following classes accordingly


CASAutoLogin:
File Path :
D:\cygwin\java\workspace\portal\portal-impl\src\com\liferay\portal\security\auth
Modification in CASAutoLogin:
1.) Adding the email address as authentication
2.) User specific login
CASFilter:
File Path :
D:\cygwin\java\workspace\portal\portal-impl\src\com\liferay\portal\servlet\filters\sso\cas
Modification in CASFilter :
1) Getting the CAS serviceURL name as dynamic.
2) Instead of redirecting to CAS logout URL we made changes to navigate to the
requestURI of Home page.
Note : To see the changes done in the above files, refer to the same color, in the following code.
CASFilter & CASAutoLogin:
---------------------------------------We are setting the the follwing property true in system-ext.properties
com.liferay.filters.sso.cas.CASFilter=true
So CASFilter class will redirect the user to the CAS login page for SSO.
Page 8 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited

The following are the detailed steps:


a. User logs in to liferay portal.
b. Because of configured CASFilter, it leads to CAS login screen. We also send the service url.
c. After successful authentication, CAS server redirects the request to this service url. The
generated ticket is set in the request.
d. The redirection to service url again goes through CASFilter.
e. CASFilter finds the ticket in the request and tries to validate it.
f. It sends validation request to CAS server.
g. Upon successful validation, the CASFilter will set the CAS_FILTER_USER attribute in
session.
h. Now control goes to CASAutoLogin where it successfully gets the userId.
i. Now we will get the organizationIds by passing the userId as a parameter to validate users
with organization. If validation is successful we are allowing the user to login to that
particular Organization.

CASAutoLogin:
package com.liferay.portal.security.auth;
import java.util.List;
import javax.naming.Binding;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.liferay.portal.NoSuchUserException;
import com.liferay.portal.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.Group;
import com.liferay.portal.model.LayoutSet;
import com.liferay.portal.model.Organization;
import com.liferay.portal.model.User;
import com.liferay.portal.security.ldap.PortalLDAPUtil;
import com.liferay.portal.service.GroupLocalServiceUtil;
import com.liferay.portal.service.LayoutSetLocalServiceUtil;
import com.liferay.portal.service.OrganizationLocalServiceUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.util.PrefsPropsUtil;
import com.liferay.portal.util.PropsKeys;
import com.liferay.portal.util.PropsUtil;
import com.liferay.portal.util.PropsValues;
import edu.yale.its.tp.cas.client.filter.CASFilter;
Page 9 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


public class CASAutoLogin implements AutoLogin
{
public String[] login(HttpServletRequest request, HttpServletResponse response)
{
String[] credentials = null;
try
{
long companyId = PortalUtil.getCompanyId(request);
if (!PrefsPropsUtil.getBoolean(companyId,
PropsKeys.CAS_AUTH_ENABLED,PropsValues.CAS_AUTH_ENABLED))
{
return credentials;
}
HttpSession session = request.getSession();
String userName = (String)session.getAttribute(CASFilter.CAS_FILTER_USER);
if (Validator.isNull(userName))
{
return credentials;
}
User user = null;
try //Authenthentication based on screenName or emailAddress or userId
{
if(authType.equals("emailAddress"))
{
user = UserLocalServiceUtil.getUserByEmailAddress(companyId, userName);
}
else if(authType.equals("screenName"))
{
user = UserLocalServiceUtil.getUserByScreenName(companyId, userName);
}
else if(authType.equals("userId"))
{
user = UserLocalServiceUtil.getUserById(companyId, Long.parseLong(userName));
}
}
catch (NoSuchUserException nsue)
{
if (PrefsPropsUtil.getBoolean(companyId,
PropsKeys.CAS_IMPORT_FROM_LDAP,PropsValues.CAS_IMPORT_FROM_LDAP))
{
user = addUser(companyId, userName);
}
else
{
throw nsue;
}
}
credentials = new String[3];
String serverName = request.getServerName();
//In order to validate the user with organizations to login
if(user != null)
{
if(serverName.equalsIgnoreCase("www.localhost.com"))
{
Page 10 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


credentials[0] = String.valueOf(user.getUserId());
credentials[1] = user.getPassword();
credentials[2] = Boolean.TRUE.toString();
return credentials;
}
else
{
try
{
List organizations = OrganizationLocalServiceUtil.getUserOrganizations(user.getUserId());
LayoutSet layout = LayoutSetLocalServiceUtil.getLayoutSet(serverName);
long layoutGroupId = layout.getGroupId();
for (int i = 0; i < organizations.size(); i++)
{
Organization organization = (Organization)organizations.get(i);
long organizationId = organization.getOrganizationId();
Group group = GroupLocalServiceUtil.getOrganizationGroup(companyId, organizationId);
long groupId = group.getGroupId();
try
{
if(groupId == layoutGroupId )
{
credentials[0] = String.valueOf(user.getUserId());
credentials[1] = user.getPassword();
credentials[2] = Boolean.TRUE.toString();
return credentials;
}
}
catch (Exception e)
{
System.out.println("Exception from CASAutoLogin" + e.getMessage());
}
}//End of for loop
credentials = null;
return credentials;
}
catch (Exception e)
{
_log.warn("User does not have belong to an organization");
}
}
}
}
catch (Exception e)
{
_log.error(e, e);
}
return credentials;
}
protected User addUser(long companyId, String screenName)throws SystemException
{
Page 11 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited

try
{
String baseDN = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_DN);
LdapContext ctx = PortalLDAPUtil.getContext(companyId);
if (ctx == null)
{
throw new SystemException("Failed to bind to the LDAP server");
}
String filter = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_AUTH_SEARCH_FILTER);
if (_log.isDebugEnabled())
{
_log.debug("Search filter before transformation " + filter);
}
filter = StringUtil.replace(filter,new String[] {"@company_id@", "@email_address@",
"@screen_name@"},
new String[] {String.valueOf(companyId), StringPool.BLANK, screenName});
if(filter != null)
System.out.println("Filter :" + filter);
if (_log.isDebugEnabled())
{
_log.debug("Search filter after transformation " + filter);
}
SearchControls cons = new SearchControls(SearchControls.SUBTREE_SCOPE, 1, 0, null, false,
false);
NamingEnumeration<SearchResult> enu = ctx.search(baseDN, filter, cons);
if (enu.hasMoreElements())
{
if (_log.isDebugEnabled())
{
_log.debug("Search filter returned at least one result");
}
Binding binding = enu.nextElement();
Attributes attrs = PortalLDAPUtil.getUserAttributes(companyId,
ctx,PortalLDAPUtil.getNameInNamespace(companyId, binding));
return PortalLDAPUtil.importLDAPUser(companyId, ctx, attrs, StringPool.BLANK, true);
}
else
{
throw new NoSuchUserException("User " + screenName + " was not found in the LDAP
server");
}
}
catch (Exception e)
{
_log.error("Problem accessing LDAP server ", e);
throw new SystemException("Problem accessign LDAP server " + e.getMessage());
}
Page 12 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


}
private static Log _log = LogFactoryUtil.getLog(CASAutoLogin.class);
}

CASFilter:
package com.liferay.portal.servlet.filters.sso.cas;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.servlet.BaseFilter;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.util.PrefsPropsUtil;
import com.liferay.portal.util.PropsKeys;
import com.liferay.portal.util.PropsValues;
import com.liferay.util.servlet.filters.DynamicFilterConfig;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class CASFilter extends BaseFilter
{
public static void reload(long companyId)
{
_casFilters.remove(companyId);
}
protected Filter getCASFilter(long companyId,String serviceUrl) throws Exception
{
edu.yale.its.tp.cas.client.filter.CASFilter casFilter = _casFilters.get(companyId);
if (casFilter == null)
{
casFilter = new edu.yale.its.tp.cas.client.filter.CASFilter();
}
DynamicFilterConfig config = new DynamicFilterConfig(_filterName, _servletContext);
String serverName = PrefsPropsUtil.getString(companyId,
PropsKeys.CAS_SERVER_NAME,PropsValues.CAS_SERVER_NAME);
Page 13 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


System.out.println("ServiceURL requested: " +serviceUrl);
config.addInitParameter(edu.yale.its.tp.cas.client.filter.CASFilter.LOGIN_INIT_PARAM,
PrefsPropsUtil.getString(companyId,
PropsKeys.CAS_LOGIN_URL,PropsValues.CAS_LOGIN_URL));
if (Validator.isNotNull(serviceUrl))
{

config.addInitParameter(edu.yale.its.tp.cas.client.filter.CASFilter.SERVICE_INIT_PARAM,serviceUrl);
}
else
{

config.addInitParameter(edu.yale.its.tp.cas.client.filter.CASFilter.SERVERNAME_INIT_PARAM,serverName
);
}
config.addInitParameter(edu.yale.its.tp.cas.client.filter.CASFilter.VALIDATE_INIT_PARAM,
PrefsPropsUtil.getString(companyId,
PropsKeys.CAS_VALIDATE_URL,PropsValues.CAS_VALIDATE_URL));
casFilter.init(config);
_casFilters.put(companyId, casFilter);
return casFilter;
}
protected Log getLog()
{
return _log;
}
protected void processFilter(HttpServletRequest request, HttpServletResponse response,FilterChain
filterChain)
{
try
{
long companyId = PortalUtil.getCompanyId(request);
String serverName = PrefsPropsUtil.getString(companyId,
PropsKeys.CAS_SERVER_NAME,PropsValues.CAS_SERVER_NAME);
String serviceUrl = PrefsPropsUtil.getString(companyId,
PropsKeys.CAS_SERVICE_URL,PropsValues.CAS_SERVICE_URL);
try
{
URI requestURI = new URI(request.getRequestURL().toString());
if(requestURI != null)
System.out.println("requestURI :" + requestURI);
serviceUrl = requestURI.toString();
}
catch (URISyntaxException e)
{
System.out.println("Exception from the URI :" + e.getMessage());
}
Page 14 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited

if (PrefsPropsUtil.getBoolean(companyId,
PropsKeys.CAS_AUTH_ENABLED,PropsValues.CAS_AUTH_ENABLED))
{
String pathInfo = request.getPathInfo();
if (pathInfo.indexOf("/portal/logout") != -1)
{
HttpSession session = request.getSession();
session.invalidate();
String logoutUrl = PrefsPropsUtil.getString(companyId,
PropsKeys.CAS_LOGOUT_URL,PropsValues.CAS_LOGOUT_URL);
//Inorder to redirecting to cas logout page we need to redirect the requestedURI Home page once
the signout is clicked.
String url = "/portal/caslogout";
url = request.getContextPath() + request.getServletPath() + url;
try
{
URI requestURI = new URI(request.getRequestURL().toString());
URI redirectURI = requestURI.resolve(url);
url = redirectURI.toString();
}
catch (URISyntaxException e)
{
System.out.println("Exception :" + e.getMessage());
}
final String urlEncodedService = response.encodeURL(url);
final StringBuffer buffer = new StringBuffer(255);
buffer.append(logoutUrl).append("?
service=").append(URLEncoder.encode(urlEncodedService, "UTF-8"));
response.sendRedirect(buffer.toString());
//response.sendRedirect(logoutUrl);
}
else
{
// Add the the serviceUrl argument for getting the serviceUrl of CAS dynamically.
Filter casFilter = getCASFilter(companyId,serviceUrl);
casFilter.doFilter(request, response, filterChain);
}
}
else
{
processFilter(CASFilter.class, request, response, filterChain);
}
}
catch (Exception e) {
_log.error(e, e);
}
}
private static Log _log = LogFactoryUtil.getLog(CASFilter.class);
private static Map<Long, edu.yale.its.tp.cas.client.filter.CASFilter>
Page 15 of 16
Confidential
www.ityug.com

Vidyayug Soft Technologies Private Limited


_casFilters = new ConcurrentHashMap
<Long, edu.yale.its.tp.cas.client.filter.CASFilter>();
private String _filterName;
private ServletContext _servletContext;
}

Step 13:

Add the new action path in struts-config.xml

(location: D:\cygwin\java\workspace\portal\portal-web\docroot\WEB-INF)
<action path="/portal/caslogout" type="com.liferay.portal.action.LogoutAction" />
Testing the CAS server
Start tomcat and click Sign-In from Dock Menu . It will redirect to CAS server page as follows:
(Access CAS with https://localhost:8443/cas-web/login You should see the CAS login screen and no
errors in your catalina logs. )

Page 16 of 16
Confidential
www.ityug.com

Vous aimerez peut-être aussi