Drupal modules for browsing and managing Fedora-based digital repositories.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

152 lines
4.2 KiB

<?php
namespace Drupal\islandora\EventSubscriber;
use Drupal\islandora\Form\IslandoraSettingsForm;
use Drupal\jwt\Authentication\Event\JwtAuthValidateEvent;
use Drupal\jwt\Authentication\Event\JwtAuthValidEvent;
use Drupal\jwt\Authentication\Event\JwtAuthGenerateEvent;
use Drupal\jwt\Authentication\Event\JwtAuthEvents;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Subscribes to Jwt Events.
*
* @package Drupal\islandora\EventSubscriber
*/
class JwtEventSubscriber implements EventSubscriberInterface {
const AUDIENCE = 'islandora';
/**
* User storage to load users.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $userStorage;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructor.
*
* @param \Drupal\Core\Entity\EntityStorageInterface $userStorage
* User storage to load users.
* @param \Drupal\Core\Session\AccountInterface $user
* The current user.
*/
public function __construct(
EntityStorageInterface $userStorage,
AccountInterface $user
) {
$this->userStorage = $userStorage;
$this->currentUser = $user;
}
/**
* Factory.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityManager
* Entity manager to get user storage.
* @param \Drupal\Core\Session\AccountInterface $user
* The current user.
*/
public static function create(
EntityTypeManagerInterface $entityManager,
AccountInterface $user
) {
return new static(
$entityManager->getStorage('user'),
$user
);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[JwtAuthEvents::VALIDATE][] = ['validate'];
$events[JwtAuthEvents::VALID][] = ['loadUser'];
$events[JwtAuthEvents::GENERATE][] = ['setIslandoraClaims'];
return $events;
}
/**
* Sets claims for a Islandora consumer on the JWT.
*
* @param \Drupal\jwt\Authentication\Event\JwtAuthGenerateEvent $event
* The event.
*/
public function setIslandoraClaims(JwtAuthGenerateEvent $event) {
global $base_secure_url;
// Standard claims, validated at JWT validation time.
$event->addClaim('iat', time());
$expiry_setting = \Drupal::config(IslandoraSettingsForm::CONFIG_NAME)
->get(IslandoraSettingsForm::JWT_EXPIRY);
$expiry = $expiry_setting ? $expiry_setting : '+2 hour';
$event->addClaim('exp', strtotime($expiry));
$event->addClaim('webid', $this->currentUser->id());
$event->addClaim('iss', $base_secure_url);
// Islandora claims we need to validate.
$event->addClaim('sub', $this->currentUser->getAccountName());
$event->addClaim('roles', $this->currentUser->getRoles(FALSE));
$event->addClaim('aud', [static::AUDIENCE]);
}
/**
* Validates that the Islandora data is present in the JWT.
*
* @param \Drupal\jwt\Authentication\Event\JwtAuthValidateEvent $event
* A JwtAuth event.
*/
public function validate(JwtAuthValidateEvent $event) {
$token = $event->getToken();
if (!in_array(static::AUDIENCE, $token->getClaim('aud'), TRUE)) {
$event->invalidate('Missing audience entry.');
}
$uid = $token->getClaim('webid');
$name = $token->getClaim('sub');
$roles = $token->getClaim('roles');
$url = $token->getClaim('iss');
if ($uid === NULL || $name === NULL || $roles === NULL || $url === NULL) {
$event->invalidate("Expected data missing from payload.");
return;
}
$user = $this->userStorage->load($uid);
if ($user === NULL) {
$event->invalidate("Specified UID does not exist.");
}
elseif ($user->getAccountName() !== $name) {
$event->invalidate("Account name does not match.");
}
}
/**
* Load and set a Drupal user to be authentication based on the JWT's uid.
*
* @param \Drupal\jwt\Authentication\Event\JwtAuthValidEvent $event
* A JwtAuth event.
*/
public function loadUser(JwtAuthValidEvent $event) {
$token = $event->getToken();
$uid = $token->getClaim('webid');
$user = $this->userStorage->load($uid);
$event->setUser($user);
}
}