Advanced: Creating a Custom Authentication Type

Getting an authentication type object is pretty easy whether you know the handle or not.

// Get a list of all types
$types = \Concrete\Core\Authentication\AuthenticationType::getList();

// Get a type by handle
$type = \Concrete\Core\Authentication\AuthenticationType::getByHandle($handle);

// Get a type by the type ID
$type = \Concrete\Core\Authentication\AuthenticationType::getByID($id);

To install an authentication type, make sure you have a controller.php and a form.php for it, and use the static AuthenticationType::add() method.

// Add an authentication type
$type = \Concrete\Core\Authentication\AuthenticationType::add($handle, $name);

And once you're done with it, you can delete it by calling ->delete()

// Delete an authentication type
$type->delete();

In order to use an installed authentication type, it must be enabled. Users can enable an authentication type in their dashboard, but we can do it easily with code as well.

if (!$type->isEnabled()) {
    // Enable an authentication type
    $type->enable();
}

// Then disable it
$type->disable();

Creating an authentication type

Authentication types can be created with as little as a controller.php file and a form.php file for rendering the login form. A fully featured type can also have a type_form.php view file for editing the authentication type from the dashboard and a hook.php view file for displaying a setup form in the users profile page. You may notice that the core "concrete" authentication type includes more files than just those.
For example, in your own custom authentication type that has the handle "custom_type", navigate a browser to /login/custom_type/info to render info.php. The core authentication type uses this functionality to render a forgot password form as well as other things, and the oauth authentication types use this to handle the full oauth authentication flow separately from the standard Concrete CMS login flow.

Authentication type login form

The authentication type form can be as simple or as complex as you need, your controller will be handling the authentication request so there are few limitations with what an authentication type can do. An authentication type login form is generally located in "form.php", though in some cases you may have the form located in a separate controller action view similar to the way that the core Concrete login displays the forgot password form.

To initiate a standard login flow, a form.php should include an html form that POSTs to /login/authenticate/HANDLE, for example an authentication type with the handle demo will post to /login/authentication/demo to attempt login. A valid authentication request will include a CSRF token generated from the core Token service with the handle being login_typehandle so for example, an authentication type with the handle "demo" will create and send a token with the handle "login_demo".

<form method="post" action="<?= URL::to('/login', 'authenticate', $type->getAuthenticationTypeHandle()) ?>">
    Enter the password to login as admin: <input name="password" />
    <button type="submit" class="btn btn-primary">Submit</button>

    <?php Core::make('helper/validation/token')->output('login_' . $type->getAuthenticationTypeHandle()); ?>
</form>

Authentication type controller

Authentication type controllers must extend \Concrete\Core\Authentication\AuthenticationTypeController, they handle:

  • Login form submission
  • Creating and validating a "forever" cookie
  • The authentication type icon
  • Standard Concrete controller actions and views

Login and Logout

An authentication type controller handles the full authentication operation of logging in including setting the authenticated cookie, though there is a helper method on the AuthenticationTypeController class that can complete the authentication for you give a user account.

public function authenticate()
{
    // Get the request object from the Concrete application
    $request = $this->app['request'];

    // Get the password from the request POST body
    $password = $request->post('password');

    // If the password matches our secret password
    if ($password == $this->getSecretPassword()) {

        // Get the admin user
        $admin = User::getByUserID(1);

        // Complete the authentication for the admin user account
        $this->completeAuthentication($admin);

    } else {
        $this->set('message', 'Invalid password!');
    }
}

The core concrete authentication type uses the deauthenticate() method to clean up the "2 week" remember me hashes from the database, if you don't need to do anything special on logout, you can just return false.

Creating a forever cookie

A custom authentication type can define a user specific hash to be set against a long running cookie. The core authentication type uses this functionality to create a user specific hash on login so that a user returning to the site that has a valid cookie can be logged in automatically.

Authentication type icons

Icons are an important part of an authentication type's identity. An authentication type controller has full control over the icon:

public function getAuthenticationTypeIconHTML()
{
    // Show a font awesome clock icon
    return "<i class='fa fa-clock'></i>";
}

Controller actions

Authentication type controllers allow for controller actions in the same way a single page controller would. Create a public method on your controller and navigate to /login/type_handle/method_name where type_handle is the handle of your authentication type and method_name is the name of your method. The method will fire and the form.php view file will be loaded. If you also create a view file with the same name as the method, that view file will be loaded instead. Refer to the core forgot_password flow for more information on how to use these.