I've been thinking lately about how to add authentication to a jQuery Mobile site. I whipped up a quick example that works, but I'm definitely open to suggestions on how this could be done better. My intent with calling this entry the "first round" is to make it clear that there are other ways of doing this and probably better ways of doing it. Hopefully this example will help others and - admittedly - flesh out some improvements from my readers.

I began by creating a very simple page with two links. In my application login is not required for everything, but only for one link.

<!DOCTYPE html> <html> <head> <title>Page Title</title> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4/jquery.mobile-1.0a4.min.css" /> <script src="http://code.jquery.com/jquery-1.5.2.min.js"></script> <script src="http://code.jquery.com/mobile/1.0a4/jquery.mobile-1.0a4.min.js"></script> </head> <body>

<div data-role="page">

<div data-role="header"> <h1>Secure Site Test</h1> </div>

<div data-role="content"> <ul data-role="listview" data-inset="true"> <li data-role="list-divider">Options</li> <li><a href="page1.cfm">Non-Secure page</a></li> <li><a href="page2.cfm">Secure page</a></li> </ul> </div>

<div data-role="footer"> <h4>Page Footer</h4> </div>

</div>

</body> </html>

So I won't go over the basics - I've blogged about jQuery Mobile quite a bit already - but you can see I've created a basic list page with two links. One to an open page and one to a secure page. I then created page1.cfm:

<div data-role="page">

<div data-role="header"> <h1>Non-Secure page</h1> <a href="index.cfm" data-icon="home" class="ui-btn-right">Home</a> </div>

<div data-role="content"> <p>This page is not secure.</p> </div>

<div data-role="footer"> <h4>Page Footer</h4> </div>

</div>

And then page2.cfm - note this page assumes that session.username exists.

<div data-role="page">

<div data-role="header"> <h1>Secure page</h1> <a href="index.cfm" data-icon="home" class="ui-btn-right">Home</a> </div>

<div data-role="content"> <cfoutput> <p>This page is secure. You should only see it if you are logged in: #session.username#</p> </cfoutput> </div>

<div data-role="footer"> <h4>Page Footer</h4> </div>

</div>

So - how to handle the security? I decided to add a simple Application.cfc page. This will run with every request and I could use it to lock down requests for page2.cfm. Remember that jQuery Mobile will load page2.cfm via an Ajax call, but it's still just a request to ColdFusion.

component { this.name="jqmwithlogin_rev1"; this.sessionManagement="true";

public boolean function onApplicationStart() { return true; }

public boolean function onRequestStart(string req) { //logic to determine if a page is secured should probably be elsewhere... if(listLast(arguments.req, "/") == "page2.cfm" && !structKeyExists(session, "username")) { location(url="login.cfm",addToken=false); } return true; }

}

You can see where I do my security check. I wouldn't normally write the code so statically, but for a simple example it works ok. My app only has one secure page so the logic isn't too complex. Anything more than one though would require a bit more thought here. So if the request is for my secured page and I am not logged in, I use a location call to push the user to the login page. Let's look at that.

<cfif structKeyExists(form, "login")> <cfif form.username is "admin" and form.password is "admin"> <cfset session.username = "admin"> <cflocation url="page2.cfm" addToken="false"> <cfelse> <cfset badFlag = true> </cfif> </cfif>

<div data-role="page">

<div data-role="header"> <h1>Login</h1> </div>

<div data-role="content"> <cfif not structKeyExists(variables, "badFlag")> <p>Please login...</p> <cfelse> <p>Your login was incorrect - try again - try harder...</p> </cfif> <p> <form action="login.cfm" method="post">

<div data-role="fieldcontain"> <label for="username">Username:</label> <input type="text" name="username" id="username" /> </div>

<div data-role="fieldcontain"> <label for="password">Password:</label> <input type="password" name="password" id="password" /> </div>

<input type="submit" name="login" value="Login" /> </form>

</div>

<div data-role="footer"> <h4>Page Footer</h4> </div>

</div>

So - this page is a bit bigger, but not really that complex. The form makes use of a divs with the role fieldcontain. This is standard jqm form rendering style. My form posts to itself and you can see logic on top of the file to handle that. Note the use of a static username and password. Again - this isn't something you would do normally. If the login is ok, once again a location is called to send you to the secure page.

So - how horrible is this? It seems to work ok. You can try this yourself by running the demo below.