Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 60 additions & 55 deletions cwd_saml_mapping.module
Original file line number Diff line number Diff line change
Expand Up @@ -19,46 +19,46 @@ function cwd_saml_mapping_saml_sp_drupal_login_user_attributes_alter($user, $att
$entity_ids = \Drupal::entityQuery('saml_role_mapping')->condition('status', 1)->execute();
$configs = \Drupal::entityTypeManager()->getStorage('saml_role_mapping')->loadMultiple($entity_ids);
//Variables for storing data and signaling a user save is needed.
$saveUser = false;
$saveUser = FALSE;
$samlManagedRoles = [];
$userRolesToAdd = [];
$saml_property_mappings = ShibbolethHelper::getMappingArray();
$missing_property_messages = [];
$rolesUnableToEvaluateForRemoval = [];
foreach ($configs as $role_assigment_config) {
//Create a list of all roles managed by saml properties
$needsRole = false;
$needsRole = FALSE;
$role = $role_assigment_config->get('role');
if (!in_array($role, $samlManagedRoles)) {
$samlManagedRoles[] = $role;
}

//Property in saml we are looking at
$samlprop = $role_assigment_config->get('samlprop');
if($samlprop == "other") {
if ($samlprop == "other") {
$samlprop = $role_assigment_config->get('samlother');
}

//Drupal's accepted values we configure on our end
$values = explode("\r\n", $role_assigment_config->get('values'));


//Catch condition the property is not release to us from shibboleth (ex. Test Shibboleth does no release groups property)
if (!array_key_exists($samlprop, $attributes)) {
$missing_property_messages[] = $saml_property_mappings[$samlprop] . " => " . $role_assigment_config->get('id');
$missing_property_messages[] = $saml_property_mappings[$samlprop] . " => " . $role_assigment_config->get('id');
$rolesUnableToEvaluateForRemoval[] = $role;
continue;
}

//Catch condition that the property is released but has no data
//Catch condition that the property is released but has no data
if (is_null($attributes[$samlprop])) {
\Drupal::logger('cwd_saml_mapping')->warning("Shibboleth data not found for " . $saml_property_mappings[$samlprop] . " need to check the saml_role_mapping configuration for " . $role_assigment_config->get('id'));
$rolesUnableToEvaluateForRemoval[] = $role;
continue;
}

$specialmatchcriteria = $role_assigment_config->get('specialmatchcriteria') ?? "none";
switch($specialmatchcriteria) {
switch ($specialmatchcriteria) {
case "none":
//If saml attribute has more than one value in a field we will look at all values
if (count($attributes[$samlprop]) > 1) {
Expand All @@ -76,14 +76,14 @@ function cwd_saml_mapping_saml_sp_drupal_login_user_attributes_alter($user, $att
if (count($attributes[$samlprop]) > 1) {
$saml_pro_data = $attributes[$samlprop];
//Search each saml data element in array if it contains any of the accepted values
foreach($saml_pro_data as $saml_data_element) {
if($needsRole) {
foreach ($saml_pro_data as $saml_data_element) {
if ($needsRole) {
break;
}
//Find any partial containing match of the value we are searching for
foreach($values as $stringtofind) {
if(str_contains($saml_data_element,$stringtofind)) {
$needsRole = true;
foreach ($values as $stringtofind) {
if (str_contains($saml_data_element, $stringtofind)) {
$needsRole = TRUE;
break;
}
}
Expand All @@ -93,9 +93,9 @@ function cwd_saml_mapping_saml_sp_drupal_login_user_attributes_alter($user, $att
//Single valued saml property
$saml_pro_data = $attributes[$samlprop][0];
//Check if the saml data contains any of our accepted values
foreach($values as $stringtofind) {
if(str_contains($saml_pro_data,$stringtofind)) {
$needsRole = true;
foreach ($values as $stringtofind) {
if (str_contains($saml_pro_data, $stringtofind)) {
$needsRole = TRUE;
break;
}
}
Expand All @@ -110,9 +110,9 @@ function cwd_saml_mapping_saml_sp_drupal_login_user_attributes_alter($user, $att
$userRolesToAdd[] = $role;
}
} // end of for loop processing saml_role_mapping configs

//Log message about configurations with missing properties
if(count($missing_property_messages) > 0) {
if (count($missing_property_messages) > 0) {
$message = "Property not found in Shibboleth data found for [" . implode("] , [", $missing_property_messages) . "]";
\Drupal::logger('cwd_saml_mapping')->info($message);
}
Expand All @@ -121,18 +121,22 @@ function cwd_saml_mapping_saml_sp_drupal_login_user_attributes_alter($user, $att
foreach ($userRolesToAdd as $roleToAdd) {
if (!$user->hasRole($roleToAdd)) {
$user->addRole($roleToAdd);
$saveUser = true;
$saveUser = TRUE;
}
}

//Compute roles we need to take away and remove if needed
$userRolesToRemove = array_diff($samlManagedRoles, $userRolesToAdd);
//Don't remove roles we don't have all the properties from shibboleth to evaluate
$userRolesToRemove = array_diff($userRolesToRemove,$rolesUnableToEvaluateForRemoval);
foreach ($userRolesToRemove as $roleToRemove) {
if ($user->hasRole($roleToRemove)) {
$user->removeRole($roleToRemove);
$saveUser = true;
$config = \Drupal::config('cwd_saml_mapping.config_form');
$should_remove_roles = $config->getRawData()['remove_roles'] ?? TRUE;
if ($should_remove_roles) {
//Compute roles we need to take away and remove if needed
$userRolesToRemove = array_diff($samlManagedRoles, $userRolesToAdd);
//Don't remove roles we don't have all the properties from shibboleth to evaluate
$userRolesToRemove = array_diff($userRolesToRemove, $rolesUnableToEvaluateForRemoval);
foreach ($userRolesToRemove as $roleToRemove) {
if ($user->hasRole($roleToRemove)) {
$user->removeRole($roleToRemove);
$saveUser = TRUE;
}
}
}

Expand All @@ -149,7 +153,7 @@ function cwd_saml_mapping_saml_sp_drupal_login_user_attributes_alter($user, $att
$new_user_name = $attributes[$username_saml_prop][0];
if ($user->name != $new_user_name) {
$user->name = $attributes[$username_saml_prop];
$saveUser = true;
$saveUser = TRUE;
}
//-------------------------------------------------------------------------------------
// End of use global config to set user name
Expand All @@ -176,7 +180,7 @@ function cwd_saml_mapping_saml_sp_drupal_login_user_attributes_alter($user, $att
}
if ($current_field_value != $new_field_value) {
$user->{$field_mapping_config->get('field')} = $new_field_value;
$saveUser = true;
$saveUser = TRUE;
}
}
//-------------------------------------------------------------------------------------
Expand Down Expand Up @@ -206,9 +210,9 @@ function cwd_saml_mapping_preprocess_item_list(&$variables) {
$config = \Drupal::config('cwd_saml_mapping.config_form');
$show_all_idps = $config->getRawData()['show_all_idps'];

if($show_all_idps) {
if ($show_all_idps) {
foreach ($variables['items'] as $index => $link) {
$idp_name = $link['value']->getText()->getArguments()['%idp'] ?? null;
$idp_name = $link['value']->getText()->getArguments()['%idp'] ?? NULL;
$idp_class = strtolower(preg_replace("/\s+/", "_", $idp_name));
$link['value']->setText(new TranslatableMarkup($idp_name . " Login"));
$link['attributes']->addClass(['login-link-button', $idp_class]);
Expand All @@ -227,7 +231,7 @@ function cwd_saml_mapping_preprocess_item_list(&$variables) {
elseif (get_class($link['value']) != "Drupal\Core\Link") {
continue;
}
$idp_name = $link['value']->getText()->getArguments()['%idp'] ?? null;
$idp_name = $link['value']->getText()->getArguments()['%idp'] ?? NULL;
$idp_class = strtolower(preg_replace("/\s+/", "_", $idp_name));
if ($idp_name && str_contains(strtolower(($idp_name)), "test") && !$show_all_idps) {
unset($variables['items'][$index]);
Expand All @@ -248,7 +252,7 @@ function cwd_saml_mapping_preprocess_item_list(&$variables) {
elseif (get_class($link['value']) != "Drupal\Core\Link") {
continue;
}
$idp_name = $link['value']->getText()->getArguments()['%idp'] ?? null;
$idp_name = $link['value']->getText()->getArguments()['%idp'] ?? NULL;
$idp_class = strtolower(preg_replace("/\s+/", "_", $idp_name));
if ($idp_name && str_contains(strtolower(($idp_name)), "prod") && !$show_all_idps) {
unset($variables['items'][$index]);
Expand All @@ -265,24 +269,25 @@ function cwd_saml_mapping_form_alter(&$form, \Drupal\Core\Form\FormStateInterfac
if ($form_id == 'user_login_form') {
$config = \Drupal::config('cwd_saml_mapping.config_form');
$form['#cache'] = ['max-age' => 0];
$hide_drupal_login_prod = $config->getRawData()['hide_drupal_login_prod'] ?? false;

$hide_drupal_login_prod = $config->getRawData()['hide_drupal_login_prod'] ?? FALSE;
$is_prod_and_hide = (isset($_ENV['PANTHEON_ENVIRONMENT']) && $_ENV['PANTHEON_ENVIRONMENT'] === 'live' && $hide_drupal_login_prod);
$hide_drupal_login = $config->getRawData()['hide_drupal_login'] ?? false;
$hide_drupal_login = $config->getRawData()['hide_drupal_login'] ?? FALSE;

$sso_text = $config->getRawData()['sso_text'] ?? "Login with your NetID";
$form['new'] = array(
'#markup' => '<hr/><h2>' . $sso_text . ':</h2>',
'#weight' => -999,
);

if($hide_drupal_login || $is_prod_and_hide) {
if ($hide_drupal_login || $is_prod_and_hide) {
unset($form['name']);
unset($form['pass']);
unset($form['actions']);
unset($form['#submit']);
return;
} else {
}
else {
$form['#submit'][] = 'cwd_saml_mapping_user_login_form_submit';
}

Expand All @@ -291,11 +296,11 @@ function cwd_saml_mapping_form_alter(&$form, \Drupal\Core\Form\FormStateInterfac
$form['pass']['#weight'] = 9999;
$form['actions']['#weight'] = 9999;
$form['orstatement'] = array(
'#markup' => '<hr/><h2>'.$drupal_login_text.':</h2>',
'#markup' => '<hr/><h2>' . $drupal_login_text . ':</h2>',
'#weight' => 9998,
);
unset($form['name']['#attributes']['autofocus']);

}
}

Expand All @@ -304,7 +309,7 @@ function cwd_saml_mapping_form_alter(&$form, \Drupal\Core\Form\FormStateInterfac
*/
function cwd_saml_mapping_user_login_form_submit($form, FormStateInterface $form_state) {
$current_path = \Drupal::service('path.current')->getPath();
if(empty($form_state->getRedirect())) {
if (empty($form_state->getRedirect())) {
$current_path = Url::fromUserInput($current_path);
$form_state->setRedirectUrl($current_path);
}
Expand All @@ -313,13 +318,13 @@ function cwd_saml_mapping_user_login_form_submit($form, FormStateInterface $form

function cwd_saml_mapping_local_tasks_alter(&$local_tasks) {
$config = \Drupal::config('cwd_saml_mapping.config_form');
$hide_drupal_login_prod = $config->getRawData()['hide_drupal_login_prod'] ?? false;
$hide_drupal_login_prod = $config->getRawData()['hide_drupal_login_prod'] ?? FALSE;
$is_prod_and_hide = (isset($_ENV['PANTHEON_ENVIRONMENT']) && $_ENV['PANTHEON_ENVIRONMENT'] === 'live' && $hide_drupal_login_prod);
$hide_drupal_login = $config->getRawData()['hide_drupal_login'] ?? false;
if($hide_drupal_login || $is_prod_and_hide) {
$hide_drupal_login = $config->getRawData()['hide_drupal_login'] ?? FALSE;
if ($hide_drupal_login || $is_prod_and_hide) {
unset($local_tasks['user.register']);
unset($local_tasks['user.login']);
}
}
}

function cwd_saml_mapping_user_login(UserInterface $account) {
Expand All @@ -330,7 +335,7 @@ function cwd_saml_mapping_user_login(UserInterface $account) {
return;
}
$entity_ids = \Drupal::entityQuery('saml_login_redirect')->condition('status', 1)->execute();
if($entity_ids == null) {
if ($entity_ids == NULL) {
return;
}

Expand All @@ -351,13 +356,13 @@ function cwd_saml_mapping_user_login(UserInterface $account) {
\Drupal::service('request_stack')->getCurrentRequest()->query->set('destination', $redirect);
return;
}

}
}
function cwd_saml_mapping_user_logout($account) {

$entity_ids = \Drupal::entityQuery('saml_logout_redirect')->condition('status', 1)->execute();
if($entity_ids == null) {
if ($entity_ids == NULL) {
return;
}

Expand All @@ -378,7 +383,7 @@ function cwd_saml_mapping_user_logout($account) {
\Drupal::service('request_stack')->getCurrentRequest()->query->set('destination', $redirect);
return;
}

}
}

Expand All @@ -398,23 +403,23 @@ function _cwd_saml_mapping_return_token_url($redirect_string, $account) {

function cwd_saml_mapping_preprocess_page(&$variables) {
$config = \Drupal::config('cwd_saml_mapping.config_form');
$restrict_all_pages = $config->getRawData()['restrict_all_pages'] ?? false;
if($restrict_all_pages) {
$restrict_all_pages = $config->getRawData()['restrict_all_pages'] ?? FALSE;
if ($restrict_all_pages) {
$allowed_paths = [
"/user/login",
"/accessdenied",
];

$restriction_choice = $config->getRawData()['restrict_pages_url'];
switch($restriction_choice) {
switch ($restriction_choice) {
case "direct":
$url_string = "/saml/drupal_login";
$samlsp_login_config = \Drupal::config('saml_sp_drupal_login.config');
$idps = $samlsp_login_config->getRawData()['idp'];
if (isset($_ENV['PANTHEON_ENVIRONMENT']) && $_ENV['PANTHEON_ENVIRONMENT'] === 'live') {
$url_string .= "/" . $idps['cornell_prod'];
}
else {
else {
$url_string .= "/" . $idps['cornell_test'];
}
break;
Expand All @@ -426,9 +431,9 @@ function cwd_saml_mapping_preprocess_page(&$variables) {

$current_user = \Drupal::currentUser();
$current_path = \Drupal::service('path.current')->getPath();
$url_string .= "?returnTo=" .$current_path;
if(!in_array($current_path,$allowed_paths) && $current_user->isAnonymous() ) {
$url_string .= "?returnTo=" . $current_path;

if (!in_array($current_path, $allowed_paths) && $current_user->isAnonymous()) {
$response = new RedirectResponse($url_string);
\Drupal::service('kernel')->rebuildContainer();
$response->send();
Expand Down
21 changes: 16 additions & 5 deletions src/Form/CWDSamlMappingConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#default_value' => $config->get('403_custom_text'),
'#size' => 200,
'#maxlength' => 2000,
'#required' => false,
'#required' => FALSE,
];
$form['customize_403']['403_custom_logged_in_text'] = [
'#type' => 'textarea',
Expand All @@ -105,7 +105,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#default_value' => $config->get('403_custom_logged_in_text'),
'#size' => 200,
'#maxlength' => 2000,
'#required' => false,
'#required' => FALSE,
];
$form['customize_403']['local_login_text'] = [
'#type' => 'textfield',
Expand Down Expand Up @@ -137,6 +137,17 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#default_value' => $config->get('restrict_pages_url') ?? "none",
];

$form['role_management_settings'] = [
'#type' => 'details',
'#title' => $this->t('Role Management Settings'),
'#open' => TRUE,
];
$form['role_management_settings']['remove_roles'] = [
'#type' => 'checkbox',
'#title' => $this->t('The user's roles are assigned by mapping through SSO. By checking this box any manually added role is deleted upon user's log in, unless the user is present in that role’s uid list.'),
'#default_value' => $config->get('remove_roles') ?? TRUE,
];

return parent::buildForm($form, $form_state);
}

Expand All @@ -154,9 +165,9 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
$ignore = ["submit", "form_build_id", "form_token", "form_id", "op"];
$config = $this->config('cwd_saml_mapping.config_form');
foreach($form_state->getValues() as $key => $value) {
if(!in_array($key,$ignore)) {
$config->set($key,$value);
foreach ($form_state->getValues() as $key => $value) {
if (!in_array($key, $ignore)) {
$config->set($key, $value);
}
}
$config->save();
Expand Down