cancel
Showing results for 
Search instead for 
Did you mean: 

SSO with OpenAM

smcardle
Champ in-the-making
Champ in-the-making
Hi All

I am using OpenAM as our authentication server and need to get Alfresco and Share community 4.0.d involved in the same architecture.

However, I am having serious issues here. Usually when OpenAM (previously OpenSSO) is configured to work with web application we do the following :
1. add the OpenAM filter to the web.xml file
2. configure some policies on OpenAM for the protected resources on the Web Application being SSO'ed.
3. Add references to the login page, login error page and logout page.

When a protected resource is then requested in the application, the OpenAM filter will redirect the user to the OpenAM login page, the use logs in and then the application is able to use the HttpServletRequest to get the user principal and check isUserInRole().

However, it seems there is another way to do this with Alfresco and Share but I cannot understand how they would be able to redirect to the OpenAM application when I enter the URL http://<server>:<port>/share into the browser address bar. !!!!

Basically I never want to see the Share or Alfresco login pages. We always want our users ONLY in OpenAM and force Alfresco and Share to trust them as externally Authenticated. Alfresco would then create a user of it's own but the user record will be externally managed i.e. passwords etc are not managed by Alfresco.

From all the SSO options I can see in the Documentation this scenario does not seem to be covered.

There was an old integration for Alfresco with OpenSSO from sourcesence but this is not a good option in our case as it uses the concept of the OpenSSO AM properties file for the agent configuration instead of the remote server agent configuration.

So, the question is….. Can I configure Alfresco and Share so that they redirect to OpenAM and trust all authenticated users using out of the box functionality and configuration OR do I have to create my own SSOAthentication Filter for Alfresco and Share that uses the OpenAM SDK to get them to participate in our SSO configuration?

If I have to do this, what is Share expecting to see in the way of cookies or headers such that it will not present it's own login page?

I can't believe that nobody has already done this with Alfresco. OpenAM (OpenSSO) is a widely used and excellent AAA SSO Solution.

Regards

Steve
21 REPLIES 21

lotharmärkle
Champ in-the-making
Champ in-the-making
These are all really good questions.
It would be clearly possible to create an OpenAM SSO Authenticator for Alfresco and this would be a great thing, because IAM is still/always a very hot topic for enterprises of all size.
I think it does not exists, because Alfresco can do LDAP, Kerberos and NTLM SSO ootb - and these are systems provisioned by OpenAM then.

What would be the benefits of an Alfresco <-> OpenAM integration regarding authorization?

Regards,
  lothar

medb
Champ in-the-making
Champ in-the-making
I'm also looking for Alfresco integration with OpenAM, preferably using SAML 2.0 protocol.
Any help or suggestions will be greatly appreciated.

P.S. Benefit of such an integration for me is that in such a case I don't need to pass username/password when talking to Alfresco via the CMIS interface (If I have understood the SSO correctly).

smcardle
Champ in-the-making
Champ in-the-making
@lothar

The benefit of this is that We already use OpenAM for all of our other application in the stack.

The problem with LDAP etc is that you still need to login i.e. Share is connected to LDAP but you still get the Share login page. NTLM just means that the browser will pass on the current logged in user for the machine.

As we don't use the NTLM user/password for our other systems this is out of the equation. For LDAP it's pretty much the same.

OpenAM can use multiple user stores, including LDAP but this would only authenticate us to the LDAP system

I think I have found a method for OpenAM integration anyway, just haven't finished configuring yet. This solution uses the Alfresco 4.1.a release where a couple of new SSO classes have been added that can authenticate using either a Cookie or Request Header called SsoUserHeader (or whatever you want to call it in the algfresco-global-properties file.

OpenAM can be configured such that after authentication the redirect to the application is passed either a custom Cookie or Header, in my case SsoUserHeader containing the uid of the user (Our OpenAM user store is LDAP).

Looking at the code this would seem to be the way to go. You cannot fool Alfresco by creating a cookie on the client called SsoUserHeader because if going via OpenAM, OpenAM will remove all such cookies and headers and not pass them on to the target application during the redirect, unless otherwise instructed.

As soon as I have managed to get 4.1.a running and my OpenAM polices configured I will test it out and post the results. I may also write a wiki on how to configure Share with OpenAM.

The other side of the coin is Authorisation. Here I want to create a set of groups in OpenAM for Alfresco, like GROUP_myGroup and have Alfresco use the JEE isUserInRole(…) method to determine if they have privilege to do so, because I don't want to have to also setup Groups and Users  and map them in Alfresco as well as the Groups and Users management we have in OpenAM. However, this will be a little more difficult as it will require synchronising the two systems as Alfresco requires these internally for it's Authorisation mechanisms. Initially we will live with the duplication of assigning groups to externally managed users in the Alfresco UI

Steve

gopals
Champ in-the-making
Champ in-the-making
@Steve

We are also trying to integrate Alfresco community edition with OpenAM but, no luck so far. It would be a great help if you can post some pointers at your convenience.

Thanks in advance,
Gopal

smcardle
Champ in-the-making
Champ in-the-making
Hi Gopal

The good news is that I now have a fully integrated OpenAM Alfresco installation.

NOTE: This works with Alfresco 4.1.a only as there are new SSO classes defined that are required… It may well be possible to retrofit this to older versions of Alfresco (perhaps an Alfresco DEV can tell us what jars need updating to do this) but I will not be doing this for our installation….

The OpenAM only integrates with Share in our environment and then the usual Share / Alfresco remote communication takes place.

I don't know how you have setup your OpenAM but we configure the agents to get their configuration from the OpenAM server. If this is the same way you configure this then I can help you out.

I will assume you have installed OpenAM and have the J2EE agent installed and setup correctly (I will not cover this in the following text so you should be at a stage where the OpenAM example J2EE application runs)

The Share application states everywhere that you should not need to change the web.xml file but for OpenAM /OpenSSO integration this is necessary otherwise there is no way to redirect the login to the OpenAM server.

1. Configure your OpenAM agent
  a. Log into OpenAM as the admin user and navigate to "Access Control -> (Your Realm) - where in my case your realm is the top level realm
  b. Select Policies -> New Policy
  c. Enter Share as the policy name and then create 2 new URL Policy agent rules
  d. 1st Rule - Name Share ALL - GET & POST selected - Resource Name = http://<your share server>:<share port>/share/*
  e. 2nd Rule - Name Share With Parameters - GET & POST selected - Resource Name = http://chma-qa115.chelmer.co.nz:8080/share/*?*
  f. Add a subjects - All Authenticated Users
  g. Now select Agents -> J2EE - > (your J2EE agent)
  h. Select the Application tab
  i. Login Processing -> Login Form URI - add /share/page/dologin
  j. Logout Processing -> Application Logout URL - add Map Key = share - Corresponding Map Value = /share/page/dologout
  k. Not Enforced URI Processing - Add 2 entries - /share and /share/
  l. Profile Attributes Processing - Select HTTP_HEADER and add Map Key = uid - Corresponding Map Value = SsoUserHeader (This is what I called my header in the alfresco-global.properties file - see below)

# Auth chain
authentication.chain=external1:external,alfrescoNtlm1:alfrescoNtlm
alfresco.authentication.allowGuestLogin=true

# SSO settings
external.authentication.enabled=true
external.authentication.defaultAdministratorUserNames=admin
external.authentication.proxyUserName=
external.authentication.proxyHeader=SsoUserHeader

NOTE- It does not seem possible to configure SSO where the Guest login has been disabled. There are webscripts used on the Alfresco repository that need guest login.

That concludes the setup for Alfresco and OpenAM

For Share you need to have the following section uncommented in your share-config-custom.xml

   <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>SsoUserHeader</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://<alfresco server>:<alfresco port>/alfresco/wcs</endpoint-url>
            <identity>user</identity>
            <external-auth>true</external-auth>
         </endpoint>
      </remote>
   </config>

Notice I am not using the SSL cert and in my alfrescoHeader connector I have used SsoUserHeader (as setup in OpenAM) and the endpoint uses the alfrescoHeader connector

Now you need to add the OpenAM filter to the Share web.xml file

Add the following filter just before the Share SSO authentication support filter

       <filter>
            <filter-name>Agent</filter-name>
            <filter-class>com.sun.identity.agents.filter.AmAgentFilter</filter-class>
        </filter>

Add the following filter mapping to the filter-mapping section

        <filter-mapping>
            <filter-name>Agent</filter-name>
            <url-pattern>/*</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>INCLUDE</dispatcher>
            <dispatcher>FORWARD</dispatcher>
            <dispatcher>ERROR</dispatcher>
        </filter-mapping>

This makes sure ALL pages go through the OpenAM authentication filter before the Share SSO filter. OpenAM will set the SsoUserHeader to the UID of the currently authenticated user and Share will use this and then perform SSO with the Alfresco Repository


Now when you select the Share URL you will be redirected to the OpenAM login page to authenticate. OpenAM will set the SsoUserHeader on the request that is forwarded to the Share SSO filter and all should be good.

You do not need to create your users in Alfresco as the SSO authentication implicitly trusts externally authenticated users and will create a user and a home space in Alfresco for you. The user it creates will have no option for changing password…

CAVEAT : Even though I have an authentication chain of external and then alfresco NTLM the alfresco NTLM will never be usable as you cannot bypass the authentication mechanism for OpenAM. What normally would happen is that it will say are you externally authenticated? if not see if your are a user in Alfresco. The second part of this process will not work with this setup as ALL users must be defined in OpenAM.
Because of this, if you want and Alfresco user to login via Share, you will need to make one of your OpenAM users a member of the Alfresco Admin group. If you don't want to do this then no worries as you can always login directly to the Alfresco Repo browser as any internally defined Alfresco user, including the admin user.

I hope this helps you to get your configuration working

Regards

Steve

jainmcs03
Champ in-the-making
Champ in-the-making
@Steve

I got a SSO with openAM successfully as per instructions above, but when i try to logout from the share, its not responding which means redirect not working.

Below the logs for reference, please let me know if we need special handling for logout for share. Thanks,


ApplicationFilterChain : Inside doFilter
ApplicationFilterChain : doFilter : IS_SECURITY_ENABLED : false
ApplicationFilterChain : printstatement : req.getHeaderNames() org.apache.tomcat.util.http.NamesEnumerator@37e696b6
ApplicationFilterChain : printstatement : req.getHeaderNames() : host
ApplicationFilterChain : printstatement : req.getHeaderNames() : connection
ApplicationFilterChain : printstatement : req.getHeaderNames() : content-length
ApplicationFilterChain : printstatement : req.getHeaderNames() : origin
ApplicationFilterChain : printstatement : req.getHeaderNames() : x-requested-with
ApplicationFilterChain : printstatement : req.getHeaderNames() : alfresco-csrftoken
ApplicationFilterChain : printstatement : req.getHeaderNames() : user-agent
ApplicationFilterChain : printstatement : req.getHeaderNames() : content-type
ApplicationFilterChain : printstatement : req.getHeaderNames() : accept
ApplicationFilterChain : printstatement : req.getHeaderNames() : referer
ApplicationFilterChain : printstatement : req.getHeaderNames() : accept-encoding
ApplicationFilterChain : printstatement : req.getHeaderNames() : accept-language
ApplicationFilterChain : printstatement : req.getHeaderNames() : cookie
ApplicationFilterChain : printstatement : req.getAttributeNames() java.util.Collections$2@3b0a366
ApplicationFilterChain : Inside internalDoFilter
ApplicationFilterChain : Inside internalDoFilter : value of 'pos' : 0
ApplicationFilterChain : Inside internalDoFilter : value of 'n' : 6
ApplicationFilterChain : internalDoFilter - filters.toString() : [Lorg.apache.catalina.core.ApplicationFilterConfig;@c312851
ApplicationFilterChain : internalDoFilter - filterConfig.getFilterName() :Agent Filter
ApplicationFilterChain : internalDoFilter - filter.getClass():class com.sun.identity.agents.filter.AmAgentFilter
ApplicationFilterChain : internalDoFilter : IS_SECURITY_ENABLED : false
ApplicationFilterChain : printstatement : req.getHeaderNames() org.apache.tomcat.util.http.NamesEnumerator@41b77f6e
ApplicationFilterChain : printstatement : req.getHeaderNames() : host
ApplicationFilterChain : printstatement : req.getHeaderNames() : connection
ApplicationFilterChain : printstatement : req.getHeaderNames() : content-length
ApplicationFilterChain : printstatement : req.getHeaderNames() : origin
ApplicationFilterChain : printstatement : req.getHeaderNames() : x-requested-with
ApplicationFilterChain : printstatement : req.getHeaderNames() : alfresco-csrftoken
ApplicationFilterChain : printstatement : req.getHeaderNames() : user-agent
ApplicationFilterChain : printstatement : req.getHeaderNames() : content-type
ApplicationFilterChain : printstatement : req.getHeaderNames() : accept
ApplicationFilterChain : printstatement : req.getHeaderNames() : referer
ApplicationFilterChain : printstatement : req.getHeaderNames() : accept-encoding
ApplicationFilterChain : printstatement : req.getHeaderNames() : accept-language
ApplicationFilterChain : printstatement : req.getHeaderNames() : cookie
ApplicationFilterChain : printstatement : req.getAttributeNames() java.util.Collections$2@760f3076
AmAgentBaseFilter: doFilter: httpRequest.getHeaderNames()  : org.apache.tomcat.util.http.NamesEnumerator@5f36cf87
AmAgentBaseFilter: httpRequest.getHeaderName : host
AmAgentBaseFilter: httpRequest.getHeaderName : connection
AmAgentBaseFilter: httpRequest.getHeaderName : content-length
AmAgentBaseFilter: httpRequest.getHeaderName : origin
AmAgentBaseFilter: httpRequest.getHeaderName : x-requested-with
AmAgentBaseFilter: httpRequest.getHeaderName : alfresco-csrftoken
AmAgentBaseFilter: httpRequest.getHeaderName : user-agent
AmAgentBaseFilter: httpRequest.getHeaderName : content-type
AmAgentBaseFilter: httpRequest.getHeaderName : accept
AmAgentBaseFilter: httpRequest.getHeaderName : referer
AmAgentBaseFilter: httpRequest.getHeaderName : accept-encoding
AmAgentBaseFilter: httpRequest.getHeaderName : accept-language
AmAgentBaseFilter: httpRequest.getHeaderName : cookie
AmAgentBaseFilter: doFilter: httpRequest.getHeader(SsoUserHeader)  : null
AmAgentBaseFilter: doFilter : filter.getClass() :class com.sun.identity.agents.filter.AmFilter
AmFilter: incoming request =>
———————————————————–
HttpServletRequest: class => org.apache.catalina.connector.RequestFacade

   Character Encoding   : null
   Content Lenght      : 0
   Content Type      : application/json
   Locale         : en_US

   Accept Locales:
      en_US
      en

   Protocol      : HTTP/1.1
   Remote Address      : 10.0.2.2
   Remote Host      : 10.0.2.2
   Scheme         : http
   Server Name      : madura.scimergent.com
   Server Port      : 8080
   Is Secure      : false
   Auth Type      : null
   Context Path      : /share
   Cookies:
      JSESSIONID: 6B723091722F67624E85A93240F60C1F
      Alfresco-CSRFToken: ifC6fOgUNX%2bMP7vKvQS7xjPWpddCRMdWTHJ2%2bkXvlcg%3d
      _alfTest: _alfTest
      amlbcookie: 01
      iPlanetDirectoryPro: AQIC5wM2LY4SfcziS59cAnPwKSw5GytkcBgxO5UHlZzV60s.*AAJTSQACMDEAAlNLABQtNzg5MjM2MjEzNzY3NjM3NDczNA..*

   Headers:
      host:
         madura.scimergent.com:8080
      connection:
         keep-alive
      content-length:
         0
      origin:
         http://madura.scimergent.com:8080
      x-requested-with:
         XMLHttpRequest
      alfresco-csrftoken:
         ifC6fOgUNX+MP7vKvQS7xjPWpddCRMdWTHJ2+kXvlcg=
      user-agent:
         Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
      content-type:
         application/json
      accept:
         */*
      referer:
         http://madura.scimergent.com:8080/share/page/user/admin/dashboard
      accept-encoding:
         gzip, deflate
      accept-language:
         en-US,en;q=0.8
      cookie:
         JSESSIONID=6B723091722F67624E85A93240F60C1F; Alfresco-CSRFToken=ifC6fOgUNX%2bMP7vKvQS7xjPWpddCRMdWTHJ2%2bkXvlcg%3d; _alfTest=_alfTest; amlbcookie=01; iPlanetDirectoryPro=AQIC5wM2LY4SfcziS59cAnPwKSw5GytkcBgxO5UHlZzV60s.*AAJTSQACMDEAAlNLABQtNzg5MjM2MjEzNzY3NjM3NDczNA..*
   Method         : POST
   Path Info      : /dologout
   Path Trans      : /opt/tomcat7Alf/webapps/share/dologout
   Query String      : null
   Remote User      : null
   Requested Session ID   : 6B723091722F67624E85A93240F60C1F
   Request URI      : /share/page/dologout
   Servlet Path      : /page
   Session         : true
   User Principal      : <not queried>
   Attributes:
      *** No Attributes ***


———————————————————–

AmFilter: now processing: XSS Detection Task Handler
AmFilter: now processing: Notification Task Handler
AmFilter: now processing: FQDN Task Handler
AmFilter: now processing: Not Enforced List Task Handler
AmFilter: now processing: SSO Task Handler
AmFilter: now processing: Application Logout Handler
AmAgentBaseFilter: doFilter : result :
———————————————————–
FilterResult:
   Status       : REDIRECT
   ProcessResponse       : false
   RedirectURL   : http://madura.scimergent.com:8081/OpenAM-11.0.0/UI/Logout?goto=http%3A%2F%2Fmadura.scimergent.com%3A...
   RequestURL   : null
   RequestHelper:
      null

   Data:
      null

———————————————————–

AmAgentBaseFilter: doFilter : result.getRequestURL() : null
AmAgentBaseFilter: doFilter : result.getRedirectURL() : http://madura.scimergent.com:8081/OpenAM-11.0.0/UI/Logout?goto=http%3A%2F%2Fmadura.scimergent.com%3A...
AmAgentBaseFilter: doFilter : result.isNotEnforced() : false
AmAgentBaseFilter: doFilter : result.getStatus().getIntValue() : 1
…After Redirect….


Regards
Jayendran

gopals
Champ in-the-making
Champ in-the-making
Hi Steve,

Firstly, thank you so much for a detailed write up.  We have similar OpenAM setup and I am going to execute your steps for integration tomorrow.

Thanks again,
Gopal

smcardle
Champ in-the-making
Champ in-the-making
Your welcome.

Please post back if it works for you.

Also, if you have any issues I may be able to help you out but you will need to be explicit with regard to your OpenAM configuration.

Regards

Steve

davdou79
Champ in-the-making
Champ in-the-making
Hi,

I want to use Alfresco 4.2.c with openam. So i use External Authentication.

These is my log file.

2014-02-12 13:19:58,952  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] Authenticating the current user using session based Ticket information.
2014-02-12 13:19:58,952  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] Remote user mapper configured and active. Asking for external user ID.
2014-02-12 13:19:58,952  DEBUG [app.servlet.DefaultRemoteUserMapper] [http-bio-8080-exec-9] Getting RemoteUser from http request.
2014-02-12 13:19:58,952  DEBUG [app.servlet.DefaultRemoteUserMapper] [http-bio-8080-exec-9] The remote user id is: null
2014-02-12 13:19:58,952  DEBUG [app.servlet.DefaultRemoteUserMapper] [http-bio-8080-exec-9] The header user id is: null
2014-02-12 13:19:58,953  DEBUG [app.servlet.DefaultRemoteUserMapper] [http-bio-8080-exec-9] The proxy user name is: null
2014-02-12 13:19:58,953  DEBUG [app.servlet.DefaultRemoteUserMapper] [http-bio-8080-exec-9] Returning null
2014-02-12 13:19:58,953  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] No external user ID in request.
2014-02-12 13:19:58,953  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] SessionUser is: guest
2014-02-12 13:19:58,954  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] Settings the external authentication flag on the session to false
2014-02-12 13:19:58,954  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] We're not in the portal, getting the login bean.
2014-02-12 13:19:58,954  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] Force guest is: false
2014-02-12 13:19:58,954  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] The user is: guest
2014-02-12 13:19:58,954  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] Setting up the request thread.
2014-02-12 13:19:58,955  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] The general locale is : en_US
2014-02-12 13:19:58,955  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] The UserPreferencesBean is : org.alfresco.web.bean.users.UserPreferencesBean@307fe1b5
2014-02-12 13:19:58,957  DEBUG [app.servlet.AuthenticationHelper] [http-bio-8080-exec-9] The content locale is : en_US

If i create a new file test.jsp and add out.print(request.getHeader("ssouser")), i can see my user id.
With Live HTTP Edit, if i define a HTTP HEADER attribut ssouser, it works.
I don't understand why AuthenticationHelper can't get my Header Attribut.

Thanks for your help