The AMSeT Project Blog http://www.socketelf.org:8080/roller/amset/ Funded by JISC IE Programme en-us Copyright 2009 Sat, 26 Sep 2009 00:29:45 +0100 Apache Roller (incubating) 3.1 (20070421020349:dave) http://www.agbooth.com/AMSeTBlog/www.socketelf.org_8080/roller/amset/entry/shibbing_alfresco.html Shibbing Alfresco Andrew G. Booth http://www.agbooth.com/AMSeTBlog/www.socketelf.org_8080/roller/amset/entry/shibbing_alfresco.html Tue, 16 Jun 2009 14:37:31 +0100 Guanxi amset guanxi saml shibboleth <p><b>Introduction</b></p> <p>Part of the AMSeT project is the addition of a Shibboleth Service Provider to Alfresco. Some work has already been done in this area by <a href="http://forums.alfresco.com/en/viewtopic.php?f=11&t=6331&p=60568&hilit=Shibboleth#p60568" target="new">Kimmo Ilppola</a>, but this has used the Internet 2 implementation of the Shibboleth SAML Profile. This requires Apache as well as Tomcat and is complicated to set up and test. </p> <p>We decided to use the <a href="http://www.guanxi.uhi.ac.uk" target = "new">Guanxi</a> implementation instead. Written entirely in Java by Alistair Young at the University of the Highlands and Islands, all Guanxi modules are fully compatible with the Internet2 implementation and also fully compatible with the UK Access Management Federation and OpenAthens. These notes describe how Alfresco was 'shibbed' using Guanxi.</p> <p><b>Adding Guanxi to Alfresco</b></p> <p>We used Tomcat version 5.5.27, Java 1.6.0_13 and Alfresco Labs version 3 final. Most of our work has been done using Red Hat Enterprise 5 on a 64-bit Dell server, but we have also successfully installed Guanxi on Windows and OSX computers.</p> <p>We'll assume that Java, Tomcat and Alfresco have been successfully installed and that the Alfresco webapp is installed at &lt;TOMCAT_HOME&gt;/webapps/alfresco. We downloaded and compiled the source code of all five modules of Guanxi (WAYF, IdP, security provider, SP engine and SP guard from <a href="http://sourceforge.net/project/showfiles.php?group_id=134770" target="new">Sourceforge</a>. Installation of Guanxi, protecting a test webapp - &lt;TOMCAT_HOME&gt;/webapps/protectedapp - was done as described in <a href="http://www.guanxi.uhi.ac.uk/index.php/Guanxi_localhost_2" target="new">Alistair's localhost tutorial</a>, except that all references to localhost were replaced by the domain name of the server.</p> <p>Having tested Guanxi and made sure that the attributes were being released by the IdP, it was time to copy the Guanxi guard to the alfresco webapp.<br/> <code><br/> cd &lt;TOMCAT_HOME&gt;/webapps/alfresco<br/> cp -r ../protectedapp/guanxi_sp .<br/> cp -r ../protectedapp/protected .<br/> cd WEB-INF<br/> cp -r ../../protectedapp/WEB-INF/classes .<br/> cp -r ../../protectedapp/WEB-INF/guanxi_sp_guard .<br/> </code><br/> Then we compared the contents of &lt;TOMCAT_HOME&gt;/webapps/alfresco/WEB-INF/lib with the contents of &lt;TOMCAT_HOME&gt;/webapps/protectedapp/WEB-INF/lib and copied from the latter to the former any files that were only found in the latter. Any jar files that were older in the former were removed and replaced with the newer files from Guanxi.</p> <p>We modified Kimmo Ilppola's authentication filter to include the creation of groups and to implement a logout from the SP. Here is the <a href="http://www.agbooth.com/AMSeTBlog/www.socketelf.org_8080/roller/amset/resource/ShibbolethHTTPRequestAuthenticationFilter.java" target="new">Java code</a>. The compiled class file was placed in the directory &lt;TOMCAT_HOME&gt;/webapps/alfresco/WEB-INF/classes/org/alfresco/web/app/servlet. </p> <p>The corresponding <a href="http://www.agbooth.com/AMSeTBlog/www.socketelf.org_8080/roller/amset/resource/shibbolethAttributes.properties" target="new">shibbolethAttributes.properties</a> was placed in the directory &lt;TOMCAT_HOME&gt;/webapps/alfresco/WEB-INF/classes.</p> <p>The web.xml files of the alfresco and Guanxi Guard webapps were then merged. Here is the <a href="http://www.agbooth.com/AMSeTBlog/www.socketelf.org_8080/roller/amset/resource/web.xml" target="new">merged file</a>.</p> <p>The next file to edit was &lt;TOMCAT_HOME&gt;/webapps/alfresco/WEB-INF/guanxi_sp_guard/config/guanxi-sp-guard.xml and here is the content of our file:<br/> <code><br/> &lt;?xml version="1.0" encoding="UTF-8"?&gt;<br/> &lt;Guard xmlns="urn:guanxi:sp"&gt;<br/> &nbsp;&nbsp;&lt;GuardInfo&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;HostName&gt;socket1.leeds.ac.uk&lt;/HostName&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;ID&gt;alfresco-guard&lt;/ID&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;AttributePrefix&gt;HTTP_&lt;/AttributePrefix&gt;<br/> &nbsp;&nbsp;&lt;/GuardInfo&gt;<br/> &nbsp;&nbsp;&lt;Cookie&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;Domain&gt;.leeds.ac.uk&lt;/Domain&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;Path&gt;/&lt;/Path&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;Age units="transient"/&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;Prefix&gt;GUANXI_GUARD_SERVICE_PROVIDER_&lt;/Prefix&gt;<br/> &nbsp;&nbsp;&lt;/Cookie&gt;<br/> &nbsp;&nbsp;&lt;EngineInfo&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;AuthConsumerURL&gt;https://socket1.leeds.ac.uk:8443/samlengine/shibb/acs&lt;/AuthConsumerURL&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;WAYFLocationService&gt;https://socket1.leeds.ac.uk:8443/samlengine/shibb/wayf-location&lt;/WAYFLocationService&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;Timeout&gt;10&lt;/Timeout&gt;<br/> &nbsp;&nbsp;&lt;/EngineInfo&gt;</p> <p>&nbsp;&nbsp;&lt;TrustStore&gt;/opt/tomcat55/webapps/alfresco/WEB-INF/guanxi_sp_guard/truststore/guard.jks&lt;/TrustStore&gt;<br/> &nbsp;&nbsp;&lt;TrustStorePassword&gt;xxxxxxxx&lt;/TrustStorePassword&gt;<br/> &nbsp;&nbsp;&lt;Keystore&gt;/opt/tomcat55/webapps/protectedapp/WEB-INF/guanxi_sp_guard/keystore/guard.jks&lt;/Keystore&gt;<br/> &nbsp;&nbsp;&lt;KeystorePassword&gt;xxxxxxxx&lt;/KeystorePassword&gt;<br/> &nbsp;&nbsp;&lt;CertificateAlias&gt;webservices&lt;/CertificateAlias&gt;<br/> &lt;/Guard&gt;<br/> </code><br/> Our &lt;TOMCAT_HOME&gt; was /opt/tomcat55 and our server's domain name was socket1.leeds.ac.uk - you will need to substitute your own values.</p> <p>At this point it was necessary to start Tomcat and register the alfresco-guard with the SP engine and the IdP as described in <a href="http://www.guanxi.uhi.ac.uk/index.php/Guanxi_localhost_2" target="new">Alistair's tutorial</a>. If you are using the Internet2 IdP, then you will need to supply the IdP with the guard's certificate. Again, Alistair has an <a href="http://www.guanxi.uhi.ac.uk/index.php/Tutorials/Getting_a_Guard_certificate" target="new">excellent tutorial</a> which will guide you through the process.</p> <p><b>Enabling logout</b></p> <p>In order to log out from a session, you need to log out from both the SP and the IdP. Logging out from the SP is easy, because we know where it is. Logging out from the IdP is not as straightforward because we need to call a web service at the IdP. We need to know the URL of this web service - if it exists. The easiest way to find the URL is for the IdP to send it as an attribute. Here is how to set this up using the Guanxi IdP. (We have been using the flat file authenticator/attributor which is the default for Guanxi. If you use a different authenticator, you will need to make the appropriate changes.)</p> <p>We added the following entry to the file &lt;TOMCAT_HOME&gt;/webapps/guanxi_idp/WEB-INF/guanxi_idp/config/shared/custom-arps/arp-providers.xml<br/> <code><br/> &nbsp;&nbsp;&lt;provider name="alfresco-guard"&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;allow&gt;MappedFlatFileAttributesForAlfresco&lt;/allow&gt;<br/> &nbsp;&nbsp;&lt;/provider&gt;<br/> </code><br/> We added the following entry to the file &lt;TOMCAT_HOME&gt;/webapps/guanxi_idp/WEB-INF/guanxi_idp/config/shared/custom-arps/arp-bags.xml<br/> <code><br/> &nbsp;&nbsp;&lt;bag name="MappedFlatFileAttributesForAlfresco"&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="alfresco_ID" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="idWithDomain" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="idEncrypted" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="alfresco_FirstName" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="alfresco_Surname" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="alfresco_Email" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="mail" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="memberOf" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="function" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="alfresco_PersistentID" value="*" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute name="logoutIDP" value="*" /&gt;<br/> &nbsp;&nbsp;&lt;/bag&gt;<br/> </code><br/> Then we edited Harry McDesperate's entry in the file &lt;TOMCAT_HOME&gt;/webapps/guanxi_idp/WEB-INF/guanxi_idp/config/shared/flatfile.xml to:<br/> <code><br/> &nbsp;&nbsp;&lt;User&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Harry McDesperate. The world's most violent programmer! --&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;Username&gt;harrymcd&lt;/Username&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;Password&gt;growl&lt;/Password&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;UserAttribute name="id" value="harrymcd" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;UserAttribute name="firstName" value="Harry" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;UserAttribute name="surname" value="McDesperate" /&gt<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;UserAttribute name="email" value="HarryMcD-AT-jumpingupanddown-DOT-net" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;UserAttribute name="role" value="CheifHeidbanger" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;UserAttribute name="group" value="heidbangers" /&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&lt;UserAttribute name="logoutIDP" value="http://socket1.leeds.ac.uk:8080/guanxi_idp/shibb/logout" /&gt;<br/> &nbsp;&nbsp;&lt;/User&gt;<br/> </code><br/> Our modifications to Kimmo Ilppola's ShibbolethHttpRequestAuthenticationFilter include the following piece of code which picks up the logout service URL from the Shibboleth header and then stores it as a session attribute. It then redirects to the SP logout service, which in turn will chain the IdP logout.<br/> <code><br/> &nbsp;&nbsp;if (req.getMethod()=="POST")<br/> &nbsp;&nbsp;{<br/> &nbsp;&nbsp;&nbsp;&nbsp;for (Enumeration e = req.getParameterNames(); e.hasMoreElements(); )<br/> &nbsp;&nbsp;&nbsp;&nbsp;{<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String name = (String)e.nextElement();<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String value = req.getParameter(name);<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (name.endsWith("act") && value.endsWith("logout"))<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// get the IdP's logout URL - if it's there<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String logoutIDP = req.getHeader( logoutHeaderName );<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((logoutIDP==null) || (logoutIDP.length() <1 ))<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logoutIDP = "NO_IDP_LOGOUT";<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// and store it in the session - <br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// the logout jsp will use this to log out from the IdP<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info("IdP logout is "+logoutIDP);<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpSess.setAttribute("LOGOUT_IDP_URL", logoutIDP);</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// log out of the sp<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info("Logging out of SP");<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String logoutURL = req.getContextPath()+"/guard.guanxiGuardlogout";<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.info("URL is: "+logoutURL); <br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resp.sendRedirect( logoutURL ); <br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br/> &nbsp;&nbsp;&nbsp;&nbsp;}<br/> &nbsp;&nbsp;}<br/> </code><br/> To make Guanxi log out of the IdP, the following code was added to &lt;TOMCAT_HOME&gt;/webapps/alfresco/WEB-INF/guanxi_sp_guard/jsp/logout.jsp<br/> <code><br/> &nbsp;&nbsp;&lt%<br/> &nbsp;&nbsp;&nbsp;&nbsp;HttpSession httpSess = request.getSession();<br/> &nbsp;&nbsp;&nbsp;&nbsp;String logoutURL = (String)httpSess.getAttribute("LOGOUT_IDP_URL");<br/> &nbsp;&nbsp;&nbsp;&nbsp;if ((logoutURL==null) || (logoutURL == "NO_IDP_LOGOUT")) {<br/> &nbsp;&nbsp;%&gt;<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;center&gt;Cannot log out of the IdP.&lt;/center&gt;<br/> &nbsp;&nbsp;&lt;%<br/> &nbsp;&nbsp;&nbsp;&nbsp;} else {<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.sendRedirect( logoutURL );<br/> &nbsp;&nbsp;&nbsp;&nbsp;}<br/> &nbsp;&nbsp;%&gt;<br/> </code><br/> Now when the used clicks on the logout link in Alfresco, he/she is logged out of both the SP and the IdP.</p>