2016-09-01

IPS Community Suite comes with a number of different methods to allow users to log in to the community, called "login handlers". Generally speaking, there are two types of login handlers:

"Standard" login handlers which take a username and/or email address and password. For example, the default login handler, LDAP and IPS Connect.

Login handlers which use a custom form, which are usually (though not necessarily) OAuth based. For example, Facebook, Twitter and LinkedIn login.

Getting Started

Both types are implemented by creating a PHP file in the system/Login folder containing class that extends IPSLoginLoginAbstract and inserting a record into the core_login_handlers database table. If you are creating a 3rd party login handler for distribution, you will need to create a plugin to insert that record, and distribute it with your login class.

When inserting the record into core_login_handlers, set login_key to the name of the class without the namespace (for example, if your class is IPSLoginExample, set login_key to "Example").

Note that your PHP class will be prefixed with an underscore. This is a technicality in how code hooks are facilitated in the IPS Community Suite.

Standard Login Handlers

Here is a basic skeleton for a standard login handler:

The $authTypes property defines whether your login handler expects a username or email address or either. It is a bitwise field, and the acceptable values are:

If you want to base this off a setting, or do any other setup for your login handler, you can implement an init() method.

The authenticate() function receives the values from the form (the username/email address and password) and can either return an IPSMember object if the login was successful, or throw an IPSLoginException object if it wasn't. If throwing an IPSLoginException object, the message is displayed to the user, and the code should be one of the following values:

If your login handler needs to create an account for a user, and it is appropriate to do that, you can do that in the authenticate() method. For example:

The acpForm() and canChange() methods are discussed below.

Other Login Handlers

Here is a basic skeleton for an OAuth-based login handler:

The $icon parameter should be the name of a FontAwesome icon which is used on some login screens.

The loginForm() method is used to display the HTML you need for the form. For an OAuth-based handler, this will usually just return the appropriate login button. You can alternatively return an IPSHelpersForm object.

The authenticate() method is where the bulk of your login code will go. If your loginForm() method returns an IPSHelpersForm object it will be passed an array of values from that form (just like standard login handlers). If your loginForm() method returns raw HTML, it is your responsibility to ultimately redirect the user back to the same URL that was passed as $url to loginForm with the "loginProcess" set to the key for your login handler. Most OAuth providers do this with a gateway script in the interface directory.

Your authenticate() method needs to return an IPSMember object or throw an IPSLoginException object, just as described above for standard login handlers.

The acpForm(), link() and changeSettings() methods are described below.

Creating settings for your login handler

You will likely need to create settings for your login handler so when an admin sets it up they can provide keys, etc. There are two methods to assist with this:

acpForm() can return an array of form fields allowing you to specify these settings, and testSettings() allows you to check the settings are correct. For example, to define a client ID setting you might do something like this:

And then you can simply access it's value elsewhere using $this->settings['example_client_id'].

You can of course use custom validation callbacks for fields if appropriate, but often you will need testSettings() where there are multiple settings which work together.

Merging Accounts

With some login handlers, particularly those which are OAuth-based, you may need to merge accounts. For example, imagine a user is registered on your community, and then they try to log in using Facebook. In this situation, you don't want to create a new account, but rather prompt the user to link their Facebook account with their existing account. In this case, throw an exception in your authenticate() method:

Set $handler to the key for your login handler, $member to the existing account and $details to any details you need to link the accounts together, such as the access token.

Then implement a link() method:

Your link() method is called after the user has provided their password and it is safe to link the accounts together. Do whatever is necessary so that on subsequent logins, you can log the user in without intervention. Note that link() is static and cannot use any settings from the login handler.

Checking if email/username is in use

When a user registers an account on the community, your handler can check if the email address or username is acceptable. This is useful if you want your login handler to provide close integration such as is provided by the LDAP and IPS Connect handlers. The methods are emailIsInUse() and usernameIsInUse() - see the signatures in LoginAbstract for information on how to override these.

Changing Details and additional callbacks

When a user changes their email, password or username on the community, your handler can be notified of these changes and update their databases. You need to implement the canChange() method to let the User CP controllers know you support this functionality, and then the methods are changeEmail(), changePassword() and changeUsername() - see the signatures in LoginAbstract for information on how to override these.

Additional callbacks are also available - logoutAccount(), createAccount(), validateAccount(), deleteAccount(), banAccount() and mergeAccounts() - see the signatures in LoginAbstract for information on how to override these.

Show more