Uploaded image for project: 'OpenAM'
  1. OpenAM
  2. OPENAM-10444

FMSessionProvider should adhere to setCookieToAllDomains setting

    Details

    • Type: Improvement
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 13.5.0
    • Fix Version/s: 13.5.1, 14.0.0
    • Component/s: SAML
    • Environment:
      Windows Server 2012 R2
    • Support Ticket IDs:

      Description

      Short version:
      FMSessionProvider should only set the cookies for the matching cookie domains. This bug can prevent WildFly users from acting as a hosted SAML SP, when having more than one cookie domain configured in the deployment.

      Long version:
      In a setup like:
      IDP1, IDP2 --> RPX:IDP Proxy --> RPS:SP

      RPX (OpenIG) reverse proxies eamx-local.idx.external.com (external FQDN) to iamx-local.internal.com (an internal OpenAM realm /idx FQDN that is configured as an IDP Proxy).

      RPS (OpenIG) reverse proxies eam-local.sp.external.com (external FQDN) to iam-local.internal.com (an internal realm /sp FQDN that is configured as an SP).

      In addition, the COTs between IDP Proxy and SP involve subrealms of /sp (e.g. /sp/app1) and /idx

      Lastly, both OpenAM IDP Proxy and SP are running in the same OpenAM instance and have the following platform cookies configured:

      iplanet-am-platform-cookie-domains=.sp.external.com
      iplanet-am-platform-cookie-domains=.idx.external.com
      iplanet-am-platform-cookie-domains=.internal.com
      

      Good News:
      --------------
      Setting the following advanced site property:

      com.sun.identity.authentication.setCookieToAllDomains=false
      

      Allows us to login to a ldap user in IDP Proxy in a browser tab, and in a different ldap user in SP in another browser tab, and alternate hitting refresh on either tab without issue.

      This works by instead of directly using the following static method in class AuthClientUtils:
      ...Whenever possible, use

      {@link #getCookieDomainsForRequest(HttpServletRequest)}

      instead.
      public static Set<String> getCookieDomains()

      The code leverages the setCookieToAllDomains by indirectly calling in the static method in class AuthClientUtils:

      public static Set<String> getCookieDomainsForRequest(HttpServletRequest request)
      

      The static class method in class AuthClientUtils:

      public static Set<String> getCookieDomains()
      

      AND the static method in class CookieUtils to filter cookie domains obtained from the platform cookies to just those that match the request FQDN:

      public static Set<String> getMatchingCookieDomains(HttpServletRequest request, Collection<String> cookieDomains)
      

      Problem:
      ----------
      Now when doing a SAML2 authentication when the session is created on the IDP Proxy all 3 cookie domains are written for the iPlanetDirectoryPro cookie

      Bottom Line:
      ---------------
      The FMSessionProvider in the following method:

      public Object createSession(Map info, HttpServletRequest request, HttpServletResponse response, StringBuffer targetApplication ) throws SessionException {
      

      Has the following code:

      ... 
      ServiceSchemaManager scm = null; 
      try { 
      scm = new ServiceSchemaManager( 
      "iPlanetAMPlatformService", ssoToken); 
      } catch (Exception e) { 
      throw new SessionException(e); 
      } 
      ServiceSchema platformSchema = null; 
      try { 
      platformSchema = scm.getGlobalSchema(); 
      } catch (SMSException se) { 
      throw new SessionException(se); 
      } 
      setLoadBalancerCookie(request, response); 
      Set cookieDomains = (Set)platformSchema.getAttributeDefaults(). 
      get("iplanet-am-platform-cookie-domains"); 
      String value = ssoToken.getTokenID().toString(); 
      if (cookieDomains.size() == 0) { 
      Cookie cookie = 
      CookieUtils.newCookie(cookieName, value, "/"); 
      CookieUtils.addCookieToResponse(response, cookie); 
      } else { 
      Iterator it = cookieDomains.iterator(); 
      Cookie cookie = null; 
      String cookieDomain = null; 
      while (it.hasNext()) { 
      cookieDomain = (String) it.next(); 
      if (debug.messageEnabled()) { 
      debug.message("cookieName=" + cookieName); 
      debug.message("value=" + value); 
      debug.message("cookieDomain=" + cookieDomain); 
      } 
      cookie = CookieUtils.newCookie( 
      cookieName, value, 
      "/", cookieDomain); 
      CookieUtils.addCookieToResponse(response, cookie); 
      } 
      } 
      ...
      

      Which repeats A LOT of code of getCookieDomains and moreover could be largely refactored to leverage code either directly or a copy of the static method in class AuthClientUtils:
      public static Set<String> getCookieDomainsForRequest(HttpServletRequest request)

      Solution:
      ----------
      The FAMSessionProvider SHOULD be enhanced to either leverage the functionality of the existing property setCookieToAllDomains or a newly constructed similar property specifically for FAM (i.e. SAML2).

      Our current architecture and implementation is highly dependent on a FIX for this problem otherwise this will cause our architecture to be invalid and create a large set of issues as we would need to split the IDP Proxy and the SP into separate OpenAM instances with separate Configuration stores and separate CTS stores and our HA deployment would involve 2X the number of servers or server instances.

      Moreover, fixing this would fill a gap that appears to have been perhaps omitted because I suspect other clients have not pushed the envelope on OpenAM with SAML2 the way this architecture is doing so. Regardless a fix for this would make the FAM and AM components behave in a similar manner when it came to shared OpenAM instances and multiple AM FQDN/realm deployments.

      Quick (and Dirty) Fix:
      -----------------------
      Leverage the static method getMatchingCookieDomains in CookieUtils in FMSessionProvider.java as follows:

      ... 
      setLoadBalancerCookie(request, response); 
      Set cookieDomains = (Set)platformSchema.getAttributeDefaults(). 
      get("iplanet-am-platform-cookie-domains"); 
      
      // START - ADDED CODE 
      // 
      cookieDomains = CookieUtils.getMatchingCookieDomains(request, cookieDomains); 
      // 
      // END - ADDED CODE 
      
      String value = ssoToken.getTokenID().toString(); 
      if (cookieDomains.size() == 0) { 
      ...
      

      I have compiled and tested the above and indeed during a SAMLv2 authentication the SAMLv2 mechanism only writes cookies based on the incoming http request.

      I say Quick and Dirty as the FM and AM have traditionally been kept separate and in this case the above has the OpenFM-13.5.0.jar leveraging code in the openam-core-13.5.0.jar which is most likely not desirable however a simple refactoring activity of the FAM code to leverage similar AuthClientUtils/CookieUtils code should be a very simple undertaking.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                peter.major Peter Major [X] (Inactive)
                Reporter:
                nikolaosinlight Nikolaos Giannopoulos [X] (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: