Application Security: Login Page

Most web applications require some level of security. Here, for example, I have an area where I update the categories, articles, and other content that is displayed on the web site.

Model-View-Controller

A classic Model-View-Controller approach is used to implement initial security (that is, to let a user log on). The model is the AppUserFactory class that represents the user table in the underlying PostgreSQL database. The view is the LoginPage application module where the user presents credentials: most commonly, a username (or email address) and a password. The controller is the ApplicationSecurityDelegate object, which manages the interaction with the AppUser model object class and handles the results of successful (and unsuccessful) authentication.

Login: the View

[fig]login-workflow[/fig]

The Login application module uses a LoginWorkflow (which is provided in the Istarel Workshop Application Framework). A LoginWorkflow object manages two states: IWMode::MODE_EDIT (edit) and IWMode::MODE_LOGIN (login). The edit state is presented as a form, so the Login application module needs to provide the elements that comprise the form.

Listing: rsrc/Login.php

class Login extends IWModule
{
   function requiredWorkflow() { return 'IWLoginWorkflow'; }

   function pageClass() { return 'LoginPage'; }
   function pageTitle() { return 'Login'; }

   function formElements()
   {
      return array(
         'header'   => new IWHeaderElement('Login Information'),
         'email'    => new IWFormElement('Email:', new IWTextElement(30, 100)),
         'password' => new IWFormElement('Password:', new IWPasswordElement(10, 12)),
         'uri'      => new IWHiddenElement(IWRequest::getValue('uri', null))
      );
   }
}

The last element of the form captures the user's intended destination. If an individual comes directly to the login page, the value is null. If an individual tried to navigate directly to a secure module (either by typing the URL directly into her browser or from a bookmark), then that URL is encoded in the query string if authentication failed (as would be the case if the user was not logged in before attempting to go there).

Page Object

Every application module that can render content has an associated Page object, which in turn uses a template file as the basis for how its components are rendered.

Listing: rsrc/page/LoginPage.php

class LoginPage extends HTML5Page
{
   function initialize()
   {
      $this->addStylesheet('css/login.css');
   }

   function templateFile()
   {
      return APPL_RSRC_DIR . 'page/html/login.html';
   }

   function expectedComponents()
   {
      return array('head', 'header', 'form', 'footer');
   }
}

Listing: rsrc/page/html/login.html

<!DOCTYPE html>
<html lang="en">
{*head*}
<body>

<div id="wrapper">
   <div id="header">{*header*}</div>
   <div id="content">{*form*}</div>
   <div id="footer">{*footer*}</div>
</div>

</body>
</html>