Preserving URL anchor fragments on login form submission


New CAS documentation site

CAS documentation has moved over to jasig.github.io/cas, starting with CAS version 4.x. The wiki will no longer be maintained. For the most recent version of the documentation, please refer to the aforementioned link.


Anchors/fragments are lost across redirects, as the server-side handler of the form post ignores the client-side anchor, unless appended to the form POST url. See https://jira.springsource.org/browse/SEC-1067 for more details. This feature is needed if you want a CAS-authenticated application to be able to use anchors/fragments when bookmarking. If the user has a bookmark with an anchor/fragment in it and is redirected to the login page when attempting to navigate to the link with the anchor, the anchor will be lost upon redirect without this patch.


Let's assume you go to www.example.com/index#someAnchor, but you have not been authenticated. The container will automatically redirect you to your login page, but the browser will maintain the anchor/fragment from the original link: www.example.com/login#someAnchor. With the change demonstrated below, it is ensured that the anchor is not lost upon the form post so that it can be re-applied by the browser to the redirect URL issued by the server upon successful login. Because anchors/fragments are client-side pieces maintained by the browser and NEVER transmitted as part of the HTTP POST to the server, this is the only way to maintain the anchor/fragment (without putting it in the POST data and modifying the server to restore it).

 

Browser Support

Note that this will only help FireFox/Chrome/Opera/IE 10 and not Safari and IE 9 and below: http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx. This has nothing to do with the code itself and more to do with how the browsers handle persisting fragments/anchors across 302 redirect responses from servers.

Changes to cas.js:

/**
 * Prepares the login form for submission by appending any URI
 * fragment (hash) to the form action in order to propagate it
 * through the re-direct (i.e. store it client side).
 * @param form The login form object.
 * @returns true to allow the form to be submitted.
 */
function prepareSubmit(form) {
    // Extract the fragment from the browser's current location.
    var hash = decodeURIComponent(self.document.location.hash);

    // The fragment value may not contain a leading # symbol
    if (hash && hash.indexOf("#") === -1) {
        hash = "#" + hash;
    }
  
    // Append the fragment to the current action so that it persists to the redirected URL.
    form.action = form.action + hash;
    return true;
}

 

Changes to casLoginView.jsp:

<form:form method="post" id="fm1" cssClass="fm-v clearfix" commandName="${commandName}" htmlEscape="true" onsubmit="return prepareSubmit(this);">