Security in GWT, or “How to lay the foundation”
Almost three years ago to the day, I concluded a post with this:
I hate security and all software and hardware related to it, including but not limited to: anti-virus, spam, phishing, SSL, permissions, LDAP, NTLM, forms authentication, SecurID tokens, VPNs, swipe cards, PIN numbers, security deposits, car alarms, bike locks, and cell phones for seven-year-olds.I don't like that the major upgrade to Windows XP was a firewall that broke a bunch of apps. And that among IE7's features is not to let me into websites because I'm not smart enough to figure out if they're dangerous. And that Vista's main differentiation from XP is that it's harder to play my music. I will concede, however, that retinal scanners are pretty cool.
Now, three years later and my position has changed slightly in that now I also don’t like OAuth, RSA, salts, Kerberos, MD5, SHA, IPSec, OpenID, HTTP sessions, cookies, cross-site request forgery, fingerprint scanners, parental controls, deadbolts, my mother’s maiden name, my favorite pet, the name of my elementary school, and “forgot my password” links that all but announce my password on Twitter. Again, though, retinal scanners rock.
With that background, today’s topic is authentication with Google Web Toolkit.
In the .NET world, I had my head somewhat wrapped around authentication. Or rather, I knew which code to cut and paste from previous apps to make it work in new ones. But having thrown myself headlong into GWT, I’ve had to actually research the concepts. A little.
With an AJAX application like one built with GWT, there are actually two scenarios that require authentication:
- Navigating to a page
- Performing an action on a page
Navigation has traditionally been fairly easy for me to work out. You fiddle with the web.config, add a login page, toss around a FormsAuthenticationTicket or two and call it a day. With GWT, this needs to be done via gwt-presenter. But I’ll leave it at that for now because I haven’t actually got around to doing that part of the authentication yet.
Instead, I’ll focus on the second item: performing an action on a page. In GWT, I’m using gwt-dispatch, a command pattern implementation. It’s nice in that it provides a centralized interface for making RPC calls ‘twixt client and server. Nicer still is the latest version on the trunk which includes support for securing these calls.
As David Peterson points out in this thread, there isn’t much you need to do in order to add security to your command calls. That said, it isn’t altogether obvious to a Java greenhorn how to implement it. So forthwith are my current thoughts in as plain English as I can realistically make it.
The main issue I had when researching all this is that it seemed fairly academic. There is talk of sessions and session IDs and I couldn’t make the leap from that discussion to what I really wanted: to log in to the application. As I lamented on the OpenRasta forum, I can get a username and password from the screen, validate it against a database, and create a random session ID. What happens after that is still a little foggy.
So here is the workflow as I see it now:
- User enters username and password and clicks submit
- Login command is created and sent/dispatched to its appropriate handler on the server
- LoginHandler validates the user, creates a user object, and dumps it into the HTTP Session
- Server also creates a random session ID and dumps it into an appropriately-named cookie.
- Server returns login success
Next, the user performs some action that requires authentication:
- Client creates an appropriate command and sends it to the server
- The session ID is attached to the command and sent to the server
- The server checks to see if the action being performed requires authentication.
- If not, it executes the action
- If so, it checks to see if a user has been added to the session. It also verifies that the session ID it received matches the one it generated earlier (by also checking the cookies)
- If the checks fail, throw an InvalidSessionException. Otherwise, execute the action.
- Back on the client, we use a custom AsyncCallback class that specifically checks for InvalidSessionException. If it catches one, we raise a Logout event which is configured elsewhere to redirect to the login page.
The session ID check seems kind of superfluous on the surface. But from what I gather, it’s necessary to prevent cross-site request forgery attacks. As far as I can tell, it’s not used for any other purpose.
The vast majority of this is taken from various sources and I hope I remember them all. First is the Hupa, a web mail app written in GWT. Much assistance has come from the guy behind this site, which is shaping up to be one of the best tutorials I’ve seen in either Java or .NET. A good chunk of the explanation is from this post and I should note that most of the code in it has been incorporated into gwt-dispatch already.
I had planned to incorporate some code in here but didn’t for a couple of reasons. One, this is kind of wordy and I’d rather do a follow-up that is more code-centric. Two, I haven’t finished the code. For now, the act of typing all this out has served it’s purpose in that it’s helped clarify things in my head. The nice thing is that much of this is already incorporated into gwt-dispatch already. I’m still a little fuzzy on where to implement the parts I need to implement (e.g. where do I check to see if an action can be performed anonymously?) but I have something that works. Which will serve as the basis for future posts.
Kyle the Dispatched