In our project, we have successfully implemented SAML (Security Assertion Markup Language) 2.0 with our Alfresco Content Service v5.2.0. We use AD(Active Directory) to sync users and groups into Alfresco System.
Installation
Installation was straight forward. Just following the guides from Alfresco https://docs.alfresco.com/saml/concepts/saml-overview.html.
Before Implementing, make sure you have gone through the supported-platforms by Alfresco Content Service and download the correct versions of amps. https://docs.alfresco.com/5.2/concepts/supported-platforms-ACS.html.
We have installed the following amps:
- alfresco-saml-repo-1.0.3.amp
- alfresco-saml-share-1.0.3.amp
Configuration
There are several ways to configure SAML:
- Admin Console (Enterprise Admin Tool)
- JMX settings
- alfresco-global.properties
- New subsystem
We chose to do the configuration by adding a subsystem (SAML) under ../tomcat/shared/classes/alfresco/extension/subsystems/SAML.
There are some reasons, we decided to use properties-files over JMX console.
- First of all, its easier to transfer configurations between environments(development-test-production) by using properties-files.
- The reason to choose Subsystem instead of alfresco-global.properties is that we have different settings between Share, REST-API and AOS. In REST-API we want saml.sp.isEnforced=false, but in the others saml.sp.isEnforced=true.
Configuration files and settings
Generate the certificate or ask your organization to provide the signed jks certificate to validate. Add the below attributes in alfresco-global.properties file:
saml.keystore.location=f:/alfresco/${alfresco.version}/alf_data/keystore/saml/test-saml.keystore.jks
saml.keystore.keyMetaData.location=f:/alfresco/alf_data/keystore/saml/test-saml.keystore-passwords.properties
Update the test-saml.keystore-passwords.properties file to look like
aliases=te-c1c66075-f6e3-6fe3-b3e1-rtr
keystore.password=password123
te-c1c66075-f6e3-6fe3-b3e1-rtr.password=password123
Note: Use keytool to convert pfx certificate to jks certificate if your organization does not provide jks, in our case we did this.
Create a subsystem/SAML directory if it does not exists in extension directory.
subsystem/SAML directory will have the configurations for repository and share application. Inline-style:
The share folder will store the configuration file for share, saml-custom-share-sp.properties. The repository folder will have two sub-folders, aos and rest-api. The aos folder will store the configuration file for aos, saml-custom-aos-sp.properties. And the rest-api folder will store the configuration file for rest-api, saml-custom-rest-api-sp.properties.
Update and provide the SAML configuration for share, repository and aos properties as below.
saml-custom-share-sp.properties:
# The SAML attribute (or 'Subject/NameID' for SAML subject NameID) to map to the Alfresco user's ID
saml.sp.user.mapping.id=Subject/NameID
# Whether or not SAML is enabled for the service provider
saml.sp.isEnabled=true
# Whether or not SAML login is enforced
saml.sp.isEnforced=true
# IdP description if you choose to enforce SAML login
saml.sp.idp.description=WAM-TEST
# IdP URL to which the Authentication Request from Alfresco is posted for the service provider
saml.sp.idp.sso.request.url=https://mycompany.com/FIM/sps/alfresco/saml20/login
# IdP URL to which a logout *request* from Alfresco is posted when logging out from the service provider
saml.sp.idp.slo.request.url=https://mycompany.com/FIM/sps/alfresco/saml20/slo
# IdP URL to which a logout *response* from Alfresco is posted when receiving a logout request from your IdP for the service provider
#saml.sp.idp.slo.response.url=
# Path to the certificate used to validate the requests and responses from the IdP
saml.sp.idp.certificatePath=f:/alfresco/5.2.0/alf_data/keystore/saml/alfresco-cert.cer
# Entity identification (issuer) for the service provider. Some IdPs may use this to determine which SP connection to use.
saml.sp.idp.spIssuer=https://alfresco.mycompany.com
saml-custom-rest-api-sp.properties:
# The SAML attribute (or 'Subject/NameID' for SAML subject NameID) to map to the Alfresco user's ID
saml.sp.user.mapping.id=Subject/NameID
# Whether or not SAML is enabled for the service provider
saml.sp.isEnabled=true
# Whether or not SAML login is enforced
saml.sp.isEnforced=false
# IdP description if you choose to enforce SAML login
saml.sp.idp.description=WAM-TEST
# IdP URL to which the Authentication Request from Alfresco is posted for the service provider
saml.sp.idp.sso.request.url=https://mycompany.com/FIM/sps/alfresco/saml20/login
# IdP URL to which a logout *request* from Alfresco is posted when logging out from the service provider
saml.sp.idp.slo.request.url=https://mycompany.com/FIM/sps/alfresco/saml20/slo
# IdP URL to which a logout *response* from Alfresco is posted when receiving a logout request from your IdP for the service provider
#saml.sp.idp.slo.response.url=
# Path to the certificate used to validate the requests and responses from the IdP
saml.sp.idp.certificatePath=f:/alfresco/5.2.0/alf_data/keystore/saml/alfresco-cert.cer
# Entity identification (issuer) for the service provider. Some IdPs may use this to determine which SP connection to use.
saml.sp.idp.spIssuer=https://alfresco.mycompany.com/rest-api
saml-custom-aos-sp.properties:
# The SAML attribute (or 'Subject/NameID' for SAML subject NameID) to map to the Alfresco user's ID
saml.sp.user.mapping.id=Subject/NameID
# Whether or not SAML is enabled for the service provider
saml.sp.isEnabled=true
# Whether or not SAML login is enforced
saml.sp.isEnforced=true
# IdP description if you choose to enforce SAML login
saml.sp.idp.description=WAM-TEST
# IdP URL to which the Authentication Request from Alfresco is posted for the service provider
saml.sp.idp.sso.request.url=https://mycompany.com/FIM/sps/alfresco/saml20/login
# IdP URL to which a logout *request* from Alfresco is posted when logging out from the service provider
saml.sp.idp.slo.request.url=https://mycompany.com/FIM/sps/alfresco/saml20/slo
# IdP URL to which a logout *response* from Alfresco is posted when receiving a logout request from your IdP for the service provider
#saml.sp.idp.slo.response.url=
# Path to the certificate used to validate the requests and responses from the IdP
saml.sp.idp.certificatePath=f:/alfresco/5.2.0/alf_data/keystore/saml/alfresco-cert.cer
# Entity identification (issuer) for the service provider. Some IdPs may use this to determine which SP connection to use.
saml.sp.idp.spIssuer=https://alfresco.mycompany.com/aos
Update the custom-share-config file to implement SAML on share:
<config evaluator="string-compare" condition="CSRFPolicy" replace="true">
<filter>
<!-- SAML SPECIFIC CONFIG - START -->
<!-- Since we have added the CSRF filter with filter-mapping of "/*" we will catch all public GET's 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 -->
</filter>
</config>
SAML dance
To connect to backend API’s using SAML-based authentication, you do “the SAML-dance”.
To authenticate: http://alfresco.mycompany.com/alfresco/service/saml/-default-/rest-api/authenticate
Response:
*entry:
id: "TICKET_4d5f271531755e13302d00774290ab2c0ecfd0c9"
userId: "test_user"*
Call the repo-api using the ticket from response above: http://alfresco.mycompany.com/alfresco/s/api/sites?alf_ticket=TICKET_4d5f271531755e13302d00774290ab2c0ecfd0c9
See https://docs.alfresco.com/saml/concepts/develop-saml.html for more details.
Problems & solutions
We have encountered some problems after the deploy of SAML-based authentication.
One problem is with View In Browser when using Internet Explorer. If you are in Document Library and try to do a View In Browser on a Microsoft Office file, the Office program will show you a login dialog. If you click cancel twice the document will open just fine. This is a known issue.
Share/proxy URLs
When integrating with Alfresco, you will notice that if you try to connect to a repo-api through share/proxy you will not get authenticated by SAML. We have lot of users that are creating links to documents from our Intranet, they are taking the download URL from Alfresco share. (URL includes share/proxy). These links will not work any more if the users isn’t already having a session in the browser. We have created a custom share-api that authenticate the user with SAML and redirect to the original URL.