TFA plugins and plugin development

Last updated on
27 October 2022

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

TFA plugins provide the form and validation handling for 2nd factor authentication of a user. The TFA module will interrupt a successful username and password authentication and begin the TFA process (see Configuration for exceptions to this statement), passing off the form control and validation to the active plugin.

Getting started

  • Implement hook_tfa_api() in a .module file
  • Create a class extending TfaBasePlugin and implementing one of the TFA interfaces
  • Optionally create a second class for plugin setup implementing TfaSetupPluginInterface

For starter or example code see the test classes at ./tests/includes/

Plugin interfaces, or types of plugins

TFA plugins should implement one of the following interfaces.

  • Validation (TfaValidationPluginInterface) - Validation plugins are the main TFA plugin type and are used during the authentication process to accept the 2nd authenticating element.
  • Login (TfaLoginPluginInterface) - Login plugins are used to check conditions for whether an account must carry out TFA before authentication.
  • Send (TfaSendPluginInterface) - Send plugins are used for carrying out an action at the beginning of the TFA process. For example, a plugin that sends a code to a user over SMS could implement this interface to generate and deliver the code.
  • Setup (TfaSetupPluginInterface) - A setup plugin is used by the TfaSetup class for configuring a TFA plugin for an account.

Plugin context

A plugin is instantiated with an array of data about the occurring TFA process. This context array must contain the following elements that should not be modified.

  • uid - Drupal UID of user carrying out the TFA process.
  • plugins - Array of active plugins in the process, must include element 'validate' and may also include 'login' and 'fallback'.

The context array may also include any plugin-specifc elements so long as there is no conflict with the above keys. Context can be used for temporal storage of plugin data like codes or state but do be aware that this context may be written to the Drupal session or form cache database tables so scalar or array types are recommended.

Base methods

Plugins can implement the ready() method to determine if its ready for use with the authenticating account. For example, if authenticating user has not setup of a phone number for SMS delivery a SMS TFA plugin would not want to begin the TFA process for that account and should return FALSE.

The finalize() method can be used to carry-out actions after confirming the TFA process. For example, a SMS plugin might mark a code as having been used to prevent a repeated attempt.

Example implementation descriptions

How to generate and send a code to a user via SMS

Create a plugin that implements the TfaSendPluginInterface interface and
implement the begin() method to generate a code (or use parent generate()) and send it to the user. Use the SMS Framework or Twilio modules (for example) to actually deliver the code over SMS.

Implement the TfaSetupPluginInterface to allow the user to set the phone number for delivery. Separately implement hook_schema() to create a database table for storing TFA phone numbers or use a account profile field.

How to allow web services to authenticate while requiring TFA for regular users

A services authentication scheme will be affected by TFA's implementation during hook_user_login() so create a login plugin that checks the services user and returns TRUE for loginAllowed(). See TfaTestLogin in ./tests/includes for an example.

Help improve this page

Page status: No known problems

You can: