addendum: my session expired whilst writing this!

On Feb 19, 1:07 pm, Paul S <paulsschw...@gmail.com> wrote:
> I would like to debate some ideas for how to secure GWT apps in
> different ways and their pros and cons. It is important to remember
> that there will be different needs and so different approaches will be
> more suitable in certain cases, but I just want to be aware of what
> people are doing.
>
> I am using Spring Security because it is excellent, and whilst I am
> aware that there are many other solutions available this is not the
> focus here, so I'll just call it Security from here on.
>
> Security offers protection of URLs and also some more fancy AOP style
> protection like protection of specific functions. To keep things
> simple here lets just look at protection of URLs.
>
> 1. Without Ajax - Protecting URLs that relate to pages
>
> Before the days of Ajax where a URL effectively corresponds to a state
> you can see how the model becomes straight forward. Adam accesses /
> home.html, it loads and Adam gets to read a bunch of content. At this
> point Adam is considered to be a Guest. Adam is curious about a link
> called "Administration", when he clicks it he is sending a Request.
> That Request has some header info embedded in it (which the user never
> sees but you can see if with Firebug or whatever). Sadly Adam is not
> signed in so Security redirects him to a login page, but remembers
> everything about that original Request. Adam suddenly remembers he
> does have a user name and password so he logs in. Security processes
> his login and then redirects him to the exact equivalent of what would
> have been the original Request. Adam is happy because his work flow
> continued seamlessly despite being asked to login.
>
> (Ok, Spring Security can be configured to replay the original Request
> upon successful login (default), or it can be forced to send you to a
> particular default login success page. If you use the latter then
> Adam's work flow will not be seamless because his original request for
> the "Administration" page has been forgotten. Though sometimes you
> might need a set up like this?)
>
> Now Ajax comes along, and in particular I'm going to talk about GWT
> here but the principles apply.
>
> 2.a. With Ajax - but still protecting URLs that relate to pages
>
> If we use Security to protect the URL of container page (in GWT that's
> the page that hosts the bootstrap javascript code for your GWT app)
> then, just like normal if Adam visits /home.html he will be able to
> read the content on that page. The "Administration" link has been
> modified to take you to /admin.html which is in fact the host page the
> GWT administrator module. Adam clicks "Administration" which Security
> knows requires the Admin role so he is redirected to the login page.
> Adam logs in and whether Security is configured to play back the exact
> Request or whether you specifically move the browser along to /
> admin.html, at this point doesn't matter. Adam is now looking at a
> fully loaded GWT application. Lets say also that Security is told to
> protect every GWT RPC call. Well Adam is logged in so he is allowed
> access to the server services via GWT RPC and all goes smoothly...
> until Adam leaves his computer for an hour and comes back to continue
> his work. When the next server call that occurs is met by Security who
> says, since your session has expired you are not logged in, so I'm
> going to redirect you to the login page. XmlHttpRequest obeys the 30x
> response code which is telling it to actually load the resource at /
> login.html. In GWT this amounts to an InvocationException where the
> error message content is your /login.html page markup. That's no good!
> The XHR cannot interpret this as your browser would, so what to do?
> The answer is pretty straightforward here. Design your /login.html
> page to contain a text token that you can search for. So for example
> in my /login.html code I have places an html comment right at the top
> like this
> <!-- SECURITY-LOGIN-PAGE -->
> so when the browser hits the /login.html page it just looks like a
> regular login page. But when the RPC call encounters this
> InvocationTarget exception I have an onFailure handler that looks like
> this:
>
>    public void onFailure(Throwable t) {
>       if (t instanceof InvocationException){
>          if 
> (t.getMessage().split("<!--\\s*SECURITY-LOGIN-PAGE\\s*-->").length > 1){
>
>             onLoginRequested();
>         } else {...}
>       } else {...}
>    }
>
> My onLoginRequested() method could be any of a few styles. The most
> obvious is to have it call a native method that looks like this:
>
>    private native void redirectToLogin() /*-{
>       $wnd.location.replace("/login.html");
>    }-*/;
>
> Now at this point we have to get clear on the behaviour of Security
> with regard to where it redirects the browser after successful login.
> In this case you would have to specify that it ALWAYS redirects you
> to /admin.html so that when Adam signs in again he is taken back into
> the Administration app. But sadly his page state (history tokens) is
> lost and he's back on the front screen of your app and is now required
> to put the app back into the state it was before (i.e. Adam may have
> had some popup open, some menu item open, etc. Now he's back on the
> clean front page).
> If you're wondering what would have happen if we didn't tell Security
> to force the successfully logged in user back to /admin.html, but
> instead allowed Security to replay the orignal Request, wouldn't we
> end up back in the app with page state preserved? No! Remember that
> the Request that causes us to be taken to /login.html in the first
> place was the RPC call. So if Security were to do Adam the favour of
> redirecting his browser to reflect the original Request then the
> browser would be attempting to display the contents of the RPC call's
> response! eww... not what we wanted. That's why the solution here is
> to force Security to redirect any and all successful logins to /
> admin.html. Disadvantage is Adam's workflow is interrupted.
>
> 2.b. With Ajax - iframe style login (in place login rather than the
> browser being redirected to /login.html)
>
> Ok, so how about this: When Adam first clicks "Administration" he is
> taken to the /login.html page, upon successful login he is redirected
> to /admin.html. Now, as above, if he waits an hour and the tries to
> perform and RPC call he receives the /login.html page via the RPC
> response, as above, but instead of doing $wnd.location.replace("/
> login.html"); and sending the browser off to the login page, we simply
> show a nice, pretty, GWT popup that contains an iframe that points to /
> login.html. In the background Adam is still looking at the GWT
> Administration app and Adam's workflow (page state) is preserved but
> he must answer the login iframe before he can continue. Implementation
> is up to you but I would suggest that you would have the iframe load
> up /login.html and then upon clicking login two things happen, the
> iframe sends the login request to Security who authenticates, and at
> the same time the popup containing the iframe is removed from the DOM.
> Adam can then continue with what he was doing before. Still you can't
> take advantage of asking Security to replay the original request
> because that would be like telling the iframe to navigate to the page
> that corresponds to the original RPC call (same problem as above,
> makes no sense). Ok firstly I must say I can see some issues with this
> approach, like telling the Login button to tell the GWT application in
> the parent frame to close the popup?! Unwieldy in my opinion. Also
> note that if login fails what should happen is that the popup iframe
> shows up again to ask you to log in again. But does this happen upon
> unsuccessful login, or does the popup silently disappear and then only
> when Adam tries to execute an action that requires the RPC call again
> then we get the popup iframe login once more? Seems like this approach
> carries the advantage of preserving application state but still uses
> the pre-Ajax still approach.
>
> 3. With Ajax - protecting only RPC calls, but not protecting host page
>
> So anyone can visit /admin.html and the GWT app will load (the GWT is
> just Javascript so who cares if the app can load, it's the data/RPC
> call that we want to protect, isn't it?).
> Ok so the app loads and looks like it's ready to use, but as you
> invoke an action that requires an RPC call Security says, Adam, you're
> not logged in. Because this example is totally Ajaxified we will still
> allow Security to redirect out requests to a login URL, but this time
> our login page does not contain a valid HTML login form, it just
> contains a token like PLEASE-LOGIN. To keep things clear lets say that
> we save this file as /login.response. So Security redirects the RPC
> call to /login.response. As before, GWT is unaware the redirect taking
> place, but, as before, in our onFailure method we look for
> InvocationExceptions and then check the exception's .getMessage()
> string and test if equals PLEASE-LOGIN. If it does then we program a
> function in GWT to show a nice, pretty, GWT popup that comprises a
> form. The form elements are a username input box, password input box
> and login submit button. The form action will be Security's access
> check URL (by default in Spring Security this will be "/
> j_spring_security_check"). If login is successful then Security would
> redirect the browser to /admin.html, oops! That's not what we wanted.
> What we really wanted is a way for that popup form to be submitted,
> hidden and Adam is able to seamlessly continue with his work flow.
> I have used this approach in an large intranet application before and
> here is the result. Adam hits the /admin.html URL and the GWT app
> loads. He then clicks login and the popup form appears (ok, this is
> Adam hitting login, but equally he could try an action and it would
> fail and the login popup would show). Now, it was quite a nuisance for
> Adam that when his session expires and he logs in using the popped up
> form he is taken back to the apps front page. So, not to be put off by
> the failure of this approach, I built in a ping system, so the GWT app
> periodically (every 5 minutes) pings the server via a very simple RPC
> call but to tell it "hey, still here, don't lose my session!". The
> problem with this is that we are solving the problem by overcoming the
> session time out problem. That's ok but not really what we want - not
> to mention some purists would say that this is an abuse of the session
> timeout function. I'm not sure where I sit on that argument, because
> session timeout does two things - 1. ensure that if you walk away from
> your computer and then later a rogue colleague sits are you computer,
> the system protects itself by having timed out and requiring login
> again, assuming an hour elapsed. 2. allows the server a way to garbage
> collect old sessions so it's memory isn't taken up by session
> information from last week/month/year. If 2. is all you care about
> then the server ping approach works fine.
>
> 4. With Ajax - logging in using an RPC call
>
> This would be the silver bullet, wouldn't it? I doubt (though maybe I
> am wrong) that you could employ the traditional style of protection/
> login as mentioned in 2. to protect your host page "/admin.html" and
> then if successfully logged in you gain access to the host page and
> all of the RPC calls as well, but when your session expires you get
> the nice, pretty, GWT popup that then does its second login via an RPC
> call?! This would require that the URL of your RPC login service would
> have to have public access, but all your business services would need
> Admin access.
> The advantages here are
> -  admin app is protected
> -  RPC calls are protected
> -  if session times out and you attempt an RPC call then your
> onFailure code would know to show you the login popup
> -  if you successfully login then the popup hides and you may continue
> with your work. Page state/work flow was never interrupted. At worst
> you'll need to repeat your last action, which may be clicking "Save"
> again, or whatever, I don't know if we could get the RPC call Request
> to replay automatically, your thoughts?
>
> If this is possible then please share. If it is not, then I would
> still like to explore the authentication over RPC technique, and would
> be happy to forego having the /admin.html page protected. Like I said,
> in most apps it is the interaction with the server that must be
> protected, it is not crucial to protect your Javascript application
> code. (unless it is ;) ).
>
> I hope this helps someone, and in return I hope someone can help me
> with approach number 4. Note that approach number 4 will require some
> server side set up, so will require some Spring-specific modifications/
> changes of default behaviour.
>
> Happy coding,
> Paul S

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to google-web-tool...@googlegroups.com.
To unsubscribe from this group, send email to 
google-web-toolkit+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-web-toolkit?hl=en.

Reply via email to