Caching and Re-playing Credentials

Real-world portals often need to perform credential replay in order to access interesting information on behalf of an end user. For example, an email preview portlet might need to authenticate to an IMAP store using the logged-in user's institutional username and password.

Step 1: Enable Credential Caching

  • To enable credential caching, you will need to use the CacheSecurityContext in uportal-war/src/main/resources/properties/security.properties

For each context you'd like to cache credentials, add a cache property using the following template: 

root.securityContextName.cache=org.jasig.portal.security.provider.CacheSecurityContextFactory

The following example shows a portal installation modified to cache credentials for both local and LDAP login:

## This is the factory that supplies the concrete authentication class
root=org.jasig.portal.security.provider.UnionSecurityContextFactory
root.ldap=org.jasig.portal.security.provider.SimpleLdapSecurityContextFactory
root.ldap.cache=org.jasig.portal.security.provider.CacheSecurityContextFactory
root.simple=org.jasig.portal.security.provider.SimpleSecurityContextFactory
root.simple.cache=org.jasig.portal.security.provider.CacheSecurityContextFactory

To get the cache to be populated, you will also need to allow the security credentials to continue being passed through the securityContexts by modifying uportal-war/src/main/resources/properties/portal.properties

uportal-war/src/main/resources/properties/portal.properties
## Tells the ChainingSecurityContext whether or not to stop trying to authenticate a user
## once they have successfully passed authentication
##
org.jasig.portal.security.provider.ChainingSecurityContext.stopWhenAuthenticated=false

Step 2: Uncomment cachedPasswordUserInfoService

The cachedPasswordUserInfoService bean auto-wires its other dependencies and doesn't need the full bean definition anymore: 

  • Uncomment the bean cachedPasswordUserInfoService in uportal-war/src/main/resources/properties/contexts/portletContainerContext.xml:
    <bean id="cachedPasswordUserInfoService" class="org.jasig.portal.portlet.container.services.CachedPasswordUserInfoService">
        <property name="decryptPassword" value="false"/>  <!-- If using CAS Clearpass, set to false. Use true if not using CAS Clearpass. -->
    </bean>

Step 3: Enable stringEncryptionService

You must make sure the stringEncryptionServicebean in uportal-war/src/main/resources/properties/contexts/securityContext.xml is enabled (uncommented).

    <bean id="stringEncryptionService" class="org.jasig.portal.security.JasyptPBEStringEncryptionServiceImpl">
        <property name="stringEncryptor">
            <bean class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">

                <!-- Before using the string encryption service you should first set a password.  The default
                     password works but is not secure.
                -->
                <property name="password" value="${org.jasig.portal.portlets.passwordEncryptionKey}"/>


                <!--
                    Example BouncyCastle-powered AES encryption

                    To use AES encryption, uncomment the following section, add
                    the unrestricted JCE provider files to your JVM, and add
                    the JVM-version-appropriate BouncyCastle dependency to uPortal
                -->
                <!--
                <property name="algorithm" value="PBEWITHSHA256AND128BITAES-CBC-BC"/>
                <property name="provider">
                    <bean class="org.bouncycastle.jce.provider.BouncyCastleProvider"/>
                </property>
                -->
            </bean>
        </property>
    </bean>

Though it is only used to protect password values stored in memory, it is recommended to change the default password encryption key value in uportal-war/src/main/resources/properties/portal.properties for increased security.  An alternate approach is to set the value with one of the Spring Property override files.

## Encryption key for the String Encryption Service used for user password encryption. Should be set to different value
## at least in prod, typically by using the Spring Property override files defined in CATALINA_HOME or
## PORTAL_HOME (see applicationContext.xml).  This is used to encrypt the user's password stored in-memory in the
## security context so malicious code or a hacker is less likely to obtain user's credentials.
##
org.jasig.portal.portlets.passwordEncryptionKey=changeme

Step 4:  Configure portlets

For each portlet that uPortal will pass the user's password to, the portlet's portlet.xml must be configured to accept the password as a user attribute and the portlet must be configured to use the password value.  Refer to each portlet's configuration documentation for specific procedures.

CAS Clearpass

Performing credential caching for CAS authentication is more complex, since when a user logs in via CAS, uPortal never sees the user's credentials. Luckily an interesting extension to CAS has been developed to allow the portal to query the CAS server and retrieve these credentials. Check out more on about the CAS ClearPass plug-in at How CAS relates to the Gateway SSO Portlet.

Step 1: Do the items specified above to enable password caching

Step 2: Update security.properties

Change the root.cas property to the CAS clearpass factory, and ensure the URL of the CAS clearPass service is uncommented.  You do not need a 'root.cas.cache' property because CAS is collecting and caching the password, not a uPortal security provider.

security.properties
#root.cas=org.jasig.portal.security.provider.cas.CasAssertionSecurityContextFactory
root.cas=org.jasig.portal.security.provider.cas.clearpass.PasswordCachingCasAssertionSecurityContextFactory
...
## URL of the CAS clearPass password service
org.jasig.portal.security.provider.cas.clearpass.PasswordCachingCasAssertionSecurityContextFactory.clearPassCasUrl=${environment.build.cas.protocol}://${environment.build.cas.server}/cas/clearPass

Step 3: If uPortal servers are clustered in any environment (certainly Prod), enable PGP Ticket cluster replication

1. Uncomment init-param 'proxyGrantingTicketStorageClass' in uportal-war/src/main/webapp/WEB-INF/web.xml

<!--
 | For CAS PGT replication for CAS ClearPass in a clustered uPortal environment.
 | See "Replicating PGT using "proxyGrantingTicketStorageClass" and Distributed Caching" in
 | https://wiki.jasig.org/display/CASC/Configuring+the+Jasig+CAS+Client+for+Java+in+the+web.xml
 +-->
<init-param>
    <param-name>proxyGrantingTicketStorageClass</param-name>
    <param-value>org.jasig.cas.client.proxy.EhcacheBackedProxyGrantingTicketStorageImpl</param-value>
</init-param>

2. Uncomment the cas-client-support-distributed-ehcache dependency in uportal-war/pom.xml

uportal-war/pom.xml
<!-- For clustered uPortal environments using CAS ClearPass -->
<dependency>
    <groupId>org.jasig.cas.client</groupId>
    <artifactId>cas-client-support-distributed-ehcache</artifactId>
    <version>${casclient.version}</version>
    <exclusions>
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </exclusion>
    </exclusions>
    <scope>runtime</scope>
</dependency>

3.  Configure RMI Cache Replication

a) In your uportal-war/src/main/resources/properties/ehcache.xml, uncomment either the automatic or manual RMI Peer Provider.

Approach 1:  Automatic Peer Discovery

Use this approach if all your environments that clustered uPortal servers will be running in allow multicast.  Uncomment the Automatic RMI Peer Discoverer section of ehcache.xml:

ehcache.xml
<!--
 | RMI Replicated Caching Automatic Peer Discovery.  If it works in your network environment, it is a simpler
 | configuration.
 | Need to verify it with someone who can test it though. Couldn't on my home network (see UP-4108 notes).
 | When testing it, suggest enabling debug logging as indicated in UP-4108.
 +-->
 <cacheManagerPeerProviderFactory
    class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
    properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446, timeToLive=32"
    propertySeparator="," />

TBD:  Configuration of multicast group address, port, and TTL should be specified in filters/*.properties. Please do this and submit a pull request!  (smile)

Approach 2: Manual Peer Discovery

Use this if you cannot use approach 1.  It is not as easy to maintain because each uPortal server in the cluster has to list the IP of the other servers in the cluster, but not itself so you have to update the filters/*.properties file on each server in the cluster or post-edit the ehcache.xml on each deployed uPortal webapp.

Step 1: Uncomment the manual RMI Peer Provider:

ehcache.xml
<!--
 | RMI Replicated Caching Manual Peer Discovery.  Use if automatic does not work for you or you don't want to
 | allow multicast on your network.  You must also set the IP addresses of the machines in the uPortal cluster
 | in the filters/*.properties files.
 +-->
<cacheManagerPeerProviderFactory
    class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
    properties="peerDiscovery=manual,rmiUrls=${environment.build.cas.clearpass.cache.rmi.urls}" />

Step 2: Modify your filters/*.properties file to specify the IP addresses of the servers in your uPortal cluster.  You will need to have a different version of the filters/*.properties file for EACH uPortal Server in your cluster (e.g. you will need to modify the file on each uPortal server in the cluster, and not check the modifications into git).

filters/*.properties
# Clustered uPortal CAS Clearpass RMI URI list.
# Needed if using CAS Clearpass and a clustered uPortal environment.  See https://issues.jasig.org/browse/UP-4108.
# Replaces values in ehcache.xml.  Format is a pipe-separated list of uPortal machine IPs in the cluster (not including
# this machine) and the cache name.  See http://ehcache.org/documentation/replication/rmi-replicated-caching for
# more information.  The Manual RMI Peer Discovery must be uncommented in ehcache.xml.
environment.build.cas.clearpass.cache.rmi.urls=//192.168.0.16:41001/org.jasig.cas.client.proxy.EhcacheBackedProxyGrantingTicketStorageImpl.cache|//192.168.0.17:41001/org.jasig.cas.client.proxy.EhcacheBackedProxyGrantingTicketStorageImpl.cache
# Clustered uPortal CAS Clearpass RMI Listener port.  If using manual peering, this port should match the port
# specified in the RMI URLs.  Range 1025 - 65536. Also used with automatic peer discovery.
environment.build.cas.clearpass.cache.rmi.listenerPort=41001

b) Regardless of which approach used in (a), uncomment the RMI Peer Listener in uportal-war/src/main/resources/properties/ehcache.xml:

ehcache.xml
 <!--
 | Required if using Manual or Automatic RMI Replicated Caching Peer Discovery for CAS ClearPass in clustered
 | uPortal environment.
 +-->
<cacheManagerPeerListenerFactory
    class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
    properties="port=${environment.build.cas.clearpass.cache.rmi.listenerPort}" />

c) Regardless of which approach used in (a), uncomment the cacheEventListenerFactory in cache 'org.jasig.cas.client.proxy.EhcacheBackedProxyGrantingTicketStorageImpl.cache' in uportal-war/src/main/resources/properties/ehcache.xml

ehcache.xml
<!--
 | Caches CAS Proxy-Granting Tickets (PGT) for CAS Clearpass support in a clustered uPortal environment, allowing
 | a CAS server to make the Clearpass PGT callback to any uPortal server, not just the uPortal server that initiated
 | the Clearpass PGT Request call to CAS.  Note that this cache data is replicated synchronously (really fired
 | synchronously - you don't know when the nodes in the cluster actually process the replication) to lessen the
 | chance that the uPortal node needing the PGT to request the user's password doesn't have it.  The PGT ticket
 | needs to be retained until requested by the portal to provide to a portlet, then it is not needed anymore since
 | the password is cached in the SecurityContext.
 |
 | Additional configuration steps needed:
 | - https://wiki.jasig.org/display/CASC/Configuring+the+Jasig+CAS+Client+for+Java+in+the+web.xml,
 |          section Replicating PGT using "proxyGrantingTicketStorageClass" and Distributed Caching
 | - https://wiki.jasig.org/display/CASUM/uPortal+ClearPass+Extension
 | - https://wiki.jasig.org/display/UPM40/Caching+and+Re-playing+Credentials
 |
 | For more information, see:
 | - https://wiki.jasig.org/display/UPM40/Clustering
 | - http://jasig.275507.n4.nabble.com/Re-uportal-dev-EhCache-and-jgroups-question-td4661918.html
 |
 | - 1 x user logins
 | - CAS PGT replicated synchronously
 +-->
<cache name="org.jasig.cas.client.proxy.EhcacheBackedProxyGrantingTicketStorageImpl.cache"
       eternal="false" overflowToDisk="false" diskPersistent="false"
       maxElementsInMemory="10000" timeToIdleSeconds="600" timeToLiveSeconds="0"
       memoryStoreEvictionPolicy="LRU" statistics="true">
    <cacheEventListenerFactory
        class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
        properties="replicateAsynchronously=false,
            replicatePuts=true,
            replicateUpdates=true, replicateUpdatesViaCopy=true,
            replicateRemovals=true "/>
</cache>

Step 4: Enable SSL on uPortal servers

CAS Clearpass requires the uPortal servers to be using HTTPS.  Follow Tomcat's instructions for enabling SSL.

Local development environment

For a local development environment where the bundled CAS server is being used, you can use a self-signed certificate by following these steps.

1. Generate a self-signed certificate (http://www.sslshopper.com/article-how-to-create-a-self-signed-certificate-using-java-keytool.html)

2. Enable HTTPS in your Tomcat using your certificate (http://www.sslshopper.com/tomcat-ssl-installation-instructions.html)

3. Import your private certificate into your java jre/lib/security/cacerts (see http://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html).

Also modify your filters/local.properties to use https://<servername>:8443 for both uPortal and CAS, or adjust the configuration of 'clearPassProxyList' in CAS's clearpass-configuration.xml accordingly (see Step 5).  You cannot use a server name of localhost.

Step 5: Configure CAS server for Clearpass

Enable ClearPass on the CAS server: https://wiki.jasig.org/display/CASUM/ClearPass.

Local development environment

If using the CAS Server bundled with uPortal, perform 'Step 1: Modifying deployerConfigContext.xml' at the above URL to enable Clearpass.