Form-Auth removes URI-Fragments

Hi all,

I try to secure my Vaadin-Application with the FORM-Auth of the Jetty9-Servlet Container. With this I can guarantee access to everything in the WebAppDirectory is only allowed to users who are authenticated and also use SSL over the part in the web.xml

Jetty redirects me correclty to the login page but after the loggin I loos the URI-Fragments and therefore I end up on the default page. Whit this the Navigator URI is lost and Bookmarking a Page only wookrs after I logged in succesfully once…

The configuration of the web.xml is similar to your WIKI entry
Creating Secure Vaadin Applications using JEE6
but only covers the WebLayer-Part and uses a login.html instead of a JSP site.

  <security-constraint>
     <web-resource-collection>
          <web-resource-name>Public</web-resource-name>
          <url-pattern>/login/*</url-pattern>
     </web-resource-collection>
     <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
     </user-data-constraint>
  </security-constraint>

  <security-constraint>
     <web-resource-collection>
          <web-resource-name>Private</web-resource-name>
          <url-pattern>/*</url-pattern>
     </web-resource-collection>

     <auth-constraint>
         <role-name>**</role-name>
     </auth-constraint>

     <user-data-constraint>
          <transport-guarantee>CONFIDENTIAL</transport-guarantee>
     </user-data-constraint>
  </security-constraint>

  <login-config>
      <auth-method>FORM</auth-method>
 
      <realm-name>MyUserRealm</realm-name>
      <form-login-config>
          <form-login-page>/login/login.html</form-login-page>
          <form-error-page>/login/login-error.html</form-error-page>
      </form-login-config>
  </login-config>

The login.html is

[code]

[/code]As I said, the authentication works fine, just the URI-Fragments for the Navigator are going missing somehow. Strange part is, that when the login page is displayed, the Fragments are still there...

By default the browser does not send the # fragment to the server , thus the server’s auth module will have no way to redirect you to the full URI ( including # Fragments ) .

You should be able to modify the login form to aquire the current URI (including the # fragment ) and send that in the post as a parameter, and redirect to it instead ( you’ll need a custom auth module for that )…


http://stackoverflow.com/questions/317760/how-to-get-url-hash-from-server-side

Just to confirm tested the aproach and it works.

  1. login.jspx
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">

    <jsp:directive.page contentType="text/html" pageEncoding="UTF-8"/>

    <!-- any content can be specified here, e.g.: -->
    <jsp:element name="html">
        <jsp:body>
            <head >
                <title>Login</title>
                <script>
                    function saveURIFragment(){
                        document.getElementById("j_fragment").setAttribute("value",window.location.hash);
                    }                   
                    window.onload = saveURIFragment; //notice no parenthesis
                </script>
            </head>
            <body >              
                        <form id="loginForm"  method="post" action="j_security_check">
                            <table cellpadding="4" cellspacing="0" border="0" class="login-table">
                                    <tr>
                                        <td colspan="2"><p><strong>Enter your login details below:</strong><br /><br /></p></td>
                                    </tr>
                                    <tr>
                                        <td class="border-right-bottom"><p><strong>Username: </strong></p></td>
                                        <td class="border-bottom"><input type="text" name="j_username" size="25" /></td>
                                    </tr>
                                    <tr>
                                        <td class="border-right"><p><strong>Password: </strong></p></td>
                                        <td><input type="password" size="15" name="j_password" /></td>
                                    </tr>
                                    <tr>
                                        <td colspan="2" style="padding-left: 110px; padding-top: 10px;"><input type="submit" value="Submit"  class="login-button" />  <input type="reset" value="Reset"  class="login-button"/></td>
                                    </tr>
                                    <input id="j_fragment" type="hidden" name="j_fragment" />
                            </table>
                        </form>
            </body>
        </jsp:body>
    </jsp:element>

</jsp:root>
  1. Auth-module saves the original fragment in the session when it authenticates users.
  2. The Ui then extracts the value from the session in init(…) and navigated to the fragment ( if it exists and starts with # ).

Hi Petrus,

thanks for the Info. Did not know, that the URI-Fragments are UserAgent only. Learned something new again.
Just to make sure I got it right, I need to write my own Auth-Module for Jetty so it puts the fragment into the Session or should this be a j_security_check default behavour?

I don’t find any Info on j_fragment…

Sorry for the trouble, but thanks for your help

Marc

Yes you will have to write your own auth-module , I wrote one for Glassfish that is installed via OSGI, but unfortunatly it is quite specific for Glassfish. Basically the module process the j_security_check form variables , j_username and j_password , I simply check for an additional j_fragment post variable and place it in the session with a key that the application then reteives.

Haven’t used jetty latelty , but I think you could do the same with a Auth Realm, just get the source code of the current auth-module/realm you are using , and add the lines to place the j_fragment in the session…

Hi Petrus,

thanks for the help. Worked perfectly for me.
For everyone that needs to do that with Jetty, you can extend the FormAuthenticator-Class from jetty and inject it to the Web-Context over the jetty.xml (for all Context) or the jetty-web.xml (only the Current) Context.

Without that Jetty always loads the default implementation.