Social Auth EventSubscriber example module

Last updated on
15 November 2017

Drupal 8 provides a powerful and performance efficient way how modules can interact with each other. Social Auth provides events for the following purposes:

  • social_auth.user.created: This allows other modules to react on an event when new user is created via a Social Auth implementer.
  • social_auth.user.login: This allows other modules to react on an event when users log in via a Social Auth implementer.
  • social_auth.user.fields: This allows other modules to initialize more fields in user creation.

This page contains an example module which demonstrates how to write your own module that subscribes to these events and how to make your own calls to Social Auth API. The example module is called my_module.

my_module/my_module.info.yml

name: My Module
description: 'EventSubscriber example module for Social Auth.'
package: Social
type: module
core: 8.x
dependencies:
  - social_auth

my_module/my_module.services.yml

services:
  my_module.event_subscriber:
    class: Drupal\my_module\EventSubscriber\SocialAuthSubscriber
    arguments: []
    tags:
      - { name: 'event_subscriber' }

This lets Drupal know about the existence of this service. Through the tag 'event_subscriber', my_module tells Drupal that our service wants to subscribe to events that other modules (Social Auth for our purposes) are triggering

my_module/src/EventSubscriber/SocialAuthSubscriber.php

<?php

namespace Drupal\my_module\EventSubscriber;

use Drupal\social_auth\Event\SocialAuthUserEvent;
use Drupal\social_auth\Event\SocialAuthEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Reacts on Social Auth events.
 */
class SocialAuthSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   *
   * Returns an array of event names this subscriber wants to listen to.
   * For this case, we are going to subscribe for user creation and login
   * events and call the methods to react on these events.
   */
  public static function getSubscribedEvents() {
    $events[SocialAuthEvents::USER_CREATED] = ['onUserCreated'];
    $events[SocialAuthEvents::USER_LOGIN] = ['onUserLogin'];

    return $events;
  }
  
  /**
   * Alters the user name.
   *
   * @param \Drupal\social_auth\Event\SocialAuthUserEvent $event
   *   The Social Auth user event object.
   */
  public function onUserCreated(SocialAuthUserEvent $event) {
    /**
     * @var Drupal\user\UserInterface $user
     *
     * For all available methods, see User class
     * @see https://api.drupal.org/api/drupal/core!modules!user!src!Entity!User.php/class/User
     */
    $user = $event->getUser();

    // Adds a prefix with the implementer id on username.
    $user->setUsername($event->getPluginId() . ' ' . $user->getDisplayName())->save();
  }
  
  /**
   * Sets a drupal message when a user logs in.
   *
   * @param \Drupal\social_auth\Event\SocialAuthUserEvent $event
   *   The Social Auth user event object.
   */
  public function onUserLogin(SocialAuthUserEvent $event) {
    drupal_set_message('User has logged in with a Social Auth implementer. Implementer for ' . $event->getPluginId());
  }

}

Using tokens to request more data

Social Auth implementers store their tokens in session variables. Through these variables, an external module can customize its own requests to the social network services.

my_module/my_module.services.yml

services:
  my_module.event_subscriber:
    class: Drupal\my_module\EventSubscriber\SocialAuthSubscriber
    arguments: ['@session', '@plugin.network.manager', '@social_auth_google.manager']
    tags:
      - { name: 'event_subscriber' }

This version of the services.yml file passes the following parameters to SocialAuthEventSubscriber constructor

  • session service (from Drupal core, class Symfony\Component\HttpFoundation\Session\Session): This object is used to access the tokens store in session through Social Auth implementers.
  • plugin.network.manager service (from Social API, class Drupal\social_api\Plugin\NetworkManager): This object is used to create instances of Social API plugins. When an instance is created, an object of the SDK used by the Social Auth implementer is returned.
  • social_auth_google.manager (from Social Auth Google, class Drupal\social_auth_google\GoogleAuthManager): This object is used to perform tasks such as setting the access token and authenticating. An external module can still authenticate without this object by using the instance returned by plugin.network.manager. However, Social Auth implementer managers (such as GoogleAuthManager and FacebookAuthManager) try to make the code persistent across multiple Social Auth implementers.

 my_module/src/EventSubscriber/SocialAuthSubscriber.php

<?php

namespace Drupal\event\EventSubscriber;

use Drupal\social_api\Plugin\NetworkManager;
use Drupal\social_auth\Event\SocialAuthUserEvent;
use Drupal\social_auth\Event\SocialAuthEvents;
use Drupal\social_auth_google\GoogleAuthManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

/**
 * Class UserCreatedSubscriber.
 */
class SocialAuthSubscriber implements EventSubscriberInterface {

  /**
   * Used to retrieve the token from session.
   *
   * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
   */
  protected $session;

  /**
   * Used to get an instance of the SDK used by the Social Auth implementer.
   *
   * @var \Drupal\social_api\Plugin\NetworkManager
   */
  protected $networkManager;

  /**
   * The Social Auth Google manager.
   *
   * @var \Drupal\social_auth_google\GoogleAuthManager
   */
  protected $googleManager;

  /**
   * SocialAuthSubscriber constructor.
   *
   * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
   *   Used to retrieve the token from session.
   * @param \Drupal\social_api\Plugin\NetworkManager $network_manager
   *   Used to get an instance of the SDK used by the Social Auth implementer.
   * @param \Drupal\social_auth_google\GoogleAuthManager $google_manager
   *   The Social Auth Google manager.
   */
  public function __construct(SessionInterface $session, NetworkManager $network_manager, GoogleAuthManager $google_manager)
  {
    $this->session = $session;
    $this->networkManager = $network_manager;
    $this->googleManager = $google_manager;
  }

  /**
   * Gets the Google user id.
   *
   * @param \Drupal\social_auth\Event\SocialAuthUserEvent $event
   *   The Social Auth dispatched event.
   */
  public function onUserLogin(SocialAuthUserEvent $event) {
     // If user logs in using social_auth_google and the access token exists.
    if ($event->getPluginId() == 'social_auth_google' && $this->session->get('social_auth_google_access_token')) {
      
      /* @var \Google_Client $client */
      $client = $this->networkManager->createInstance('social_auth_google')->getSdk();

      $this->googleManager->setClient($client)
        ->setAccessToken($this->session->get('social_auth_google_access_token'))
        ->authenticate();

      $user = $this->googleManager->getUserInfo();

      drupal_set_message($user->getId());
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[SocialAuthEvents::USER_LOGIN] = ['onUserLogin'];
    return $events;
  }

}

Using the native object

There might be cases in which external libraries would require to use the object returned by the PHP SDK used in the Social Auth implementer. For example, Social Auth Google uses google/google-api-php-client. Through the returning object in $this->networkManager->createInstance('social_auth_google')->getSdk(); you can directly use the \Google_Client object to request data from Google.

  /**
   * Gets the Google user id.
   *
   * @param \Drupal\social_auth\Event\SocialAuthUserEvent $event
   *   The Social Auth dispatched event.
   */
  public function onUserLogin(SocialAuthUserEvent $event) {
     // If user logs in using social_auth_google and the access token exists.
    if ($event->getPluginId() == 'social_auth_google' && $this->session->get('social_auth_google_access_token')) {
      
      /* @var \Google_Client $client */
      $client = $this->networkManager->createInstance('social_auth_google')->getSdk();

      $client->setAccessToken($this->session->get('social_auth_google_access_token'));

      $user = new Google_Service_Oauth2($client)->userinfo->get();

      drupal_set_message($user->getId());
    }
  }

Help improve this page

Page status: No known problems

You can: