diff --git a/uib_feide.module b/uib_feide.module index 09cac1c35530cbf8dbd1be6c96578cc185605b8b..c33a656867bf9c5304444ef284a11e01aa5ab170 100644 --- a/uib_feide.module +++ b/uib_feide.module @@ -8,15 +8,23 @@ * Feide OpenID connection. */ -use Drupal\Component\Plugin\Exception\PluginException; - /** * Implements hook_openid_connect_userinfo_alter(). */ function uib_feide_openid_connect_userinfo_alter(#[\SensitiveParameter] array &$userinfo, #[\SensitiveParameter] array $context) : void { - // Check if the claim exists within $userinfo before trying to access it. - if (isset($userinfo['https://n.feide.no/claims/eduPersonPrincipalName'])) { - $userinfo['preferred_username'] = $userinfo['https://n.feide.no/claims/eduPersonPrincipalName']; + $userinfo['preferred_username'] = $userinfo['https://n.feide.no/claims/eduPersonPrincipalName'] ?? $userinfo['email']; + + /** @var GuzzleHttp\Client $response */ + $response = Drupal::service('http_client')->request( + 'GET', + 'https://api.dataporten.no/userinfo/v1/userinfo', + ['headers' => ['Authorization' => 'Bearer ' . $context['tokens']['access_token']]]); + $extUserInfo = json_decode($response->getBody(), TRUE); + $userinfo['groups'] = []; + if (count($extUserInfo) > 1 && isset($extUserInfo['eduPersonEntitlement'])) { + foreach ($extUserInfo['eduPersonEntitlement'] as $group) { + $userinfo['groups'][] = Roles::{Roles::from($group)->name}->getRole(); + } } } @@ -24,54 +32,40 @@ function uib_feide_openid_connect_userinfo_alter(#[\SensitiveParameter] array &$ * Implements hook_openid_connect_pre_authorize(). */ function uib_feide_openid_connect_pre_authorize($account, array $context) : bool { - $domain_matches = FALSE; - $role_matches = FALSE; - - // Retrieve the 'uib_feide' settings. - $config = Drupal::config('uib_feide.user_control_settings'); - - if ($config->get('domains_allowed') !== '') { - /** @var Drupal\uib_api_connector\ApiConnectorPluginManager $api_service */ - $api_service = Drupal::service('plugin.manager.api_connector'); - /** @var \Drupal\uib_profile\Plugin\ApiConnector\ScimConnector $scim_connector */ - - try { - $scim_connector = $api_service->createInstance('scim'); - } - catch (PluginException $e) { - return FALSE; + if ($account) { + foreach (Roles::cases() as $role) { + if ($account->hasRole($role->name)) { + $account->removeRole($role->name); + } } - $scim_data = $scim_connector->fetchScimUser($context['userinfo']['email']); - if ($scim_data !== FALSE) { - $roles = $scim_data->getRoles(); - - // Check if the user has the correct domain. - $domains_allowed = explode("\r", str_replace(["\r\n", "\n"], "\r", $config->get('domains_allowed') ?: '')); - $email_account_for_new_user = $context['userinfo']['email']; + foreach ($context['userinfo']['groups'] as $group) { + $account->addRole($group); + } + } - if (str_contains($email_account_for_new_user, '@')) { - $domain_for_new_user = explode('@', $email_account_for_new_user)[1]; - if (in_array($domain_for_new_user, $domains_allowed)) { - $domain_matches = TRUE; - } - } + if (count($context['userinfo']['groups']) === 0) { + return FALSE; + } - // Check if the user has the correct variable. - $roles_allowed = explode("\r", str_replace(["\r\n", "\n"], "\r", $config->get('roles_allowed') ?: '')); + return TRUE; +} - // Check each setting. - foreach ($roles_allowed as $role) { - if (in_array($role, $roles)) { - $role_matches = TRUE; - break; - } - } +/** + * Enum maintaining drupal roles and the associated group definitions in FEIDE. + */ +enum Roles: string { + case StudyProgramContributor = 'https://api.uib.no/names/roles/eksternweb/uibno_studies_and_students_author'; + case StudyProgramEditor = 'https://api.uib.no/names/roles/eksternweb/uibno_studies_and_students_manager'; - // If both the domain and role matches, then proceed to log in. - return $domain_matches && $role_matches; - } + /** + * Function mapping drupal roles to enum cases. + */ + public function getRole(): string { + return match ($this) { + Roles::StudyProgramContributor => 'study_program_contributor', + Roles::StudyProgramEditor => 'study_program_editor', + }; } - return TRUE; }