bankid_oidc-1.x-dev/src/BankIdAuth.php
src/BankIdAuth.php
<?php
namespace Drupal\bankid_oidc;
use BankID\OAuth2\Client\Provider\BankIdProvider;
use BankID\OAuth2\Client\Token\AccessToken;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Url;
use Drupal\externalauth\ExternalAuthInterface;
use Drupal\user\UserDataInterface;
use Drupal\user\UserInterface;
use League\OAuth2\Client\Token\AccessTokenInterface;
use Psr\Log\LoggerInterface;
/**
* UserAuth service.
*/
class BankIdAuth implements BankIdAuthInterface {
/**
* @var \BankID\OAuth2\Client\Provider\BankIdProvider
*/
protected $oauthClient;
/**
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $config;
/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* The externalauth.externalauth service.
*
* @var \Drupal\externalauth\ExternalAuthInterface
*/
protected $authService;
/**
* Constructs an BankIdAuth service.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config.factory service
* @param \Psr\Log\LoggerInterface $logger
* The logger.channel.bankid_oidc service
* @param \Drupal\user\UserDataInterface $user_data
* The user.data service.
* @param \Drupal\externalauth\ExternalAuthInterface $externalauth
* The externalauth.externalauth service.
*/
public function __construct(
ConfigFactoryInterface $config_factory,
LoggerInterface $logger,
UserDataInterface $user_data,
ExternalAuthInterface $externalauth
) {
$this->authService = $externalauth;
$this->logger = $logger;
$this->userData = $user_data;
$this->configFactory = $config_factory;
}
/**
* @inheritdoc
*/
public function authenticate(AccessToken $access_token): UserInterface {
$userInfo = $access_token->getIdToken();
$profile = $this->oauthClient()->getResourceOwner($access_token);
$email = $profile->getEmail();
if (empty($email)) {
$email = $userInfo->getBankIdSubjectIdentifier() . '@bankid';
$message = 'No e-mail address provided, using fallback value: @mail';
$this->logger->info(t($message, ['@mail' => $email]));
}
// The username in drupal can only be 60 character maximum, so we need to
// truncate the length of the generated username to match.
$username = $profile->getName();
$oidc_sub = $userInfo->getSubjectIdentifier();
if (mb_strlen($username) > UserInterface::USERNAME_MAX_LENGTH) {
$this->logger->warning(t('User name exceeds Drupal username max length: @name', ['@name' => $username]));
// EdgeC ase: If the name alone is longer than 60 chars just use the OIDC Subject identifier
$username = $oidc_sub;
}
else {
// Get a shorter OIDC Sub. if the total length of name + oidc sub is larger than allowed.
// Include also 10 extra chars for space, parenthesis and ellipses.
$max_length = UserInterface::USERNAME_MAX_LENGTH - 10 - mb_strlen($username);
if (strlen($oidc_sub) > $max_length) {
$oidc_sub = substr($oidc_sub, 0, $max_length) . '...';
}
$username .= " ({$oidc_sub})";
}
$userData = [
'name' => $username,
'mail' => $email,
'init' => 'bankid-sub--' . $userInfo->getBankIdSubjectIdentifier(),
];
$user = $this->authService->loginRegister(
$userInfo->getSubjectIdentifier(),
BankIdAuthInterface::AUTH_NAMESPACE,
$userData
);
$this->setUserAccessToken($user, $access_token);
return $user;
}
/**
* @inheritdoc
*/
public function oauthClient(): BankIdProvider {
if (!$this->oauthClient) {
$options = $this->getOauthOptions();
$environment = $this->getConfig()->get('environment');
$this->oauthClient = BankIdProvider::createForEnvironment(
$environment,
$options
);
}
return $this->oauthClient;
}
protected function getOauthOptions(): array {
$config = $this->getConfig();
// Override with the correct value from the Key module.
if (\Drupal::moduleHandler()->moduleExists('key')) {
$key_name = $config->get('client_secret');
/** @var \Drupal\key\Entity\Key $key */
$key = \Drupal::service('key.repository')->getKey($key_name);
$options['clientSecret'] = $key->getKeyValue();
}
else {
$options['clientSecret'] = $config->get('client_secret');
}
$options['clientId'] = $config->get('client_id');
$options['scopes'] = array_keys(array_filter($config->get('scopes')));
$options['redirectUri'] = Url::fromRoute('bankid_oidc.redirect')
->setAbsolute(TRUE)
->toString(TRUE)
->getGeneratedUrl();
return $options;
}
protected function getConfig(): ImmutableConfig {
if (!$this->config) {
$this->config = $this->configFactory->get('bankid_oidc.config');
}
return $this->config;
}
protected function setUserAccessToken(
UserInterface $user,
AccessTokenInterface $access_token
): void {
$this->userData->set(
BankIdAuthInterface::AUTH_NAMESPACE,
$user->id(),
'access_token',
$access_token
);
}
}
