Skip to content

Commit

Permalink
Merge pull request #18 from openeuropa/OPENEUROPA-1177
Browse files Browse the repository at this point in the history
OPENEUROPA-1177: Consolidate oe_authentication
  • Loading branch information
upchuk authored Aug 29, 2018
2 parents 0e52061 + c4c4e65 commit 75be9ef
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 11 deletions.
20 changes: 20 additions & 0 deletions oe_authentication.module
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/**
* @file
* OpenEuropa Authentication module.
*/

declare(strict_types = 1);

use Drupal\Core\Form\FormStateInterface;

/**
* Implements hook_form_alter().
*/
function oe_authentication_form_user_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$form['account']['mail']['#disabled'] = TRUE;
$form['account']['name']['#disabled'] = TRUE;
unset($form['account']['pass']);
unset($form['account']['current_pass']);
}
2 changes: 1 addition & 1 deletion oe_authentication.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ parameters:
oe_authentication.pcas.base_url: ~
services:
oe_authentication.authentication:
class: \Drupal\oe_authentication\Authentication\Provider\OeAuthentication
class: \Drupal\oe_authentication\Authentication\Provider\Authentication
arguments: ['@oe_authentication.pcas.factory', '@oe_authentication.user_provider']
tags:
- { name: authentication_provider, provider_id: 'oe_authentication', priority: -10, global: TRUE }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/**
* Cookie based authentication provider.
*/
class OeAuthentication implements AuthenticationProviderInterface {
class Authentication implements AuthenticationProviderInterface {

/**
* The pCas variable.
Expand All @@ -29,7 +29,7 @@ class OeAuthentication implements AuthenticationProviderInterface {
protected $userProvider;

/**
* OeAuthentication constructor.
* Authentication constructor.
*
* @param \Drupal\oe_authentication\PCasFactory $pCasFactory
* The pCas variable.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* Returns responses for OE Authentication routes.
*/
class OeAuthenticationController extends ControllerBase {
class AuthenticationController extends ControllerBase {

/**
* The request stack.
Expand Down
10 changes: 10 additions & 0 deletions src/Exception/AuthenticationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types = 1);

namespace Drupal\oe_authentication\Exception;

/**
* Base class for the Open Europa Authentication exceptions.
*/
class AuthenticationException extends \Exception {}
6 changes: 3 additions & 3 deletions src/Routing/RouteSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ protected function alterRoutes(RouteCollection $collection) {
if ($route = $collection->get('user.login')) {
$defaults = $route->getDefaults();
unset($defaults['_form']);
$defaults['_controller'] = '\Drupal\oe_authentication\Controller\OeAuthenticationController::login';
$defaults['_controller'] = '\Drupal\oe_authentication\Controller\AuthenticationController::login';
$route->setDefaults($defaults);
}

// Replace the core logout route.
if ($route = $collection->get('user.logout')) {
$route->setDefault('_controller', '\Drupal\oe_authentication\Controller\OeAuthenticationController::logout');
$route->setDefault('_controller', '\Drupal\oe_authentication\Controller\AuthenticationController::logout');
}
// Remove these routes as to generate fatal errors wherever
// functionality is missing.
Expand All @@ -46,7 +46,7 @@ protected function alterRoutes(RouteCollection $collection) {
];
foreach ($routes_to_remove as $route_to_remove) {
if ($route = $collection->get($route_to_remove)) {
$collection->remove($route_to_remove);
$route->setRequirement('_access', 'FALSE');
}
}
}
Expand Down
41 changes: 37 additions & 4 deletions src/UserProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Drupal\oe_authentication;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\oe_authentication\Exception\AuthenticationException;
use Drupal\user\UserInterface;
use OpenEuropa\pcas\Security\Core\User\PCasUserInterface;

Expand Down Expand Up @@ -84,13 +85,13 @@ protected function attachRoles(UserInterface $account, PCasUserInterface $pCasUs
protected function doLoadAccount(PCasUserInterface $pCasUser) {
$username = $pCasUser->get('cas:user');
if ($username === NULL) {
throw new \Exception('No username found on the PCas user.');
throw new AuthenticationException('No username found on the PCas user.');
}

$accounts = $this->userStorage->loadByProperties(['name' => $username]);
if (empty($accounts)) {
// Account does not exist, creation of new accounts is handled in.
// @see \Drupal\oe_authentication\Controller\OeAuthenticationController::login.
// @see \Drupal\oe_authentication\Controller\AuthenticationController::login.
return FALSE;
}

Expand All @@ -108,8 +109,7 @@ protected function doLoadAccount(PCasUserInterface $pCasUser) {
*/
protected function createAccount(PCasUserInterface $pCasUser) {
$name = $this->uniqueUsername($pCasUser->getUsername());
// @todo Fix the retrieval of the email as not all CAS replies have "cas:email".
$mail = $pCasUser->get('cas:email');
$mail = $this->extractEmailFromCasUser($pCasUser);

/** @var \Drupal\user\Entity\User $account */
$account = $this->userStorage->create([
Expand Down Expand Up @@ -158,4 +158,37 @@ protected function canCreateNewAccounts() {
return TRUE;
}

/**
* Extracts the email address from a PCas user object.
*
* Since CAS implementations return differently the user information,
* we need to extract the email value generically.
*
* @todo Refactor and bring logic for user value retrieval to PCas library
* using configuration.
*
* @param \OpenEuropa\pcas\Security\Core\User\PCasUserInterface $pCasUser
* The PCas user object.
*
* @return string
* The email address.
*/
protected function extractEmailFromCasUser(PCasUserInterface $pCasUser): string {
if ($pCasUser->get('cas:email') !== NULL) {
return $pCasUser->get('cas:email');
}

// ECAS.
if ($pCasUser->get('cas:authenticationFactors') !== NULL) {
$auth_factors = $pCasUser->get('cas:authenticationFactors');
if (isset($auth_factors['cas:moniker'])) {
return $auth_factors['cas:moniker'];
}

throw new AuthenticationException('ECAS user email address is missing.');
}

throw new AuthenticationException('Could not determine user email from PCas response.');
}

}
75 changes: 75 additions & 0 deletions tests/Kernel/PCasFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types = 1);


namespace Drupal\Tests\oe_authentication\Kernel;

use Drupal\KernelTests\KernelTestBase;
use Drupal\oe_authentication\PCasFactory;

/**
* Class InstallationTest.
*/
class PCasFactoryTest extends KernelTestBase {

/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'oe_authentication',
'system',
'user',
];

/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();

$this->installConfig([
'oe_authentication',
]);
}

/**
* Test default configuration options for the PCasFactory class.
*/
public function testDefaultConfiguration(): void {
$pcasfactory = new PCasFactory($this->container->get('session'), $this->container->get('config.factory'));
$pcas = $pcasfactory->getPCas();
$properties = $pcas->getProperties();
$this->assertEquals('http://authentication:8001', $properties['base_url']);
$login_protocol = [
'path' => '/login',
'query' => [],
'allowed_parameters' => ['service', 'renew', 'gateway'],
];
$this->assertEquals($login_protocol, $properties['protocol']['login']);
}

/**
* Test custom configuration options for the PCasFactory class.
*/
public function testCustomConfiguration(): void {
$this->config('oe_authentication.settings')
->set('base_url', 'https://ecas.ec.europa.eu/cas')
->save(TRUE);
$protocols = [
'login' => [
'path' => '/login',
'query' => [],
'allowed_parameters' => ['service', 'renew', 'gateway'],
],
];
$pcasfactory = new PCasFactory($this->container->get('session'), $this->container->get('config.factory'), $protocols);
$pcas = $pcasfactory->getPCas();
$properties = $pcas->getProperties();
$this->assertEquals('https://ecas.ec.europa.eu/cas', $properties['base_url']);
$this->assertEquals($protocols, $properties['protocol']);
}

}

0 comments on commit 75be9ef

Please sign in to comment.