Skip to content
Snippets Groups Projects
Commit 386c5736 authored by Olav Morken's avatar Olav Morken
Browse files

IdP discovery: Add support for saving the users choice of IdP.

A config option is added which enables this: 'idpdisco.enableremember'
A checkbox allowing the user to save his choice of IdP appears on the IdP
selection page if this option is enabled.

This patch breaks backwards-compatibility for the selectidp-links page. Also,
the selectidp-dropdown page must be modified to show the checkboxk.

An additional page (https://.../simplesaml/cleardiscochoices.php) has been
added to make it possible to delete the current IdP choices.

There are also some dictionary updates which are not part of this patch:
frontpage.php:
+	'link_cleardiscochoices' => array (
+		'en' => 'Delete my choices of IdP in the IdP discovery services',
+		'no' => 'Slett mitt valg av IdP i IdP discovery tjenestene',
+	),
disco.php:
+	'remember' => array (
+		'en' => 'Remember my choice',
+		'no' => 'Husk mitt valg',
+	),


git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@652 44740490-163a-0410-bde0-09ae8108e29a
parent 9f1afdbf
No related branches found
No related tags found
No related merge requests found
......@@ -183,6 +183,11 @@ $config = array (
'idpdisco.url.shib13' => NULL,
'idpdisco.url.saml20' => NULL,
/*
* Whether the discovery service should allow the user to save his choice of IdP.
*/
'idpdisco.enableremember' => TRUE,
/*
* IdP Discovery service look configuration.
* Wether to display a list of idp or to display a dropdown box. For many IdP' a dropdown box
......
......@@ -5,7 +5,7 @@ if(!array_key_exists('header', $this->data)) {
}
$this->data['header'] = $this->t($this->data['header']);
$this->data['autofocus'] = 'selectbutton';
$this->data['autofocus'] = 'dropdownlist';
$this->includeAtTemplateBase('includes/header.php');
......@@ -28,7 +28,7 @@ foreach ($this->data['idplist'] AS $idpentry) {
<input type="hidden" name="entityID" value="<?php echo htmlspecialchars($this->data['entityID']); ?>" />
<input type="hidden" name="return" value="<?php echo htmlspecialchars($this->data['return']); ?>" />
<input type="hidden" name="returnIDParam" value="<?php echo htmlspecialchars($this->data['returnIDParam']); ?>" />
<select name="idpentityid">
<select id="dropdownlist" name="idpentityid">
<?php
foreach ($this->data['idplist'] AS $idpentry) {
......@@ -43,7 +43,12 @@ foreach ($this->data['idplist'] AS $idpentry) {
}
?>
</select>
<input id="selectbutton" type="submit" value="<?php echo $this->t('select'); ?>"/>
<input type="submit" value="<?php echo $this->t('select'); ?>"/>
<?php
if($this->data['rememberenabled']) {
echo('<br/><input type="checkbox" name="remember" value="1" />' . $this->t('remember'));
}
?>
</form>
......
......@@ -22,8 +22,17 @@ foreach ($this->data['idplist'] AS $idpentry) {
<h2><?php echo $this->data['header']; ?></h2>
<p><?php echo $this->t('selectidp_full'); ?></p>
<form method="get" action="<?php echo $this->data['urlpattern']; ?>">
<input type="hidden" name="entityID" value="<?php echo htmlspecialchars($this->data['entityID']); ?>" />
<input type="hidden" name="return" value="<?php echo htmlspecialchars($this->data['return']); ?>" />
<input type="hidden" name="returnIDParam" value="<?php echo htmlspecialchars($this->data['returnIDParam']); ?>" />
<p><?php
echo $this->t('selectidp_full');
if($this->data['rememberenabled']) {
echo('<br /><input type="checkbox" name="remember" value="1" />' . $this->t('remember'));
}
?></p>
<?php
......@@ -41,7 +50,9 @@ foreach ($this->data['idplist'] AS $idpentry) {
echo htmlspecialchars($this->t('idpname_' . $idpentry['entityid'])) . '</h3>';
echo ' <p>' . htmlspecialchars($this->t('idpdesc_' . $idpentry['entityid'])) . '<br />';
echo ' [ <a id="preferredidp" href="' . $this->data['urlpattern'] . htmlspecialchars($idpentry['entityid']) . '">Select this IdP</a>]</p>';
echo('<input id="preferredidp" type="submit" name="idp_' .
htmlspecialchars($idpentry['entityid']) . '" value="' .
$this->t('select') . '" /></p>');
echo '</div>';
}
......@@ -56,11 +67,13 @@ foreach ($this->data['idplist'] AS $idpentry) {
echo htmlspecialchars($this->t('idpname_' . $idpentry['entityid'])) . '</h3>';
echo ' <p>' . htmlspecialchars($this->t('idpdesc_' . $idpentry['entityid'])) . '<br />';
echo '[ <a href="' . $this->data['urlpattern'] . htmlspecialchars($idpentry['entityid']) . '">Select this IdP</a>]</p>';
echo('<input id="preferredidp" type="submit" name="idp_' .
htmlspecialchars($idpentry['entityid']) . '" value="' .
$this->t('select') . '" /></p>');
}
}
?>
</form>
<?php $this->includeAtTemplateBase('includes/footer.php'); ?>
<?php
require_once('_include.php');
/**
* This page clears the user's IdP discovery choices.
*/
/* The base path for cookies. This should be the installation directory for simpleSAMLphp. */
$config = SimpleSAML_Configuration::getInstance();
$cookiePath = '/' . $config->getBaseUrl();
/* List over the cookies we should delete. */
$deleteCookies = array(
'idpdisco_saml20_rememberchoice',
'idpdisco_shib13_rememberchoice',
);
error_log(var_export($_COOKIE, TRUE));
/* Delete the cookies. */
foreach($deleteCookies as $cookieName) {
if(!array_key_exists($cookieName, $_COOKIE)) {
/* Cookie doesn't exist. */
continue;
}
error_log('Deleting: ' . $cookieName);
/* Delete the cookie. We delete it once without the secure flag and once with the secure flag. This
* ensures that the cookie will be deleted in any case.
*/
setcookie($cookieName, '', time() - 24*60*60, $cookiePath);
}
/* Find where we should go now. */
if(array_key_exists('ReturnTo', $_REQUEST)) {
$returnTo = $_REQUEST['ReturnTo'];
} else {
/* Return to the front page if no other destination is given. This is the same as the base cookie path. */
$returnTo = $cookiePath;
}
/* Redirect to destination. */
SimpleSAML_Utilities::redirect($returnTo);
?>
\ No newline at end of file
......@@ -53,6 +53,12 @@ $links[] = array(
'text' => 'link_configcheck',
);
if($config->getBoolean('idpdisco.enableremember', FALSE)) {
$links[] = array(
'href' => 'cleardiscochoices.php',
'text' => 'link_cleardiscochoices',
);
}
$linksmeta = array();
......
......@@ -4,15 +4,22 @@ require_once('../../_include.php');
$config = SimpleSAML_Configuration::getInstance();
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
$session = SimpleSAML_Session::getInstance();
SimpleSAML_Logger::info('SAML2.0 - SP.idpDisco: Accessing SAML 2.0 discovery service');
if (!$config->getValue('enable.saml20-sp', false))
if (!$config->getValue('enable.saml20-sp', false)) {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS');
}
/* The base path for cookies. This should be the installation directory for simpleSAMLphp. */
$cookiePath = '/' . $config->getBaseUrl();
/* Has the admin enabled the remember choice option in the config? */
$rememberEnabled = $config->getBoolean('idpdisco.enableremember', FALSE);
/* Check script parameters. */
try {
if (!isset($_GET['entityID'])) throw new Exception('Missing parameter: entityID');
......@@ -28,55 +35,124 @@ try {
}
if (isset($_GET['idpentityid'])) {
$selectedIdP = NULL;
$userSelectedIdP = FALSE;
/* Check for dropdown-style of IdP selection. */
if(array_key_exists('idpentityid', $_GET)) {
$selectedIdP = $_GET['idpentityid'];
$userSelectedIdP = TRUE;
}
if($selectedIdP === NULL) {
/* Search for the IdP selection from the form used by the links view.
* This form uses a name which equals idp_<entityid>, so we search for that.
*
* Unfortunately, php replaces periods in the name with underscores, and there
* is no reliable way to get them back. Therefore we do some quick and dirty
* parsing of the query string.
*/
$qstr = $_SERVER['QUERY_STRING'];
$matches = array();
if(preg_match('/(?:^|&)idp_([^=]+)=/', $qstr, $matches)) {
$selectedIdP = urldecode($matches[1]);
$userSelectedIdP = TRUE;
}
}
SimpleSAML_Logger::info('SAML2.0 - SP.idpDisco: Choice made [ ' . $_GET['idpentityid'] . '] Setting preferedidp cookie.');
$idpentityid = $_GET['idpentityid'];
setcookie('preferedidp',$idpentityid,time()+60*60*24*90); // set cookie valid 90 days
if($selectedIdP === NULL && $rememberEnabled) {
/* No choice made by the user. Check if there is a remembered IdP for the user. */
$returnurl = SimpleSAML_Utilities::addURLparameter($return, $returnidparam . '=' . $idpentityid);
SimpleSAML_Utilities::redirect($returnurl);
if(array_key_exists('idpdisco_saml20_rememberchoice', $_COOKIE) &&
array_key_exists('idpdisco_saml20_lastidp', $_COOKIE)) {
$selectedIdP = $_COOKIE['idpdisco_saml20_lastidp'];
$userSelectedIdP = FALSE;
}
}
/* Check that the selected IdP is a valid IdP. */
if($selectedIdP !== NULL) {
try {
$idpMetadata = $metadata->getMetaData($selectedIdP, 'saml20-idp-remote');
} catch(Exception $e) {
/* The entity id wasn't valid. */
$selectedIdP = NULL;
$userSelectedIdP = FALSE;
}
}
if($selectedIdP !== NULL) {
/* We have an IdP selection. */
if($userSelectedIdP) {
/* We save the users choice for 90 days. */
$saveUntil = time() + 60*60*24*90;
SimpleSAML_Logger::info('SAML2.0 - SP.idpDisco: Choice made [ ' . $selectedIdP . ']' .
' Setting idpdisco_saml20_lastidp cookie.');
setcookie('idpdisco_saml20_lastidp', $selectedIdP, $saveUntil, $cookiePath);
if($rememberEnabled) {
if(array_key_exists('remember', $_GET)) {
/* The remember choice option is enabled, and the user has selected
* "remember choice" in the IdP list. Save this choice.
*/
setcookie('idpdisco_saml20_rememberchoice', 1, $saveUntil, $cookiePath);
}
}
}
SimpleSAML_Utilities::redirect($return, array($returnidparam => $selectedIdP));
}
/* Load list of entities. */
try {
$idplist = $metadata->getList('saml20-idp-remote');
$preferredidp = $metadata->getPreferredEntityIdFromCIDRhint('saml20-idp-remote', $_SERVER['REMOTE_ADDR']);
if (!empty($preferredidp))
if (!empty($preferredidp)) {
SimpleSAML_Logger::info('SAML2.0 - SP.idpDisco: Preferred IdP from CIDR hint [ ' . $preferredidp . '].');
}
} catch(Exception $exception) {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
}
if (!empty($_COOKIE['preferedidp'])) {
$preferredidp = $_COOKIE['preferedidp'];
if(array_key_exists('idpdisco_saml20_lastidp', $_COOKIE)) {
$preferredidp = $_COOKIE['idpdisco_saml20_lastidp'];
SimpleSAML_Logger::info('SAML2.0 - SP.idpDisco: Preferred IdP overridden from cookie [ ' . $preferredidp . '].');
}
/**
/*
* Make use of an XHTML template to present the select IdP choice to the user.
* Currently the supported options is either a drop down menu or a list view.
*/
$templatefile = ($config->getValue('idpdisco.layout') == 'dropdown' ? 'selectidp-dropdown.php' : 'selectidp-links.php');
switch($config->getString('idpdisco.layout', 'links')) {
case 'dropdown':
$templatefile = 'selectidp-dropdown.php';
break;
case 'links':
$templatefile = 'selectidp-links.php';
break;
default:
throw new Exception('Invalid value for the \'idpdisco.layout\' option.');
}
$t = new SimpleSAML_XHTML_Template($config, $templatefile, 'disco.php');
$t->data['idplist'] = $idplist;
$t->data['preferredidp'] = $preferredidp;
if ($config->getValue('idpdisco.layout') == 'dropdown') {
$t->data['return']= $return;
$t->data['returnIDParam'] = $returnidparam;
$t->data['entityID'] = $spentityid;
$t->data['urlpattern'] = htmlspecialchars(SimpleSAML_Utilities::selfURLNoQuery());
$t->show();
} else {
$t->data['urlpattern'] = htmlspecialchars(SimpleSAML_Utilities::selfURL() . '&idpentityid=');
$t->show();
}
$t->data['rememberenabled'] = $rememberEnabled;
$t->show();
?>
\ No newline at end of file
......@@ -4,16 +4,22 @@ require_once('../../_include.php');
$config = SimpleSAML_Configuration::getInstance();
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
$session = SimpleSAML_Session::getInstance();
SimpleSAML_Logger::info('Shib1.3 - SP.idpDisco: Accessing Shib 1.3 discovery service');
if (!$config->getValue('enable.shib13-sp', false))
if (!$config->getValue('enable.shib13-sp', false)) {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'NOACCESS');
}
/* The base path for cookies. This should be the installation directory for simpleSAMLphp. */
$cookiePath = '/' . $config->getBaseUrl();
/* Has the admin enabled the remember choice option in the config? */
$rememberEnabled = $config->getBoolean('idpdisco.enableremember', FALSE);
/* Check script parameters. */
try {
if (!isset($_GET['entityID'])) throw new Exception('Missing parameter: entityID');
......@@ -29,41 +35,124 @@ try {
}
if (isset($_GET['idpentityid'])) {
$selectedIdP = NULL;
$userSelectedIdP = FALSE;
/* Check for dropdown-style of IdP selection. */
if(array_key_exists('idpentityid', $_GET)) {
$selectedIdP = $_GET['idpentityid'];
$userSelectedIdP = TRUE;
}
if($selectedIdP === NULL) {
/* Search for the IdP selection from the form used by the links view.
* This form uses a name which equals idp_<entityid>, so we search for that.
*
* Unfortunately, php replaces periods in the name with underscores, and there
* is no reliable way to get them back. Therefore we do some quick and dirty
* parsing of the query string.
*/
$qstr = $_SERVER['QUERY_STRING'];
$matches = array();
if(preg_match('/(?:^|&)idp_([^=]+)=/', $qstr, $matches)) {
$selectedIdP = urldecode($matches[1]);
$userSelectedIdP = TRUE;
}
}
SimpleSAML_Logger::info('Shib1.3 - SP.idpDisco : Choice made [ ' . $_GET['idpentityid'] . '] Setting preferedidp cookie.');
$idpentityid = $_GET['idpentityid'];
setcookie('preferedidp',$idpentityid,time()+60*60*24*90); // set cookie valid 90 days
if($selectedIdP === NULL && $rememberEnabled) {
/* No choice made by the user. Check if there is a remembered IdP for the user. */
$returnurl = SimpleSAML_Utilities::addURLparameter($return, $returnidparam . '=' . $idpentityid);
SimpleSAML_Utilities::redirect($returnurl);
if(array_key_exists('idpdisco_shib13_rememberchoice', $_COOKIE) &&
array_key_exists('idpdisco_shib13_lastidp', $_COOKIE)) {
$selectedIdP = $_COOKIE['idpdisco_shib13_lastidp'];
$userSelectedIdP = FALSE;
}
}
/* Check that the selected IdP is a valid IdP. */
if($selectedIdP !== NULL) {
try {
$idpMetadata = $metadata->getMetaData($selectedIdP, 'shib13-idp-remote');
} catch(Exception $e) {
/* The entity id wasn't valid. */
$selectedIdP = NULL;
$userSelectedIdP = FALSE;
}
}
if($selectedIdP !== NULL) {
/* We have an IdP selection. */
if($userSelectedIdP) {
/* We save the users choice for 90 days. */
$saveUntil = time() + 60*60*24*90;
SimpleSAML_Logger::info('Shib1.3 - SP.idpDisco: Choice made [ ' . $selectedIdP . ']' .
' Setting idpdisco_shib13_lastidp cookie.');
setcookie('idpdisco_shib13_lastidp', $selectedIdP, $saveUntil, $cookiePath);
if($rememberEnabled) {
if(array_key_exists('remember', $_GET)) {
/* The remember choice option is enabled, and the user has selected
* "remember choice" in the IdP list. Save this choice.
*/
setcookie('idpdisco_shib13_rememberchoice', 1, $saveUntil, $cookiePath);
}
}
}
SimpleSAML_Utilities::redirect($return, array($returnidparam => $selectedIdP));
}
/* Load list of entities. */
try {
$idplist = $metadata->getList('shib13-idp-remote');
$preferredidp = $metadata->getPreferredEntityIdFromCIDRhint('shib13-idp-remote', $_SERVER['REMOTE_ADDR']);
if (!empty($preferredidp)) {
SimpleSAML_Logger::info('Shib1.3 - SP.idpDisco: Preferred IdP from CIDR hint [ ' . $preferredidp . '].');
}
} catch(Exception $exception) {
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
}
if ($config->getValue('idpdisco.layout') == 'dropdown') {
$t = new SimpleSAML_XHTML_Template($config, 'selectidp-dropdown.php', 'disco.php');
if(array_key_exists('idpdisco_shib13_lastidp', $_COOKIE)) {
$preferredidp = $_COOKIE['idpdisco_shib13_lastidp'];
SimpleSAML_Logger::info('Shib1.3 - SP.idpDisco: Preferred IdP overridden from cookie [ ' . $preferredidp . '].');
}
/*
* Make use of an XHTML template to present the select IdP choice to the user.
* Currently the supported options is either a drop down menu or a list view.
*/
switch($config->getString('idpdisco.layout', 'links')) {
case 'dropdown':
$templatefile = 'selectidp-dropdown.php';
break;
case 'links':
$templatefile = 'selectidp-links.php';
break;
default:
throw new Exception('Invalid value for the \'idpdisco.layout\' option.');
}
$t = new SimpleSAML_XHTML_Template($config, $templatefile, 'disco.php');
$t->data['idplist'] = $idplist;
$t->data['preferredidp'] = $preferredidp;
$t->data['return']= $return;
$t->data['returnIDParam'] = $returnidparam;
$t->data['entityID'] = $spentityid;
$t->data['preferedidp'] = (!empty($_COOKIE['preferedidp'])) ? $_COOKIE['preferedidp'] : null;
$t->data['urlpattern'] = htmlspecialchars(SimpleSAML_Utilities::selfURLNoQuery());
$t->show();
}
else
{
$t = new SimpleSAML_XHTML_Template($config, 'selectidp-links.php', 'disco.php');
$t->data['idplist'] = $idplist;
$t->data['urlpattern'] = htmlspecialchars(SimpleSAML_Utilities::selfURL() . '&idpentityid=');
$t->show();
}
$t->data['rememberenabled'] = $rememberEnabled;
$t->show();
?>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment