Skip to content

Commit

Permalink
Disable external user password on login and deploy
Browse files Browse the repository at this point in the history
  • Loading branch information
hyrsky committed Jun 17, 2024
1 parent e968d82 commit 49afbc6
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 5 deletions.
9 changes: 9 additions & 0 deletions helfi_tunnistamo.module
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ function helfi_tunnistamo_openid_connect_post_authorize(UserInterface $account,
}
$plugin->mapRoles($account, $context);
$plugin->setUserPreferredAdminLanguage($account);

// Once user logs in with openid connect, set user password to null.
// This prevents the user from logging in with the local user in the
// future.
if ($account->getPassword()) {
$account
->setPassword(NULL)
->save();
}
}

/**
Expand Down
12 changes: 7 additions & 5 deletions helfi_tunnistamo.services.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
services:
helfi_tunnistamo.http_exception_subscriber:
class: Drupal\helfi_tunnistamo\EventSubscriber\HttpExceptionSubscriber
arguments: ['@entity_type.manager', '@openid_connect.session', '@current_user']
tags:
- { name: event_subscriber }
_defaults:
autowire: true
autoconfigure: true

logger.channel.helfi_tunnistamo:
parent: logger.channel_base
arguments: [ 'helfi_tunnistamo' ]

Drupal\helfi_tunnistamo\EventSubscriber\HttpExceptionSubscriber: ~
Drupal\helfi_tunnistamo\EventSubscriber\DisableExternalUsersPasswordSubscriber: ~
59 changes: 59 additions & 0 deletions src/EventSubscriber/DisableExternalUsersPasswordSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Drupal\helfi_tunnistamo\EventSubscriber;

use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\helfi_api_base\EventSubscriber\DeployHookEventSubscriberBase;
use Symfony\Contracts\EventDispatcher\Event;

/**
* Sets tunnistamo users' password to NULL.
*
* This should prevent given users from logging in using password.
*/
final class DisableExternalUsersPasswordSubscriber extends DeployHookEventSubscriberBase {

/**
* Constructs a new instance.
*
* @param \Drupal\Core\Database\Connection $database
* Database connection.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
*/
public function __construct(
private readonly Connection $database,
private readonly EntityTypeManagerInterface $entityTypeManager,
) {
}

/**
* {@inheritdoc}
*/
public function onPostDeploy(Event $event) : void {
// Query tunnistamo users that have their passwords set.
$query = $this->database->select('authmap', 'am');
$query->leftJoin('users_field_data', 'ufd', 'ufd.uid = am.uid');
$query
->fields('am', ['uid'])
->condition('ufd.pass', NULL, 'IS NOT NULL')
// Make sure we have an upper bound.
->range(0, 50);

$storage = $this->entityTypeManager->getStorage('user');
foreach ($query->execute()->fetchCol() as $id) {
/** @var \Drupal\user\UserInterface $account */
$account = $storage->load($id);

// Set user password to null. This prevents the user
// from logging in with the local user in the future.
$account
->setPassword(NULL)
->save();
}
}

}
2 changes: 2 additions & 0 deletions src/EventSubscriber/HttpExceptionSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\helfi_tunnistamo\Plugin\OpenIDConnectClient\Tunnistamo;
use Drupal\openid_connect\OpenIDConnectSession;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;

/**
Expand All @@ -28,6 +29,7 @@ final class HttpExceptionSubscriber extends HttpExceptionSubscriberBase {
*/
public function __construct(
private EntityTypeManagerInterface $entityTypeManager,
#[Autowire(service: 'openid_connect.session')]
private OpenIDConnectSession $session,
private AccountProxyInterface $accountProxy,
) {
Expand Down
52 changes: 52 additions & 0 deletions tests/src/Kernel/DisableExternalUsersPasswordSubscriberTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Drupal\Tests\helfi_tunnistamo\Kernel;

use Drupal\helfi_api_base\Event\PostDeployEvent;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\user\Entity\User;

/**
* Tests disable local users subscriber.
*
* @group helfi_tunnistamo
*/
class DisableExternalUsersPasswordSubscriberTest extends KernelTestBase {

use UserCreationTrait;

/**
* Tests that deploy prevents external users from logging in with password.
*/
public function testSubscriber() : void {
/** @var \Drupal\externalauth\Authmap $authmap */
$authmap = $this->container->get('externalauth.authmap');
$external = $this->createUser(values: ['pass' => '123']);
$local = $this->createUser(values: ['pass' => '123']);

// Add external auth to user.
$authmap->save($external, 'test_provider', 'test_authname');

// User login is enabled.
$this->assertNotEmpty($external->getPassword());
$this->assertNotEmpty($local->getPassword());

$this->triggerEvent();

// User password is disabled.
$this->assertEmpty(User::load($external->id())->getPassword());
$this->assertNotEmpty(User::load($local->id())->getPassword());
}

/**
* Triggers the post deploy event.
*/
private function triggerEvent() : void {
/** @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $service */
$service = $this->container->get('event_dispatcher');
$service->dispatch(new PostDeployEvent());
}

}

0 comments on commit 49afbc6

Please sign in to comment.