Tuesday, April 3, 2012

Secure Web Edition Login Screens

As Real Studio web edition matures, more and more customers are using it to create applications that may contain private end-user information. This means that it's becoming increasingly important that your web applications be protected with an SSL certificate and some kind of authentication to make sure the user is who they claim to be.

Note: To follow along, you will need to build a CGI application and run it on a server that has an SSL certificate installed. Otherwise, you'll get an error.

Traditionally, a login screen requests a UserID of some kind (whether an email address or other unique identifying identifier of some kind, like an account number) and a password (automatically generated or entered by the end-user).

Example of a simple login screen.

My favorite method for creating login screens in Real Studio web edition is to use a Modal Dialog on an otherwise empty page, because there is no question about what you need the user to do next. It also allows you to deal with the complexities of the login process without any other code possibly getting in the way.

Something to remember: SSL connections are notably slower than non-SSL connections because no caching is allowed, so you might not want your whole web application to be secure (like if you were creating a publicly accessible site with special features for members-only). What you need to be able to do is to switch from non-SSL to SSL when a user gets to the login screen.

Making the Switch

In the example given above, the login screen is simply a blank web page that shows a web dialog in the Shown event. Before you get to that point, you need to check to see if the connection is secure. In the LoginPage.Open event:

Sub Open()
  // Make sure the user is connecting securely,
  // If not have the browser load the application securely
  if not session.Secure then
    dim host as string = session.Header("Host")
    dim url as string = "https://" + host
  end if
End Sub

Okay great, but this will take the user back to the initial entry screen, not the login page, so we need to tell the session how to handle that. In the WebSession.Open() event:

Sub Open()
  If Self.Secure then
  end if
End Sub

In this case we're making the assumption that an end-user that is just connecting to the app (i.e. creating a new Session) and is connecting securely will want to be directed to the login page.

Remember Me

If you look at the screen shot, I've included a "Remember Me" checkbox. Typically these are used to remember the UserID to help jog the end-user's memory about what their password might be. This function uses a browser feature called Cookies which stores a snippet of information on the computer where the user is (assuming cookies are enabled, of course). NOTE: I suggest not remembering the user's password because if this box gets checked on a public computer (like a Library or Internet Cafe) the user's account could be compromised.

To make the checkbox work, we need two pieces of code – in LoginPage.Shown:

Sub Shown()
    if session.Cookies.Value("username") <> "" then
      username.text = session.Cookies.Value("username")
      rememberme.Value = true
    end if
End Sub

First, we check to see if the "username" cookie has been set, and if it has, the value is placed into the Username text field, the RememberMe checkbox is checked and the focus is set to the Password field (mostly a convenience to the users don't need to do that manually).

Next, in the Action() event of the Login button:

Sub Action()
End Sub

Then create a method:

Sub DoLogin()
  if rememberme.Value then
  end if

End Sub

You may be asking yourself why I've created a separate method for what would normally be in the Action event… because you may want to close this dialog from another location (see below), but first, when the user clicks the login button, we check the value of the RememberMe checkbox – If True, we set the Username Cookie to the value in the username.text field. If False, we remove the cookie (otherwise user's wouldn't be able to remove the cookie by unchecking the box)

Capturing Returns

One last thing. Users expect things to work just like all the other web applications out there, and that means that when they press the Return key on their keyboard, they usually expect the login action to occur. You can do this by adding code the the KeyPressed event of the window itself:

Sub KeyPressed(Details As REALbasic.KeyEvent)
  if details.KeyCode = 13 then
  end if
End Sub

This is why we put the code from the Action event into a separate method! Now, when the user types their username and/or password and hits the Return key, the dialog will be dismissed just as if they had clicked the Login button themselves!


Gerard said...

Thanks. A great , simple and useful little post. The key pressed thing used to cause me some grief (I don't have the real bug I'd handy) but I am glad it is sorted. Oh that's right, if the page (or edit field subclass) was stored in the project as a external item, the key pressed event didn't fire. But that's a distracting detail. thanks for the https redirect snippet

Nige said...

Can you supply your code? I'm getting method or property does not exist.

A full login system example would be great.