Not a developer? Go to MovableType.com

Documentation

MT::Auth

Movable Type makes available to developers a pluggable authentication framework. This framework allows developers to replace Movable Type’s native authentication layer with their own, making it possible to support authentication protocols like LDAP, Apache Basic Auth, OpenID and Shibboleth.

The MT::Auth Interface

The MT::Auth module defines an interface, that when fully implemented will allow virtually any system to authenticate into Movable Type. Before we discuss the API at any great length, it is important to understand that most authentication drivers you might want to implement need not implement this entire interface. In fact most can extend an already implemented interface like MT::Auth::MT and override just the those components they need to for their specific use case.

Let’s look at the MT::Auth interface in more depth.

  • MT::Auth->fetch_credentials(\%context) - A routine that gathers login credentials from the active request and returns key elements in a hashref. The hashref should contain any of the following applicable key fields:

    • app - The handle to the active application.
    • username - The username of the active user.
    • password - The user’s password.
    • session_id - If a session-based authenication is taking place, store the session id with this key.
    • permanent - A flag that identifies whether or not the credentials should be indefinitely cached.
  • MT::Auth->validate_credentials(\%context) - A routine that takes the context returned by the ‘fetch_credentials’ method and determines if they are valid or not. It is also responsible for assigning the active user (e.g. mt->app->{user}) if the credentials are correct.

  • MT::Auth->invalidate_credentials(\%context) - A routine responsible for clearing the active logged-in user. Some authentication modules may take advantage of this time to clear cookies, redirect the user to another web site or synchronize other operations.

  • MT::Auth->is_valid_password($author, $password, $crypted, \$error_ref) - A routine that determines whether the given password is valid for the author object supplied. If the password is already processed by the ‘crypt’ function, the third parameter here will be positive. The \$error_ref is a reference to a scalar variable for storing any error message to be returned to the application. The routine itself should return 1 for a valid password, 0 or undef for an invalid one.

  • MT::Auth->login_form - A method that returns a snippet of HTML code for displaying the necessary fields for logging into the MT application.

  • MT::Auth->sanity_check - A method used by the MT application to determine if the form data provided for creating a new user is valid or not.

  • MT::Auth->new_user - A method used in the login attempt to give a chance to each authentication layer to process the user who is going to be created upon logging in for the first time. The method must return boolean value indicating whether or not the method actually saved the new user to the database or not.

  • MT::Auth->new_login - A method used in the login attempt to give chance to each authentication layer to process the existing user logging in.

  • MT::Auth->delegate_auth - A boolean flag that identifies whether this authentication module provides a delegate authentication system. This would be the case where MT itself does not ask for authentication information, but instead defers to another web service or protocol. Typically, a delegated authentication also involves using request redirects to the authentication service when necessary.

  • MT::Auth->password_exists - A boolean flag that identifies whether this authentication module utilizes a password or not (that is, whether one is required for an account and stored with the user profile).

  • MT::Auth->can_logout - A boolean flag that identifies whether this authentication module allows for a ‘Logout’ link and logout mechanism within the application interface.

  • MT::Auth->is_profile_needed - A boolean flag that identifies whether this authentication module expects the local management of the user’s profile.

  • MT::Auth->can_recover_password - A boolean flag that identifies whether this authentication module provides a password recovery function. This is only valid when passwords are locally stored and managed.

Admittedly, that is a lot to bite off and chew. Let’s use a working example as a means to deconstruct how this interface works.

Example Driver: Apache Basic Authentication

Below is a driver that comes bundled with Movable Type. You can find it in the following location:

/path/to/mt/lib/MT/Auth/BasicAuth.pm

Let’s step through this authentication driver and shed some light on how the system works.

1  package MT::Auth::BasicAuth;
2 
3  use strict;
4  use base 'MT::Auth::MT';
5  use MT::Author qw(AUTHOR);
6
7  sub can_recover_password { 0 }
8  sub is_profile_needed { 1 }
9  sub password_exists { 0 }
10 sub delegate_auth { 1 }
11 sub can_logout { 0 }

Line 1 defines the name of this driver as well as declaring the package name. An authentication driver must utilize a package name that belongs to the MT::Auth namespace.

Line 4 establishes this package as an extension of MT::Auth::MT. In this example, Movable Type’s native authentication handler does most of what we need it to. This driver needs to override where it will find the current user’s username and to validate the current user’s session.

Lines 7-11 define the basic behavior of this driver by toggling the various boolean flags associated with the driver.

12 sub new_user {
13     my $auth = shift;
14     my ($app, $user) = @_;
15     $user->password('(none)');
16     0;
17 }

Movable Type must make a record in its own database for each user that is to use the system. This is necessary in order to ensure a consistent means of identity for a user and to maintain the relational integrity between the user and all of the other tables in the database that must reference an author by ID or some other means.

The Apache Auth driver does not need to make any modifications to the user Movable Type will create automatically. All it does is set the user’s password to “(none)” to indicate that Movable Type is not the source of record for this user’s identity and password.

18 sub remote_user {
19     my $auth = shift;
20     my ($ctx) = @_;
21     if ($ENV{MOD_PERL}) {
22         my $app = $ctx->{app} or return;
23         return $app->{apache}->connection->user;
24     }
25     return $ENV{REMOTE_USER}
26 }

The method above is actually a utility function - it extracts from the web server’s context the current authenticated user’s username. Apache stores this information in the HTTP Header called REMOTE_USER. mod_perl on the other hand makes this information available through its API.

27 sub fetch_credentials {
28     my $auth = shift;
29     my ($ctx) = @_;
30     my $remote_user = $auth->remote_user($ctx);
31     my $fallback = { %$ctx, username => $remote_user };
32     $ctx = $auth->SUPER::session_credentials(@_);
33     if (!defined $ctx) {
34         if ($remote_user) {
35             $ctx = $fallback;
36         } else {
37             return undef;
38         }
39     }
40     if ($ctx->{username} ne $remote_user) {
41         $ctx = $fallback;
42     }
43     $ctx;
44 }

On line 30 we fetch from the web layer the name of the currently authenticated user. Then on line 31 we setup the default return value if we need to signal to Movable Type that we need to create a new Movable Type session for the current user.

On line 32 we take the first step and see if a Movable Type session exists. What we need to do next is check to see if that user has a current and active Movable Type session. If they do not have a context (line 33) but they have authenticated with Apache (line 34) then we return $fallback and create a new Movable Type session. If there is no active MT or Apache session, then we return undef to signal that the user is not logged in.

Finally, if the user is logged in to Apache and Movable Type we make sure their MT username is the same as the Apache username they authenticated with. If not, then signal to MT to create a new session.

45 sub validate_credentials {
46     my $auth = shift;
47     my ($ctx, %opt) = @_;
48     my $app = $ctx->{app};
49     my $user = $ctx->{username};
50     return undef unless (defined $user) && ($user ne '');
51
52     my $result = MT::Auth::UNKNOWN();
53
54     # load author from db
55     my $author = MT::Author->load({ 
           name => $user, 
           type => AUTHOR, 
           auth_type => $app->config->AuthenticationModule });
56    if ($author) {
57         # author status validation
58         if ($author->is_active) {
59             $result = MT::Auth::SUCCESS();
60             $app->user($author);
61
62             $result = MT::Auth::NEW_LOGIN()
63                 unless $app->session_user($author, $ctx->{session_id}, %opt);
64         } else {
65             $result = MT::Auth::INACTIVE();
66         }
67     } else {
68         if ($app->config->ExternalUserManagement) {
69             $result = MT::Auth::NEW_USER();
70         }
71     }
72     return $result;
73 }
74 1;

The validate_credentials method is called each time a user access the Movable Type application. It is responsible for determining whether the current state of their account and session - and what Movable Type should do in response. It returns one of the following return values:

  • MT::Auth::SUCCESS() - indicates that the user logging in has an active and valid account.
  • MT::Auth::NEW_LOGIN() - indicates that the user logging in has an active account, but that Movable Type does not have an active session on record for them.
  • MT::Auth::INACTIVE() - indicates that the user exists, but their account is disabled and they should not be permitted access to the application.
  • MT::Auth::NEW_USER() - indicates that Movable Type has no record of the current user and that Movable Type should create the necessary record in its local database for the current user.

Enabling Your Driver

To enable a driver you have created, place the driver in your plugin’s lib directory, and then add the AuthenticationModule configuration directive to your mt-config.cgi file.

AuthenticationModule BasicAuth

The name of your authentication module corresponds to the name of your auth driver as it appears in its package name (e.g. MT::Auth::BasicAuth)

Back