Alfresco is an ECM/BPM software.
Since 4.0 release, it offers an easy way to configure SSO thanks to authentication subsystems.
Authentication against LL::NG can be done trough:
You need to find the following files in your Alfresco installation:
alfresco-global.properties
(ex: tomcat/shared/classes/alfresco-global.properties
)share-config-custom.xml
(ex: tomcat/shared/classes/alfresco/web-extension/share-config-custom.xml
)The first will allow one to configure SSO for the alfresco webapp, and the other for the share webapp.
Edit first alfresco-global.properties
and add the following:
### SSO ### authentication.chain=external1:external external.authentication.enabled=true external.authentication.defaultAdministratorUserNames= external.authentication.proxyUserName= external.authentication.proxyHeader=Auth-User external.authentication.userIdPattern=
Edit then share-config-custom.xml
and uncomment the last part. In the <endpoint>
, change <connector-id>
value to alfrescoHeader
and change the <userHeader>
value to Auth-User
:
<config evaluator="string-compare" condition="Remote"> <remote> <keystore> <path>alfresco/web-extension/alfresco-system.p12</path> <type>pkcs12</type> <password>alfresco-system</password> </keystore> <connector> <id>alfrescoCookie</id> <name>Alfresco Connector</name> <description>Connects to an Alfresco instance using cookie-based authentication</description> <class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class> </connector> <connector> <id>alfrescoHeader</id> <name>Alfresco Connector</name> <description>Connects to an Alfresco instance using header and cookie-based authentication</description> <class>org.alfresco.web.site.servlet.SlingshotAlfrescoConnector</class> <userHeader>Auth-User</userHeader> </connector> <endpoint> <id>alfresco</id> <name>Alfresco - user access</name> <description>Access to Alfresco Repository WebScripts that require user authentication</description> <connector-id>alfrescoHeader</connector-id> <endpoint-url>http://localhost:8080/alfresco/wcs</endpoint-url> <identity>user</identity> <external-auth>true</external-auth> </endpoint> </remote> </config>
You need to restart Tomcat to apply changes.
Just set the Auth-User
header with the attribute that carries the user login, for example $uid
.
Set the default rule to what you need.
Other rules:
^/share/res ⇒ unprotect
^/share/page/dologout ⇒ logout_app_sso
Install SAML Alfresco module package:
cp alfresco-saml-repo-1.0.1.amp <ALFRESCO_HOME>/amps cp alfresco-saml-share-1.0.1.amp <ALFRESCO_HOME>/amps_share ./bin/apply_amp.sh
Generate SAML certificate:
keytool -genkeypair -alias my-saml-key -keypass change-me -storepass change-me -keystore my-saml.keystore -storetype JCEKS
Export the keystore:
mv my-saml.keystore alf_data/keystore cat <<EOT > alf_data/keystore/my-saml.keystore-metadata.properties aliases=my-saml-key keystore.password=change-me my-saml-key.password=change-me EOT cat <<EOT >> tomcat/shared/classes/alfresco-global.properties saml.keystore.location=\${dir.keystore}/my-saml.keystore saml.keystore.keyMetaData.location=\${dir.keystore}/my-saml.keystore-metadata.properties EOT
Edit then share-config-custom.xml
:
... <config evaluator="string-compare" condition="CSRFPolicy" replace="true"> <!-- If using https make a CSRFPolicy with replace="true" and override the properties section. Note, localhost is there to allow local checks to succeed. I.e. <properties> <token>Alfresco-CSRFToken</token> <referer>https://your-domain.com/.*|http://localhost:8080/.*</referer> <origin>https://your-domain.com|http://localhost:8080</origin> </properties> --> <filter> <!-- SAML SPECIFIC CONFIG - START --> <!-- Since we have added the CSRF filter with filter-mapping of "/*" we will catch all public GET to avoid them having to pass through the remaining rules. --> <rule> <request> <method>GET</method> <path>/res/.*</path> </request> </rule> <!-- Incoming posts from IDPs do not require a token --> <rule> <request> <method>POST</method> <path>/page/saml-authnresponse|/page/saml-logoutresponse|/page/saml-logoutrequest</path> </request> </rule> <!-- SAML SPECIFIC CONFIG - STOP --> <!-- EVERYTHING BELOW FROM HERE IS COPIED FROM share-security-config.xml --> <!-- Certain webscripts shall not be allowed to be accessed directly form the browser. Make sure to throw an error if they are used. --> <rule> <request> <path>/proxy/alfresco/remoteadm/.*</path> </request> <action name="throwError"> <param name="message">It is not allowed to access this url from your browser</param> </action> </rule> <!-- Certain Repo webscripts should be allowed to pass without a token since they have no Share knowledge. TODO: Refactor the publishing code so that form that is posted to this URL is a Share webscript with the right tokens. --> <rule> <request> <method>POST</method> <path>/proxy/alfresco/api/publishing/channels/.+</path> </request> <action name="assertReferer"> <param name="referer">{referer}</param> </action> <action name="assertOrigin"> <param name="origin">{origin}</param> </action> </rule> <!-- Certain Surf POST requests from the WebScript console must be allowed to pass without a token since the Surf WebScript console code can't be dependent on a Share specific filter. --> <rule> <request> <method>POST</method> <path>/page/caches/dependency/clear|/page/index|/page/surfBugStatus|/page/modules/deploy|/page/modules/module|/page/api/javascript/debugger|/page/console</path> </request> <action name="assertReferer"> <param name="referer">{referer}</param> </action> <action name="assertOrigin"> <param name="origin">{origin}</param> </action> </rule> <!-- Certain Share POST requests does NOT require a token --> <rule> <request> <method>POST</method> <path>/page/dologin(\?.+)?|/page/site/[^/]+/start-workflow|/page/start-workflow|/page/context/[^/]+/start-workflow</path> </request> <action name="assertReferer"> <param name="referer">{referer}</param> </action> <action name="assertOrigin"> <param name="origin">{origin}</param> </action> </rule> <!-- Assert logout is done from a valid domain, if so clear the token when logging out --> <rule> <request> <method>POST</method> <path>/page/dologout(\?.+)?</path> </request> <action name="assertReferer"> <param name="referer">{referer}</param> </action> <action name="assertOrigin"> <param name="origin">{origin}</param> </action> <action name="clearToken"> <param name="session">{token}</param> <param name="cookie">{token}</param> </action> </rule> <!-- Make sure the first token is generated --> <rule> <request> <session> <attribute name="_alf_USER_ID">.+</attribute> <attribute name="{token}"/> <!-- empty attribute element indicates null, meaning the token has not yet been set --> </session> </request> <action name="generateToken"> <param name="session">{token}</param> <param name="cookie">{token}</param> </action> </rule> <!-- Refresh token on new "page" visit when a user is logged in --> <rule> <request> <method>GET</method> <path>/page/.*</path> <session> <attribute name="_alf_USER_ID">.+</attribute> <attribute name="{token}">.+</attribute> </session> </request> <action name="generateToken"> <param name="session">{token}</param> <param name="cookie">{token}</param> </action> </rule> <!-- Verify multipart requests from logged in users contain the token as a parameter and also correct referer & origin header if available --> <rule> <request> <method>POST</method> <header name="Content-Type">multipart/.+</header> <session> <attribute name="_alf_USER_ID">.+</attribute> </session> </request> <action name="assertToken"> <param name="session">{token}</param> <param name="parameter">{token}</param> </action> <action name="assertReferer"> <param name="referer">{referer}</param> </action> <action name="assertOrigin"> <param name="origin">{origin}</param> </action> </rule> <!-- Verify that all remaining state changing requests from logged in users' requests contains a token in the header and correct referer & origin headers if available. We "catch" all content types since just setting it to "application/json.*" since a webscript that doesn't require a json request body otherwise would be successfully executed using i.e."text/plain". --> <rule> <request> <method>POST|PUT|DELETE</method> <session> <attribute name="_alf_USER_ID">.+</attribute> </session> </request> <action name="assertToken"> <param name="session">{token}</param> <param name="header">{token}</param> </action> <action name="assertReferer"> <param name="referer">{referer}</param> </action> <action name="assertOrigin"> <param name="origin">{origin}</param> </action> </rule> </filter> </config> ...
Configure SAML service provider using the Alfresco admin console (/alfresco/s/enterprise/admin/admin-saml).
Set the following parameters:
To finish with Alfresco configuration, tick the “Enable SAML authentication (SSO)” box.
Configure SAML service and set a certificate as signature public key in metadata.
Export Alfresco SAML Metadata from admin console and import them in LL::NG.
In the authentication response option, set:
And you can define these exported attributes: