Authorization in frontend

Contents...

The framework contains a special mechanism, which allows a developer to relatively easily implement a registration and authorization system (login with a password) for frontend (website) users. The data of registered users are stored by the Contacts app, and the framework kernel provides convenient interfaces to include registration and login forms in application design templates.

For a working example, look at the Guestbook 2 app in which the authorization system for frontend users described below is implemented.

Enabling authorization on the website

Authorization is set up individually for each website (domain name) connected to the installed framework instance in the Site app (primarily in the routing configuration file) in file wa-config/auth.php:

<?php

return array(
    'domain1.com' => array(
  		// enables authorization on the website; in design templates its current status is returned by function $wa->isAuthEnabled()
        'auth' => true,
  		// application, which is responsible for user registration/authorization
  		// the specified application must support authorization (its file app.php must contain record 'auth' => true)
        'app' => 'blog',
        // authorization adapters for external services
        'adapters' => array( 
            'facebook' => array (
                'app_id' => 'FACEBOOK_APP_ID',
                'app_secret' => 'FACEBOOK_APP_SECRET',
            ),
            // ... other adapters
        ),
        /*
        Array defining the set of fields for the registration form
        If not specified explicitely, the following field set is used by default:
        'fields' => array(
            'firstname',
            'lastname',
            '', // separator
            'email',
            'password', //"enter password" and "re-enter password" fields
        )
        */
    ),
    'domain2.com' => array(
        // ... similar settings for domain2.com
    )
);

The set of registration fields is controlled by array item with key 'fields'. The following values are acceptable:

'name', // if you type "John Doe", then the 'firstname' value will automatically become "John", and the value of 'lastname' will be "Doe"
'sex',
'birthday',
'phone.mobile',
'url',
'address', // composite field consisting of five subfields: street address; city; state; country; ZIP code
'im.skype',

Other field examples see in the contact field descriptions file wa-system/contact/data/fields.php.

Authorization and registration of your application's frontend users

The design and functionality of an authorization form is controlled by the specific application; therefore, they are included in website pages not at the system level but in the source code of that application. The framework offes ready-to-use tools for convenient connection of suhc forms within an application, but their appropriate location on a page, design, and actual content are defined solely by the application's developer.

  1. In file wa-apps/APP_ID/lib/config/app.php a setting should be added to specify that your application supports user authorization:

        'auth' => true
        

    Of course, your application must have a frontend:

    'frontend' => true
  2. Create 3 action classes responsible for the functioning of the login form, the registration form, and the password recovery form. A detailed description of each action is provided below.

Login form

Create file wa-apps/[APP_ID]/lib/actions/[APP_ID]Login.action.php

<?php

class [APP_ID]LoginAction extends waLoginAction
{
    public function execute()
    {
        // general website layout
        $this->setLayout(new [APP_ID]FrontendLayout());
        // login form tenplate
        $this->setThemeTemplate('login.html');
        // execution of the parent class implementing the complete login processing logic
        parent::execute();
    }
}

In the design theme create file wa-apps/[APP_ID]/themes/default/login.html

<div class="content">
    <div id="page" role="main">
        <h1>Login</h1>
        {$wa->authAdapters()}
        {$wa->loginForm($error)}
    </div>
</div>

Registration form

Create file wa-apps/[APP_ID]/lib/actions/[APP_ID]Signup.action.php

<?php

class [APP_ID]SignupAction extends waSignupAction
{
    public function execute()
    {
        // set a layout for the frontend
        $this->setLayout(new [APP_ID]FrontendLayout());
        $this->setThemeTemplate('signup.html');
        // call the parent's method
        parent::execute();
    }

    /**
     * This method is called after successful creation of a new contact.
     * You can modify it to send an greeting message to the newly registered user, for example,
     * or add the contact to the application's system category
     */
    public function afterSignup(waContact $contact)
    {
         // Add the new contact to the applications' system category,
         // $this->getAppId() returns the APP_ID of the current application.
         // The list of contacts of this category can be viewed in the Contacts app
         // in a system category with the name of your application.
         $contact->addToCategory($this->getAppId());
    }
}

Create template file wa-apps/[APP_ID]/themes/default/signup.html

<div class="content">
    <div id="page" role="main">
        {if !empty($contact)}
            <h1>Thank you!</h1>
            <p>You have been successfully registered.</p>
        {else}
            <h1>Registration</h1>
            {$wa->authAdapters()}
            {$wa->signupForm($errors)}
        {/if}
    </div>
</div>

Password recovery form

This action is responsible for the functioning of the password recovery form and for setting a new password upon a click on the password resetting link sent to the user by email.

To create those form, create action file wa-apps/[APP_ID]/lib/actions/[APP_ID]Forgotpassword.action.php

class [APP_ID]ForgotpasswordAction extends waForgotPasswordAction
{
    public function execute()
    {
        $this->setLayout(new [APP_ID]FrontendLayout());
        $this->setThemeTemplate('forgotpassword.html');
        parent::execute();
    }
}

Also create template file wa-apps/[APP_ID]/>themes/default/forgotpassword.html ($set_password is equal to true, if a new password should be entered; otherwise the login form is displayed):

<div class="content">
    <div id="page" role="main">
    {if !empty($set_password)}
        <h1>Password recovery for {$login}</h1>
        {$wa->setPasswordForm($error)}
    {else}
        <h1>Password recover</h1>
        {if !empty($sent)}
        <p>Password recovery instructions have been sent to your email address.</p>
        <br /><br />
        <a href="{$wa->loginUrl()}">I have recalled my password!</a>
        {else}
        {$wa->forgotPasswordForm($error)}
        {/if}
    {/if}
    </div>
</div>

Application-wide routing

All of these 3 actions of the login, registration, and password recovery forms should then be settled within the application's internal routing system, in file wa-apps/[APP_ID]/lib/config/routing.php:

<?php

return array(
    // logine form
    'login/' => 'login', // whenever URL /login is requested, action [APP_ID]LoginAction will be triggered
    // password recovery
    'forgotpassword/' => 'forgotpassword',
    // registration form
    'signup/' => 'signup',
    //... other routing rules for your applications' frontend
);

Now it is only necessary to settle your application to one of your websites using the Site app and enable authoriazation for that website by selecting your application as supporting authorization.


Below is the list of functions of Smarty helper $wa, which make the implementation of the authorization/registration functions easier for your application (some of them have been used in the above examples of forms).

{$wa->isAuthEnabled()}: whether authorization is enabled on the current website

{$wa->signupUrl()}: relative URL of the registration page
{$wa->loginUrl()}: relative URL of the login page
{$wa->forgotPasswordUrl()}: relative URL of the password recovery page

{$wa->signupForm($errors)}: HTML code of the registration form; $errors is an array of errors returned by action signupAction (this array is generated at the system level)
{$wa->loginForm($errors)}: HTML code of the authorization (login) form
{$wa->forgotPasswordForm($errors)}: HTML code of the password recovery form, which requests a login name or an email address from the user
{$wa->setPasswordForm($errors)}: HTML code of the new password entering form, which opens upon a click on the password resetting link

{$wa->authAdapters()}L returns an HTML block for authorization via external services (social networks)
{$wa->authAdapters(true)}: returns the array of adapters for authorization via external services (social networks)


Authorization via external services (social networks)

The framework offers the ability for the frontend users to authorize via external services (social networks). This functionality is implemented in the form of authorization adapters. By including authorization forms as described above (specifically through adding the adapter list code {$wa->authAdapters()}) to form templates, you will automatically enable authorization via all external services for your application, which are set up in your installed framework instance.

How to verify user authorization

It is relatively easy to make some part of the frontend inaccessible to public and protected with a password to be accessible only for registered users (personal online account): simply check the fact whether the user is authorized.

PHP

In actions/controllers:

if ($this->getUser()->getId()) {
     // is authorized
}

Anywhere:

if (wa()->getUser()->getId()) {
     // is authorized
}

Smarty

{if $wa->userId()}
   // is authorized
{/if}