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.

Configurationfiles 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: alt text

The share folder will store the configurationfile for share, saml-custom-share-sp.properties. The repository folder will have two subfolders, aos and rest-api. The aos folder will store the configurationfile for aos, saml-custom-aos-sp.properties. And the rest-api folder will store the configurationfile 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

Logout: http://alfresco.mycompany.com/alfresco/service/saml/-default-/rest-api/logout-request?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.

Fredrik Kasström

Alfresco Consultant at Redpill Linpro

Fredrik started at Redpill Linpro in 2015. He is specialised in the ECM area.

Local development environment for OpenShift

When developing software it makes sense to be able to work on local files, while the source code should be served from a controlled environment (a container) to prevent pollution of the developer workstation.

In this article I will describe the evolution of a development workflow for deploying applications on OpenShift. The ultimate goal is to make it possible to maximize dev/prod parity, while minimizing the idle time in the change/test cycle.

... [continue reading]

OpenShift with Jenkins for dev/prod parity

Published on November 09, 2018

Getting started with Terraform

Published on August 14, 2018