Alfresco cas with yale cas client

Document created by resplin Employee on Jun 6, 2015
Version 1Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



WARNING: THIS CAS SETUP IS NOT OFFICIALLY SUPPORTED BY ALFRESCO.



This wiki page illustrates and example of use of the external authentication subsystem in Alfresco.
Here we use the Yale java CAS client.


Install a CAS server.


There are several CAS servers implementation, see for instance:


Note that you will need to create a SSL certificate, typically using:



openssl req \
-x509 -nodes -days 6365 \
-newkey rsa:1024 -keyout mycert.pem -out mycert.pem

At the CN question:



Common Name (eg, YOUR name) []:

you need to answer with the DNS name of your CAS server.


Get the Yale CAS client distribution


Get the file

cas-client-2.0.11.tar.gz 

from

http://downloads.jasig.org/cas-clients/



Uncompress the archive and install copy the casclient.jar
into your tomcat 'lib' folder:

cp /usr/local/cas-client-2.0.11/java/lib/casclient.jar \
/opt/alfresco344MyyaleExt/tomcat/lib/

Configure your Alfresco external subsystem


Obviously you will need to put include the external subsystem in your authentication chain:



authentication.chain=external1:external

Then you need to make sure that your alfresco back-end has:

external.authentication.proxyHeader=X-Alfresco-Remote-User

This is because Share will authenticate against alfresco using calls like:



GET /alfresco/wcs/touch HTTP/1.1
X-Alfresco-Remote-User: foouser

Then you want to set the
external.authentication.proxyUserName
to your certificate user if you use certificates.
In  this setup, on the contrary to the setup which uses mod_auth_cas it is  more difficult to secure the system without certificate as the CAS  client is embedded in the application. In the mod_auth_cas setup, apache  typically listens on port 80 and tomcat on port 8080, so it is easy to  put a firewall rule (iptables) that prevent direct connections to the  webapp forging the headers.
The certificate should match the one listed in the share-config-custom.xml file


Modify your Alfresco web.xml


In alfresco web.xml, define a new filter and call it for instance 'CAS'.
In the example below, I assume your CAS server is at https://localhost and has its login page at https://localhost/login and the validate URL is https://localhost/serviceValidate

Note also that we set 'true' on the wrapRequest option: this is because the external authentication subsystem uses the getRemoteUser() servlet all to retrieve the username of the authenticated user.





<filter>
<filter-name>CAS</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://localhost/login</param-value>
</init-param>

<init-param>
<param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name>
<param-value>https://localhost/serviceValidate</param-value>
</init-param>

<init-param>
<param-name>edu.yale.its.tp.cas.client.filter.wrapRequest</param-name>
<param-value>true</param-value>
</init-param>

<init-param>
<param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name>
<param-value>localhost:8080</param-value>
</init-param>
</filter>



This should go next to the existing filters.



Then add a mapping:






<filter-mapping>
<filter-name>CAS</filter-name>
<url-pattern>/faces/*</url-pattern>
</filter-mapping>


This should go as the first of the filter mappings (the order is important) for the /faces/* url pattern.


Make java trust your CAS server certificate


Obtain the CAS server public key.



openssl s_client -connect localhost:https
......

Server certificate

BEGIN CERTIFICATE-----
MIICpDCCAg2gAwIBAgIJAPWm9dwOShCMMA0GCSqGSIb3DQEBBQUAMGsxCzAJBgNV
BAYTAlVLMRMwEQYDVQQIDApTb21lLVN0YXRlMRAwDgYDVQQHDAdyZWFkaW5nMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2Fs
aG9zdDAeFw0xMTEwMTIxMTAwMDBaFw0yOTAzMTYxMTAwMDBaMGsxCzAJBgNVBAYT
AlVLMRMwEQYDVQQIDApTb21lLVN0YXRlMRAwDgYDVQQHDAdyZWFkaW5nMSEwHwYD
VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9z
dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0GIfCnWgN5bR8rzYQTPBwbtJ
xkGBy5lOqru7ifm2ywAPkbgnX+cYAOdTStvNtV8hGZVgqq7LKxygJw9lchY1nTBk
DNT7eTXmp410qPJw5zLkyTgPjfZAhI2d0ogeiIZhmmfQ7tP+psiMsXDhXr7LZCoh
l/bWcouP4oaMMGhYLbsCAwEAAaNQME4wHQYDVR0OBBYEFG9vKJb3OTg/++lbREJV
7maiG0nAMB8GA1UdIwQYMBaAFG9vKJb3OTg/++lbREJV7maiG0nAMAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAeTFPkYCClSkRbey8Fg3hTcsoBllpzXqf
Ft208JuYaHeUKYPsNPK6wn2hmF+AGz4Tim7Zmz7hcuVQTrM9Faa7cUTBRxDAFq6T
nV9wRoOEp1r2c2XRFSiDEnZ/yGez1vghHXsikV+SDiwaeJrad46AzVIuSvIMLGK1
OrpFomVhTQ8=

END CERTIFICATE-----
....

Save the lines from

-----BEGIN CERTIFICATE-----

to

-----END CERTIFICATE-----

(included) into a file cas.pem


Import the public key


You now can tell your JVM to trust this certifcate:



sudo keytool -import -alias localhost -keystore $JAVA_HOME/jre/lib/security/cacerts -file cas.pem

Enter keystore password:  changeit
....

Trust this certificate? [no]:  yes

Test it


When you go to http://localhost:808/alfresco, then you should get redirect to the CAS server URL
https://localhost/login
and then once authenticated you should see the alfresco content.


Configure Share


Modify Share web.xml


You need to add the same filter to the Share web.xml as the filte you added to the Alfresco (Explorer) web.xml.
You then need one extra filter mapping.
I chose to use:



<filter-mapping>
<filter-name>CAS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

but you may want to less general in the url pattern, depending on your needs.


Modify the share-config-custom.xml file


You then need have to modify the share

tomcat/bin/shared/classes/alfresco/web-extension/share-config-custom.xml

creating it from  the sample file

tomcat/bin/shared/classes/alfresco/web-extension/share-config-custom.xml.sample

and follow the NTLM SSO instructions.




Problems


Missing Publick Key


if you get;



SEVERE: Servlet.service() for servlet Faces Servlet threw exception
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
    at sun.security.validator.Validator.validate(Validator.java:218)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
    at edu.yale.its.tp.cas.util.SecureURL.retrieve(SecureURL.java:70)
    at edu.yale.its.tp.cas.client.ServiceTicketValidator.validate(ServiceTicketValidator.java:212)
    at edu.yale.its.tp.cas.client.filter.CASFilter.getAuthenticatedUser(CASFilter.java:219)
    at edu.yale.its.tp.cas.client.filter.CASFilter.doFilter(CASFilter.java:184)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.alfresco.web.app.servlet.GlobalLocalizationFilter.doFilter(GlobalLocalizationFilter.java:58)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

This means you did not install the CAS server public certifcate into your java JVM.


Bad CN


If you get



SEVERE: Servlet.service() for servlet Faces Servlet threw exception
java.security.cert.CertificateException: No name matching localhost found
    at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:210)
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:77)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:264)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:250)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
    at edu.yale.its.tp.cas.util.SecureURL.retrieve(SecureURL.java:70)
    at edu.yale.its.tp.cas.client.ServiceTicketValidator.validate(ServiceTicketValidator.java:212)
    at edu.yale.its.tp.cas.client.filter.CASFilter.getAuthenticatedUser(CASFilter.java:219)
    at edu.yale.its.tp.cas.client.filter.CASFilter.doFilter(CASFilter.java:184)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.alfresco.web.app.servlet.GlobalLocalizationFilter.doFilter(GlobalLocalizationFilter.java:58)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

Then this means there is a mismatch between the CN used when you created the certificate and the host name or the alias.


Notes


The page
http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
contains detailed information about certificates.
Authentication
Single Sign On
CAS

Attachments

    Outcomes