The Drupal Social Initiative was created in 2013 as a Google Summer of Code project. Done so to create a foundation that allows Drupal to authenticate external services. Meaning, a user can register or login to a Drupal site using a social media account, like Facebook or Twitter.
The Social API module is the main hub of this initiative. And it's used to create a framework for other components to plug into. Essentially it acts as a wrapper around OAuth 2.0 integration (an authentication system many social media providers use). If you’ve ever logged into a site with your Google account and seen “this site would like access to these things”, you’ve seen OAuth 2.0.
The initiative itself proves three ways of interacting with Drupal:
- Social Auth provides a mechanism for users to log in or register with your Drupal site. The OAuth account is associated with the Drupal user account.
- Social Post allows your Drupal site to post to a social media account using a certain account. Meaning users could allow the Drupal site to post to Twitter on their behalf.
- Social Widgets provides a way of embedding social media share widgets into your site. For example, Facebook like buttons on node pages etc.
There are examples of each type of module available on Drupal.org. You can integrate your site with Google or Facebook and other providers to allow your users easy access to your site.
All of these integrations are very well documented/ For example, where to go within Google developer console to set up the OAuth 2.0 endpoint and then to integrate this with your Drupal site.
I won’t go into how OAuth 2.0 acts as an authentication system, that would be an article in itself. However, there are some good tutorials.
I decided to see if it was possible to utilise the framework provided by the Social Auth module to integrate with an OAuth 2.0 provider I had created. There are a few options available for OAuth 2.0 authentication servers ranging from standalone applications [https://github.com/bshaffer/oauth2-demo-php] to Drupal modules like OAuth2 server [https://www.drupal.org/project/oauth2_server], that turn Drupal into an authentication server.
You’ll need a way of providing a central mechanism for users to authenticate against your systems. Also, a way of managing those users. Remember, you'll need to separate the client with the authentication server or you’ll have problems.
Using a simple OAuth 2.0 compliant authentication system integrated with the Social Auth framework to authenticate with the server.
The following components are needed:
Social Network Plugin
This class will create the underlying authentication library that will be used to authenticate against your OAuth instance. Looking at the modules that implement Social Auth, there are several ways of doing this.
Some OAuth providers have their own clients for providing authentication. However, several implementations extend a package called OAuth 2.0 Client [https://github.com/thephpleague/oauth2-client], which comes with its own generic authentication client.
As this class is a plugin, it must have an annotation at the start which details what the basic settings of the plugin are. My implementation is:
@Network( id = "social_auth_custom", social_network = "Custom", type = "social_auth", handlers = { "settings": { "class": "\Drupal\social_auth_custom\Settings\CustomAuthSettings", "config_id": "social_auth_custom.settings" } } )
This class must implement a method called initSdk(), which must return an OAuth client. In my example, it generates an instance of GenericProvider.
Settings Object
Social Auth uses an internal setting system to pass settings to your custom authentication class. This object is automatically populated and injected into your network plugin so you can pass these settings over to your OAuth client object. The class should extend the SettingsBase, which is part of the Social Auth module.
Settings Form
As we have a settings object we need some way of filling the object with custom data. This is done via a settings interface provided by the Social Auth module. The form you define here will receive a series of default form elements from Social Auth. It seems like standard practice to inject an additional group of settings into the top of the form as a fieldset.
Don’t forget, you'll need to create a submitForm() method to take the values from your form and inject them into the Drupal configuration.
public function submitForm(array &$form, FormStateInterface $form_state) { $values = $form_state->getValues(); $this->config('social_auth_custom.settings') ->set('consumer_key', $values['consumer_key']) ->set('consumer_secret', $values['consumer_secret']) ->save(); parent::submitForm($form, $form_state); }
This also needs to call the parent form so the core form elements can be saved. This generates the following form in the Social Auth management area:
As this submit handler is setting a configuration value you will need to also set up a configuration schema so Drupal understands how to set the configuration. Here is the schema file I used to create the above configuration settings:
social_auth_custom.settings: type: config_object label: 'Social Auth Custom settings' mapping: consumer_key: type: text label: 'Consumer Key' consumer_secret: type: text label: 'Consumer Secret'
To note, different OAuth providers have different ways of implementing the OAuth standard. As such, you might find the above differs between providers.
Authentication Controller
A Drupal controller is needed to receive the callback from the OAuth provider. Next, this controller extends OAuth2ControllerBase from the Social Auth module. In turn, this extends the usual Drupal ControllerBase class.
During the authentication process, the user will accept the authentication settings on the OAuth server, then this is passed back to the site. Behind the scenes, the OAuth server will send a separate message back to the Drupal site to inform the site of an authenticated user. This happens quickly, so the user is unaware this is happening.
The responsibility of the callback is to then call the OAuth server, verify the correct access tokens, then generate the user. Once the user is created, it is authenticated within Drupal. Following this, the user is fully-fledged in the Drupal site. Some helper methods within the Social Auth module authentication manager class can facilitate these interactions.
Authentication Manager
The authentication manager is used by Social Auth to encapsulate user authentication and generation methods. You can create a custom class to include your own methods here, but it should extend the OAuth2Manager class from the Social Auth module. This custom class should bridge the gap between the settings object and the authentication controller.
Logo
In addition, you might want to include a logo with your module. The logo is used in the Social Auth authentication block where the user selects the OAuth authentication provider.
The logo can be installed when the module is installed using an install hook. There are helper methods in the SocialAuthController class that make this simple.
/** * Implements hook_install(). */ function social_auth_custom_install() { SocialAuthController::setLoginButtonSettings('social_auth_custom', 'social_auth_custom.redirect_to_custom', 'img/custom_logo.svg'); } /** * Implements hook_uninstall(). */ function social_auth_custom_uninstall() { SocialAuthController::deleteLoginButtonSettings('social_auth_custom'); }
Conclusion
With those elements in place, you need to allow users to authenticate against your provider. This is done by adding the Social Auth Login block to your site. Where you put this is up to you, but the block contains a series of logos for the Social Auth providers you have installed. When a user clicks on a provider logo they'll be taken through that provider OAuth 2.0 authentication process.
There's a variety of modules that integrate with Social API. Some are better than others. I tried a few and was able to authenticate against a few without problems.
Using Social Auth is a great way of getting quickly set up with an OAuth 2.0 service and providing an authentication mechanism. You can either use pre-existing packages to allow users to register and authenticate using social media, or roll your own authentication provider in quick order.
If you use an existing package and find problems, the package maintainers would be delighted to hear the fixes.