OK, I'd like to post one more answer approach, using the response event listener (with thanks to @Berdir). This is the one I'm using in the end as it avoids duplicating the login function logic. The previous answer may still be useful if you want to alter the actual login logic flow as well.
The event subscriber class
<?php
namespace Drupal\example\Listener;
use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Serialization\Xml;
use Drupal\Component\Serialization\Json;
/**
* Class ExampleLoginListener.
*
* @package Drupal\example
*/
class ExampleLoginListener implements EventSubscriberInterface
{
/**
* @var path.current service
*/
private $currentPath;
/**
* @var jwt.authentication.jwt service
*/
private $jwtAuth;
/**
* Constructor with dependency injection
*/
public function __construct($currentPath, $JwtAuth) {
$this->currentPath = $currentPath;
$this->jwtAuth = $JwtAuth;
}
/**
* Add JWT access token to user login API response
*/
public function onHttpLoginResponse(FilterResponseEvent $event) {
// Halt if not user login request
if ($this->currentPath->getPath() !== '/user/login') {
return;
}
// Get response
$response = $event->getResponse();
// Ensure not error response
if ($response->getStatusCode() !== 200) {
return;
}
// Get request
$request = $event->getRequest();
// Just handle JSON format for now
if ($request->query->get('_format') !== 'json') {
return;
}
// Decode and add JWT token
if ($content = $response->getContent()) {
if ($decoded = Json::decode($content)) {
// Add JWT access_token
$access_token = $this->jwtAuth->generateToken();
$decoded['access_token'] = $access_token;
// Set new response JSON
$response->setContent(Json::encode($decoded));
$event->setResponse($response);
}
}
}
/**
* The subscribed events.
*/
public static function getSubscribedEvents() {
$events = [];
$events[KernelEvents::RESPONSE][] = ['onHttpLoginResponse'];
return $events;
}
}
and the example.services.yml
entry
services:
example.login_response_listener:
class: '\Drupal\example\Listener\ExampleLoginListener'
arguments: ['@path.current', '@jwt.authentication.jwt']
tags:
- { name: event_subscriber }
In this way, we can add the JWT access_token
to the /user/login?_format=json
API response.