Problem

We try to access a Confluence page with a link that contains a '#' in the URL. Access to the URL is possible, however, the SAML Single Sign On plugin ignores everything after the '#'.

Example

We created an anchor (called Boulder-Techniken) inside the page, which can be hyperlinked. To insert the anchor link, we have to type #Boulder-Techniken

https://<base-URL>/display/SPOR/Bouldern#Boulder-Techniken
CODE

Cause

The problem exists because the fragment (the part after and including the # character) is not sent to the server. There is an Atlassian ticket about that https://jira.atlassian.com/browse/CONFSERVER-27175 and they decided to not do anything about it.

Solution

Instrument the IdP selection page with some JavaScript that adds the fragment again as a workaround. In a single-Identity provider scenario, this adds of course an additional step you'd normally not need. But is the only way to work around the problem. We'll explain below how to make that change as less disruptive to the users as possible.

  • enable the IdP Selection page first
  • Go to SAML Single Sign On Plugin Configuration → Page Templates → IdP Selection Page Template and edit it
  • Replace lines 20 to 24

    #foreach($idp in $idps)
    <p>
        <a href="$idp.ssoUrl">$idp.name</a> $idp.description
    </p>
    #end
    JS

    with the following lines

    #foreach($idp in $idps)
      <p>
        <a class="idplink idpanchor" href="$idp.ssoUrl">$idp.name</a> $idp.description
      </p>
    #end
    JS
  • replace line 16

    var timeout = setTimeout("location.href = '$selectedUrl';", 3000);
    CODE

    with 

    var timeout = setTimeout("location.href = '$selectedUrl' + encodeURIComponent(window.location.hash);", 3000);
    CODE

    This code redirects users automatically to the identity provider they selected last time, provided they didn't clear their cookies. The number at the end is how long it takes until that happens, in milliseconds. This makes only really sense if you really have multiple IdPs so that you have a chance to change the selection again. If you only have one, you could set that even to 0, for an almost immediate redirect.

  • Add the following script code after line 5 in the head of the template 

    <script>
      AJS.toInit(function(){
        AJS.$("a.idpanchor").each(function() {
          var idpAnchor = $(this);
          var prevHref = idpAnchor.attr('href');
          idpAnchor.attr('href', prevHref + encodeURIComponent(window.location.hash));
        });
      });
    </script>
    CODE
  • remove the following template lines if you don't want to show the option to log in with a username and password

    #if($loginurl)      <p>
        <a href="$loginurl">Login with username and password</a>
        </p>
    #end
    CODE
  • optional: remove/ change the page template title (in the template default line 3) and/ or header (in the template default line 12)

    <title>Select Identity Provider</title><h1>Select your Identity Provider</h1>
    CODE

After saving the configuration you'll see the selection page instead of being redirected immediately to the Confluence page after SSO. Clicking the link will finally take you to Confluence while preserving the fragments.