15 Feb 2008 6:08 AM #1
This is a new extension to catch and handle the J2EE FORM authentication mechanism inside Ext.Ajax requests, to avoid page reloads.
I tested it against the embedded Tomcat in JBoss v4.2.0-GA application servers. Tested browsers include Firefox v22.214.171.124 and IE6. If you find any bug don't hesitate to contact me.
See the README file inside for details.
24 Jun 2008 7:16 PM #2
Thanks Marte -
This looks good, I just downloaded and browsed the sources. I am in the same camp trying to get J2EE Form Auth to behave with the Ajax world. I will try this tomorrow.
25 Jun 2008 5:49 AM #3
I am actively using the extension, so feel free to contact me if you need to.
25 Jun 2008 8:27 AM #4
Hi Marte -
I just tested the extension and did not have the beginner's luck the first time through
When the browser send an AJAX POST request from an extJS store load:
POST /webmin/jsp/itables/usr-json.jsp HTTP/1.1 ... X-Requested-With: XMLHttpRequest
My question is without modifying the guts of the J2EE server's form auth mechanism how can we avoid the 302 redirect trap ? Since the redirection to /auth page is coming from within J2EE server, its too late for J2EEAuthServlet to intercept the Ajax X-Requested-With header.
How did this work for you?
Last edited by coderobo; 25 Jun 2008 at 8:28 AM. Reason: typo
25 Jun 2008 9:54 AM #5
What J2EE server are you using? It might need special treatment, since I don't recall to get a redirect, but just a normal response from the "/auth" servlet.
By the way, please check that "/auth" is correctly mapped in the web.xml file to a valid servlet. Something like in the packaged example:
<!-- Your security servlet -->
<!-- The mapping. This URL has to be publicly accessible, not under the restricted area -->
Otherwise it could be being understood as a normal web resource, leading to the 302 redirect.
25 Jun 2008 11:06 AM #6
Hi Marte - The Form based Auth redirects on encountering a page that is not authenticated. That seems to be part of the Servlet specs - See http://java.sun.com/j2ee/1.4/docs/tu....html#wp483393 I use the Jetty 6.1.11 as my servlet container. Having actually implemented several servlet containers at Sun & AOL, I know most of them implement the Form Auth the way the specs require. I suppose some container may use the servlet forward'ing mechanism instead of issuing a redirect to the form-login-page and thus preserving the XHR header. If I do not use the std J2EE form auth then I could have a LoginServlet check the XHR header. The J2EEAuthServlet gets invoked correctly I can see that in the debugger. Any page defined as a form-login-page in web.xml is treated as unprotected by the container so that isn't an issue. If you have the time could you trace the path of a JSON post followed by auth step in your env. You could use FireBug or LiveHttpHeaders for instance to track the Http requests ? Regards
25 Jun 2008 5:39 PM #7
Marte - The AJAX authRequest works as expected, the login screen is popped up when your interceptor determines the ajax call is unauthenticated. However the existing Ajax call returns as soon as it gets the authRequest JSON response back instead of waiting for auth to finish. The redirect is still an issue though. Regards
26 Jun 2008 12:16 AM #8
I captured a TCP stream of my login procedure with wireshark. Please take a look at it to see if the behavior is the same as in your container (which I assume it's not). Can you send me a trace of yours? The stream reflects the following:
a) I try to get the root of the secured web site, at context "regent".
b) Status code "200" is returned (instead of redirect) along with the login page.
c) The login page triggers the AJAX auth.
d) Server detects the unauthorized request and returns an invalid login. Now the popup shows.
e) I use wrong credentials "test":"test", and post to "j_security_check". The resulting JSON is a denied login, with status code "200".
f) Now I use valid credentials. Status code "302" is returned, and the extension executes again the original AJAX, the one triggered in step c).
g) The login page gets its response and does a "document.location = 'index.jsp';"
This stream is only valid on startup, since you have no other option to bootstrap the AJAX login. While inside a running app, if your session expired, any attempt made from, let's say, a grid, will act as if you started at step c), but ending at step f), so the grid would get its data.
26 Jun 2008 12:21 AM #9
Coderobo, I didn't understand the sentence "However the existing Ajax call returns as soon as it gets the authRequest JSON response back instead of waiting for auth to finish."
Do you mean that the code actually runs but the resulting data is not forwarded to the original AJAX call? Or that the AJAX call returns with the authRequest JSON as a (wrongly) valid response, interrupting the rest of the login procedure?
Can you send me a trace? The one made with wireshark would be perfect. Just apply a filter like "port 8080" (or the one you're using for web) and once the conversation is captured, click on the original request (GET or POST) and select "Follow TCP stream".
26 Jun 2008 9:25 AM #10
Hi Marte -
Attached is the trace off a FireFox 126.96.36.199 browser session. You can see at step (b)
a GET to the /auth is being generated by the browser in response to a previous redirect 302 from server. In my case the main index page has no security constraint. The user can
click on any link/menu and if the URL is protected security would be triggered. In the
attached trace the user is trying to actually do a JSON request via login/getuser.jsp.
The /auth request unfortunately doesn't have an XHR header and ends up fetching the
normal login page in step (c) instead of the authRequest JSON response.
Interestingly on IE7, at step (b) the browser is sending an XHR header after the redirect!!
So on IE7 it works fine as the J2EEAuthServlet is able to see it as an AJAX request!
From your trace I can see no 302 redirect, seems like Tomcat is just doing an internal forward and sending the appropriate login page.
Question now is if this is a FF bug - not putting all the headers in the redirected request.
IE7 appear sto be doing the right thing.