Authentication is a process of recognizing a user entity by providing some kind of credentials like a username, password, or access key.

Authentication providers are the underlying logic for authentication.

In Drupal, we have two authentication providers in the core

  1. Cookie (cookie)
    Applies globally with a provider weight of 0
  2. Basic Auth (basic_auth)
    Provider defined in basic_auth module of the core with provider weight 100

But using contributed module we can add other popular authentication providers like OAuth (v1 or v2)

Our Plan

Here, we will go through the development process and understand the general working of the authentication provider

Declaration

In Drupal, the Authentication provider is declared in module.services.yml, just like other services but with a service tag authentication_provider with few other non-required keys.

Let’s look at the below declaration of our authentication provider.

services:
  token_auth.authentication.auth_token:
    class: Drupal\token_auth\Authentication\TokenAuthenticationProvider
    arguments: [ '@entity_type.manager' ]
    tags:
      - { name: authentication_provider, provider_id: 'token_auth', priority: 100 }
  1. name: (required), the service data manager will use this tag for discovery so it must be set to “authentication_provider”
  2. provider_id: machine_name of the authentication provider.
  3. priority: authentication provider weight
  4. global: set to false by default, But if set to true then the authentication provider will be applied globally throughout the site.

Authentication Manager & Authentication Provider

The authentication manager is responsible for collecting information on the authentication provider service and for running the authentication provider logic.

It basically executes all the collected provider services on the basis of their weight, where the provider having the highest weight executed very first and the provider having the lowest weight executed at last (Highest to Lowest).

It keeps executing provider service until it has one to execute or a user is determined.

It loops through all the providers collected (global and non-global) and executes applies the method of the provider if it returns false (not applies to the route) it moves to the next provider in the loop and if it returns true then it executes authenticate method of provider if it returns null then it again moves to the next provider in the loop and if it returns an object of AccountInterface then it stops looping and authorizes the current request.

<?php

namespace Drupal\token_auth\Authentication;

use Drupal\Core\Authentication\AuthenticationProviderInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class TokenAuthenticationProvider
 *
 * @package Drupal\token_auth\Authentication\Provider
 */
class TokenAuthenticationProvider implements AuthenticationProviderInterface {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function applies(Request $request) {
    return $request->headers->has('X-Auth-Token');
  }

  /**
   * {@inheritdoc}
   */
  public function authenticate(Request $request) {
    $token = $request->headers->get('X-Auth-Token');

    $user = $this->entityTypeManager
      ->getStorage('user')
      ->loadByProperties([
        'auth_token' => $token,
      ]);

    if (!empty($user)) {
      return reset($user);
    }

    return NULL;
  }

}

There are some more functions and logic which I have written to understand the authentication provider. You can find that test module here https://github.com/devudit/token_auth

It’s a simple module that installs the following features.

  1. Add a token filed to the user entity which is automatically generated.
  2. Add a token_auth authentication provider which we can apply to routes using module.routing.yml and the REST resource using the backend interface (screenshot#1).
  3. Define a REST Resource for exposing a node by node id (for testing the token_auth authentication provider — screenshot#2).
Screenshot #1
Screenshot #1
Screenshot #2
Screenshot #2

Any suggestion to improve this article and to make it more usable will be much appreciated.