Skip to content
Snippets Groups Projects
Commit e34bc3ea authored by Simran's avatar Simran Committed by Christopher C. Wells
Browse files

Issue #3295807 by Simran.67: Update Social Auth LinkedIn for Social Auth 4.0.x

parent 7e92f4f2
Branches
Tags
1 merge request!2Update Social Auth LinkedIn
<ruleset name="drupal/social_auth_linkedin">
<description>Social Auth LinkedIn module CodeSniffer configuration.</description>
<arg name="extensions" value="php,module,inc,install,test,profile,theme,css,info,txt,md,yml"/>
<config name="drupal_core_version" value="8"/>
<file>.</file>
<exclude-pattern>vendor</exclude-pattern>
<rule ref="./vendor/drupal/coder/coder_sniffer/Drupal"/>
<rule ref="./vendor/drupal/coder/coder_sniffer/DrupalPractice"/>
</ruleset>
......@@ -38,10 +38,7 @@
"drupal/coder": "^8.3"
},
"minimum-stability": "dev",
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
"prefer-stable": true
}
<ruleset name="drupal/social_auth_linkedin">
<description>Social Auth Google module CodeSniffer configuration.</description>
<arg name="extensions" value="php,module,inc,install,test,profile,theme,css,info,txt,md,yml"/>
<arg name="basepath" value="."/>
<arg name="colors"/>
<arg name="parallel" value="75"/>
<arg value="p"/>
<config name="drupal_core_version" value="9"/>
<config name="testVersion" value="8.0-" />
<file>.</file>
<exclude-pattern>vendor</exclude-pattern>
<rule ref="./vendor/drupal/coder/coder_sniffer/Drupal"/>
<rule ref="./vendor/drupal/coder/coder_sniffer/DrupalPractice"/>
<rule ref="./vendor/phpcompatibility/php-compatibility/PHPCompatibility"/>
</ruleset>
social_auth_linkedin.settings.tab:
title: 'LinkedIn'
route_name: social_auth_linkedin.settings_form
route_name: social_auth.network.settings_form
route_parameters:
network: 'linkedin'
base_route: social_auth.integrations
social_auth_linkedin.redirect_to_linkedin:
path: 'user/login/linkedin'
defaults:
_controller: '\Drupal\social_auth_linkedin\Controller\LinkedInAuthController::redirectToProvider'
requirements:
# Anonymous users can log in, but authenticated users can also associate a new provider.
_access: 'TRUE'
options:
no_cache: TRUE
social_auth_linkedin.callback:
path: 'user/login/linkedin/callback'
defaults:
_controller: '\Drupal\social_auth_linkedin\Controller\LinkedInAuthController::callback'
requirements:
# Anonymous users can log in, but authenticated users can also associate a new provider.
_access: 'TRUE'
options:
no_cache: TRUE
social_auth_linkedin.settings_form:
path: 'admin/config/social-api/social-auth/linkedin'
defaults:
_title: 'Social Auth LinkedIn settings'
_form: '\Drupal\social_auth_linkedin\Form\LinkedInAuthSettingsForm'
requirements:
_permission: 'administer social api authentication'
<?php
namespace Drupal\social_auth_linkedin\Controller;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\social_api\Plugin\NetworkManager;
use Drupal\social_auth\Controller\OAuth2ControllerBase;
use Drupal\social_auth\SocialAuthDataHandler;
use Drupal\social_auth\User\UserAuthenticator;
use Drupal\social_auth_linkedin\LinkedInAuthManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Returns responses for Social Auth LinkedIn routes.
*/
class LinkedInAuthController extends OAuth2ControllerBase {
/**
* The LinkedIn authentication manager.
*
* @var \Drupal\social_auth_linkedin\LinkedInAuthManager
*/
protected $providerManager;
/**
* LinkedInAuthController constructor.
*
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service.
* @param \Drupal\social_api\Plugin\NetworkManager $network_manager
* Used to get an instance of social_auth_linkedin network plugin.
* @param \Drupal\social_auth\User\UserAuthenticator $user_authenticator
* Manages user login/registration.
* @param \Drupal\social_auth_linkedin\LinkedInAuthManager $linkedIn_manager
* Used to manage authentication methods.
* @param \Symfony\Component\HttpFoundation\RequestStack $request
* Used to access GET parameters.
* @param \Drupal\social_auth\SocialAuthDataHandler $data_handler
* The Social Auth data handler.
* @param \Drupal\Core\Render\RendererInterface $renderer
* Used to handle metadata for redirection to authentication URL.
*/
public function __construct(MessengerInterface $messenger,
NetworkManager $network_manager,
UserAuthenticator $user_authenticator,
LinkedInAuthManager $linkedIn_manager,
RequestStack $request,
SocialAuthDataHandler $data_handler,
RendererInterface $renderer) {
parent::__construct('Social Auth LinkedIn', 'social_auth_linkedin',
$messenger, $network_manager, $user_authenticator,
$linkedIn_manager, $request, $data_handler, $renderer);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('messenger'),
$container->get('plugin.network.manager'),
$container->get('social_auth.user_authenticator'),
$container->get('social_auth_linkedin.manager'),
$container->get('request_stack'),
$container->get('social_auth.data_handler'),
$container->get('renderer')
);
}
/**
* Response for path 'user/login/linkedin/callback'.
*
* LinkedIn returns the user here after user has authenticated.
*/
public function callback() {
// Checks if there was an authentication error.
$redirect = $this->checkAuthError();
if ($redirect) {
return $redirect;
}
/** @var \League\OAuth2\Client\Provider\LinkedInResourceOwner|null $profile */
$profile = $this->processCallback();
// If authentication was successful.
if ($profile !== NULL) {
// Gets (or not) extra initial data.
$data = $this->userAuthenticator->checkProviderIsAssociated($profile->getId()) ? NULL : $this->providerManager->getExtraDetails();
$name = $profile->getFirstName() . ' ' . $profile->getLastName();
$email = $this->providerManager->getEmail();
// If user information could be retrieved.
return $this->userAuthenticator->authenticateUser($name,
$email,
$profile->getId(),
$this->providerManager->getAccessToken(),
$profile->getImageUrl(),
$data);
}
return $this->redirect('user.login');
}
}
<?php
namespace Drupal\social_auth_linkedin\Form;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\social_auth\Form\SocialAuthSettingsForm;
/**
* Settings form for Social Auth LinkedIn.
*/
class LinkedInAuthSettingsForm extends SocialAuthSettingsForm {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'social_auth_linkedin_settings';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return array_merge(
parent::getEditableConfigNames(),
['social_auth_linkedin.settings']
);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('social_auth_linkedin.settings');
$form['linkedin_settings'] = [
'#type' => 'details',
'#title' => $this->t('LinkedIn Client settings'),
'#open' => TRUE,
'#description' => $this->t('You need to first create a LinkedIn App at <a href=":linkedin-dev">:linkedin-dev</a>',
['@linkedin-dev' => 'https://www.linkedin.com/secure/developer']),
];
$form['linkedin_settings']['client_id'] = [
'#type' => 'textfield',
'#required' => TRUE,
'#title' => $this->t('Client ID'),
'#default_value' => $config->get('client_id'),
'#description' => $this->t('Copy the Client ID here.'),
];
$form['linkedin_settings']['client_secret'] = [
'#type' => 'textfield',
'#required' => TRUE,
'#title' => $this->t('Client Secret'),
'#default_value' => $config->get('client_secret'),
'#description' => $this->t('Copy the Client Secret here.'),
];
$form['linkedin_settings']['authorized_redirect_url'] = [
'#type' => 'textfield',
'#disabled' => TRUE,
'#title' => $this->t('Authorized redirect URL'),
'#description' => $this->t('Copy this value to <em>Authorized Redirect URLs</em> field of your LinkedIn App settings.'),
'#default_value' => Url::fromRoute('social_auth_linkedin.callback')->setAbsolute()->toString(),
];
$form['linkedin_settings']['advanced'] = [
'#type' => 'details',
'#title' => $this->t('Advanced settings'),
'#open' => FALSE,
];
$form['linkedin_settings']['advanced']['scopes'] = [
'#type' => 'textarea',
'#title' => $this->t('Scopes for API call'),
'#default_value' => $config->get('scopes'),
'#description' => $this->t('Define any additional scopes to be requested, separated by a comma (e.g.: r_1st_connections,w_member_social).<br>
The scopes \'r_liteprofile\' and \'r_emailaddress\' are added by default and always requested.<br>
You can see the full list of valid fields and required scopes <a href="@fields">here</a>.',
['@fields' => 'https://docs.microsoft.com/en-us/linkedin/consumer/']),
];
$form['linkedin_settings']['advanced']['endpoints'] = [
'#type' => 'textarea',
'#title' => $this->t('API calls to be made to collect data'),
'#default_value' => $config->get('endpoints'),
'#description' => $this->t('Define the endpoints to be requested when user authenticates with LinkedIn for the first time<br>
Enter each endpoint in different lines in the format <em>endpoint</em>|<em>name_of_endpoint</em>.<br>
<b>For instance:</b><br>
/v2/me|profile'),
];
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValues();
$this->config('social_auth_linkedin.settings')
->set('client_id', $values['client_id'])
->set('client_secret', $values['client_secret'])
->set('scopes', $values['scopes'])
->set('endpoints', $values['endpoints'])
->save();
parent::submitForm($form, $form_state);
}
}
......@@ -7,6 +7,8 @@ use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\social_auth\AuthManager\OAuth2Manager;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\social_auth\User\SocialAuthUserInterface;
use Drupal\social_auth\User\SocialAuthUser;
/**
* Contains all the logic for LinkedIn OAuth2 authentication.
......@@ -37,7 +39,7 @@ class LinkedInAuthManager extends OAuth2Manager {
/**
* {@inheritdoc}
*/
public function authenticate() {
public function authenticate(): void {
try {
$this->setAccessToken($this->client->getAccessToken('authorization_code',
['code' => $this->request->query->get('code')]));
......@@ -51,18 +53,26 @@ class LinkedInAuthManager extends OAuth2Manager {
/**
* {@inheritdoc}
*/
public function getUserInfo() {
public function getUserInfo(): SocialAuthUserInterface {
if (!$this->user) {
$this->user = $this->client->getResourceOwner($this->getAccessToken());
/** @var \League\OAuth2\Client\Provider\LinkedInResourceOwner $owner */
$owner = $this->client->getResourceOwner($this->getAccessToken());
$this->user = new SocialAuthUser(
trim("{$owner->getFirstName()} {$owner->getLastName()}"),
$owner->getId(),
$this->getAccessToken(),
$owner->getEmail(),
NULL,
$this->getExtraDetails()
);
}
return $this->user;
}
/**
* {@inheritdoc}
*/
public function getAuthorizationUrl() {
public function getAuthorizationUrl(): string {
$scopes = ['r_liteprofile', 'r_emailaddress'];
$extra_scopes = $this->getScopes();
......@@ -79,7 +89,7 @@ class LinkedInAuthManager extends OAuth2Manager {
/**
* {@inheritdoc}
*/
public function requestEndPoint($method, $path, $domain = NULL, array $options = []) {
public function requestEndPoint(string $method, string $path, ?string $domain = NULL, array $options = []): mixed {
if (!$domain) {
$domain = 'https://api.linkedin.com';
}
......@@ -102,18 +112,8 @@ class LinkedInAuthManager extends OAuth2Manager {
/**
* {@inheritdoc}
*/
public function getState() {
public function getState(): string {
return $this->client->getState();
}
/**
* Gets the email address.
*
* @return string
* The user email address.
*/
public function getEmail() {
return $this->client->getResourceOwnerEmail($this->getAccessToken());
}
}
......@@ -2,11 +2,7 @@
namespace Drupal\social_auth_linkedin\Plugin\Network;
use Drupal\Core\Url;
use Drupal\social_api\SocialApiException;
use Drupal\social_auth\Plugin\Network\NetworkBase;
use Drupal\social_auth_linkedin\Settings\LinkedInAuthSettings;
use League\OAuth2\Client\Provider\LinkedIn;
/**
* Defines a Network Plugin for Social Auth LinkedIn.
......@@ -15,79 +11,23 @@ use League\OAuth2\Client\Provider\LinkedIn;
*
* @Network(
* id = "social_auth_linkedin",
* short_name = "linkedin",
* social_network = "LinkedIn",
* img_path = "img/linkedin_logo.svg",
* type = "social_auth",
* class_name = "\League\OAuth2\Client\Provider\LinkedIn",
* auth_manager = "\Drupal\social_auth_linkedin\LinkedInAuthManager",
* routes = {
* "redirect": "social_auth.network.redirect",
* "callback": "social_auth.network.callback",
* "settings_form": "social_auth.network.settings_form",
* },
* handlers = {
* "settings": {
* "class": "\Drupal\social_auth_linkedin\Settings\LinkedInAuthSettings",
* "class": "\Drupal\social_auth\Settings\SettingsBase",
* "config_id": "social_auth_linkedin.settings"
* }
* }
* )
*/
class LinkedInAuth extends NetworkBase implements LinkedInAuthInterface {
/**
* Sets the underlying SDK library.
*
* @return \League\OAuth2\Client\Provider\LinkedIn|false
* The initialized 3rd party library instance.
*
* @throws \Drupal\social_api\SocialApiException
* If the SDK library does not exist.
*/
protected function initSdk() {
$class_name = '\League\OAuth2\Client\Provider\LinkedIn';
if (!class_exists($class_name)) {
throw new SocialApiException(sprintf('The LinkedIn library for PHP League OAuth2 not found. Class: %s.', $class_name));
}
/** @var \Drupal\social_auth_linkedin\Settings\LinkedInAuthSettings $settings */
$settings = $this->settings;
if ($this->validateConfig($settings)) {
// All these settings are mandatory.
$league_settings = [
'clientId' => $settings->getClientId(),
'clientSecret' => $settings->getClientSecret(),
'redirectUri' => Url::fromRoute('social_auth_linkedin.callback')->setAbsolute()->toString(),
];
// Proxy configuration data for outward proxy.
$config = $this->siteSettings->get('http_client_config');
if (!empty($config['proxy']['http'])) {
$league_settings['proxy'] = $config['proxy']['http'];
}
return new LinkedIn($league_settings);
}
return FALSE;
}
/**
* Checks that module is configured.
*
* @param \Drupal\social_auth_linkedin\Settings\LinkedInAuthSettings $settings
* The LinkedIn auth settings.
*
* @return bool
* True if module is configured.
* False otherwise.
*/
protected function validateConfig(LinkedInAuthSettings $settings) {
$client_id = $settings->getClientId();
$client_secret = $settings->getClientSecret();
if (!$client_id || !$client_secret) {
$this->loggerFactory
->get('social_auth_linkedin')
->error('Define Client ID and Client Secret in module settings.');
return FALSE;
}
return TRUE;
}
}
class LinkedInAuth extends NetworkBase {}
<?php
namespace Drupal\social_auth_linkedin\Plugin\Network;
use Drupal\social_auth\Plugin\Network\NetworkInterface;
/**
* Defines the LinkedIn Auth interface.
*/
interface LinkedInAuthInterface extends NetworkInterface {}
<?php
namespace Drupal\social_auth_linkedin\Settings;
use Drupal\social_api\Settings\SettingsBase;
/**
* Defines methods to get Social Auth LinkedIn settings.
*/
class LinkedInAuthSettings extends SettingsBase implements LinkedInAuthSettingsInterface {
/**
* Client ID.
*
* @var string
*/
protected $clientId;
/**
* Client secret.
*
* @var string
*/
protected $clientSecret;
/**
* {@inheritdoc}
*/
public function getClientId() {
if (!$this->clientId) {
$this->clientId = $this->config->get('client_id');
}
return $this->clientId;
}
/**
* {@inheritdoc}
*/
public function getClientSecret() {
if (!$this->clientSecret) {
$this->clientSecret = $this->config->get('client_secret');
}
return $this->clientSecret;
}
}
<?php
namespace Drupal\social_auth_linkedin\Settings;
/**
* Defines an interface for Social Auth LinkedIn settings.
*/
interface LinkedInAuthSettingsInterface {
/**
* Gets the client ID.
*
* @return string
* The client ID.
*/
public function getClientId();
/**
* Gets the client secret.
*
* @return string
* The client secret.
*/
public function getClientSecret();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment