Skip to content
Snippets Groups Projects
Commit 82164e5c authored by Martin van Es's avatar Martin van Es
Browse files

Add customauth module and idp-hosted changes

parent 06e3ff28
No related branches found
No related tags found
No related merge requests found
Showing
with 1568 additions and 10 deletions
# Test_IdP # Test_IdP
metadata/saml20-idp-hosted.php
```
$metadata['__DYNAMIC:1__'] = [
+ 'auth' => 'custom-userpass',
```
config/authsources.php
```
+ 'custom-userpass' => [
+ 'customauth:External',
+ ],
```
...@@ -63,28 +63,46 @@ $metadata['__DYNAMIC:1__'] = [ ...@@ -63,28 +63,46 @@ $metadata['__DYNAMIC:1__'] = [
], ],
// X.509 key and certificate. Relative to the cert directory. // X.509 key and certificate. Relative to the cert directory.
'privatekey' => 'server.pem', 'privatekey' => 'server.key',
'certificate' => 'server.crt', 'certificate' => 'server.crt',
/* /*
* Authentication source to use. Must be one that is configured in * Authentication source to use. Must be one that is configured in
* 'config/authsources.php'. * 'config/authsources.php'.
*/ */
'auth' => 'example-userpass', 'auth' => 'custom-userpass',
//'auth' => 'example-userpass',
/* Uncomment the following to use the uri NameFormat on attributes. */ /* Uncomment the following to use the uri NameFormat on attributes. */
/* //'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
'authproc' => [ 'authproc' => [
// Convert LDAP names to oids. 5 => [
100 => ['class' => 'core:AttributeMap', 'name2oid'], 'class' => 'core:TargetedID',
'identifyingAttribute' => 'eduPersonTargetedId',
'nameId' => TRUE,
],
8 => [
'class' => 'core:PHP',
'code' => '
unset($attributes["eduPersonTargetedId"]);
',
],
// Convert LDAP names to urn.
10 => [
'class' => 'core:AttributeMap',
'name2oid'
],
], ],
*/ 'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
'attributeencodings' => array(
'urn:oid:1.3.6.1.4.1.5923.1.1.1.10' => 'raw', /* eduPersonTargetedID with oid NameFormat. */
),
]; ];
$query = "select o.name, o.type, c.value from idps i $query = "select o.name, o.type, c.value from idps i
left join config c on c.idp_id = i.idp_id right join config c on c.idp_id = i.idp_id
left join options o on c.option_id = o.option_id right join options o on c.option_id = o.option_id
where i.host = :host"; where i.host = :host";
...@@ -97,7 +115,7 @@ foreach ($result as $row) { ...@@ -97,7 +115,7 @@ foreach ($result as $row) {
$name = explode(':', $row['name']); $name = explode(':', $row['name']);
$value = $row['value']; $value = $row['value'];
$config = array_merge_recursive($config, nest($name, $value)); $config = array_merge_recursive($config, nest($name, $value));
} }
$metadata['__DYNAMIC:1__'] = array_replace_recursive($metadata['__DYNAMIC:1__'], $config); $metadata['__DYNAMIC:1__'] = array_replace_recursive($metadata['__DYNAMIC:1__'], $config);
enable
# simplesamlphp-module-customauth
CustomAuth simpleSAML php auth source
This file indicates that the default state of this module
is disabled. To enable, create a file named enable in the
same directory as this file.
<?php
declare(strict_types=1);
namespace SimpleSAML\Module\customauth\Auth\Process;
use SimpleSAML\Auth;
use SimpleSAML\Module;
use SimpleSAML\Utils;
/**
* A simple processing filter for testing that redirection works as it should.
*
*/
class RedirectTest extends \SimpleSAML\Auth\ProcessingFilter
{
/**
* Initialize processing of the redirect test.
*
* @param array &$state The state we should update.
* @return void
*/
public function process(&$state)
{
assert(is_array($state));
assert(array_key_exists('Attributes', $state));
// To check whether the state is saved correctly
$state['Attributes']['RedirectTest1'] = ['OK'];
// Save state and redirect
$id = Auth\State::saveState($state, 'customauth:redirectfilter-test');
$url = Module::getModuleURL('customauth/redirecttest.php');
Utils\HTTP::redirectTrustedURL($url, ['StateId' => $id]);
}
}
<?php
declare(strict_types=1);
namespace SimpleSAML\Module\customauth\Auth\Source;
use SimpleSAML\Auth;
use SimpleSAML\Error;
use SimpleSAML\Module;
use SimpleSAML\Utils;
/**
* Example external authentication source.
*
* This class is an custom authentication source which is designed to
* hook into an external authentication system.
*
* To adapt this to your own web site, you should:
* 1. Create your own module directory.
* 2. Add a file "default-enable" to that directory.
* 3. Copy this file and modules/customauth/www/resume.php to their corresponding
* location in the new module.
* 4. Replace all occurrences of "customauth" in this file and in resume.php with the name of your module.
* 5. Adapt the getUser()-function, the authenticate()-function and the logout()-function to your site.
* 6. Add an entry in config/authsources.php referencing your module. E.g.:
* 'myauth' => array(
* '<mymodule>:External',
* ),
*
* @package SimpleSAMLphp
*/
class External extends \SimpleSAML\Auth\Source
{
/**
* The key of the AuthId field in the state.
*/
public const AUTHID = 'SimpleSAML\Module\customauth\Auth\Source\External.AuthId';
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public function __construct($info, $config)
{
assert(is_array($info));
assert(is_array($config));
// Call the parent constructor first, as required by the interface
parent::__construct($info, $config);
// Do any other configuration we need here
}
/**
* Retrieve attributes for the user.
*
* @return array|null The user's attributes, or NULL if the user isn't authenticated.
*/
private function getUser(): ?array
{
/*
* In this example we assume that the attributes are
* stored in the users PHP session, but this could be replaced
* with anything.
*/
if (!session_id()) {
// session_start not called before. Do it here
session_start();
}
/*
* Find the attributes for the user.
* Note that all attributes in SimpleSAMLphp are multivalued, so we need
* to store them as arrays.
*/
$attributes = null;
if (isset($_SESSION['attributes'])) foreach($_SESSION['attributes'] as $key => $value) {
#$attributes[$key] = array_filter(array_map('trim', explode(',', $value)));
$attributes[$key] = is_array($value)?$value:[$value];
}
return $attributes;
}
/**
* Log in using an external authentication helper.
*
* @param array &$state Information about the current authentication.
* @return void
*/
public function authenticate(&$state)
{
assert(is_array($state));
$attributes = $this->getUser();
if ($attributes !== null) {
/*
* The user is already authenticated.
*
* Add the users attributes to the $state-array, and return control
* to the authentication process.
*/
$state['Attributes'] = $attributes;
return;
}
/*
* The user isn't authenticated. We therefore need to
* send the user to the login page.
*/
/*
* First we add the identifier of this authentication source
* to the state array, so that we know where to resume.
*/
$state['customauth:AuthID'] = $this->authId;
/*
* We need to save the $state-array, so that we can resume the
* login process after authentication.
*
* Note the second parameter to the saveState-function. This is a
* unique identifier for where the state was saved, and must be used
* again when we retrieve the state.
*
* The reason for it is to prevent
* attacks where the user takes a $state-array saved in one location
* and restores it in another location, and thus bypasses steps in
* the authentication process.
*/
$stateId = Auth\State::saveState($state, 'customauth:External');
/*
* Now we generate a URL the user should return to after authentication.
* We assume that whatever authentication page we send the user to has an
* option to return the user to a specific page afterwards.
*/
$returnTo = Module::getModuleURL('customauth/resume.php', [
'State' => $stateId,
]);
/*
* Get the URL of the authentication page.
*
* Here we use the getModuleURL function again, since the authentication page
* is also part of this module, but in a real example, this would likely be
* the absolute URL of the login page for the site.
*/
$authPage = Module::getModuleURL('customauth/authpage.php');
/*
* The redirect to the authentication page.
*
* Note the 'ReturnTo' parameter. This must most likely be replaced with
* the real name of the parameter for the login page.
*/
Utils\HTTP::redirectTrustedURL($authPage, [
'ReturnTo' => $returnTo,
]);
/*
* The redirect function never returns, so we never get this far.
*/
assert(false);
}
/**
* Resume authentication process.
*
* This function resumes the authentication process after the user has
* entered his or her credentials.
*
* @return void
* @throws \SimpleSAML\Error\BadRequest
* @throws \SimpleSAML\Error\Exception
*/
public static function resume()
{
/*
* First we need to restore the $state-array. We should have the identifier for
* it in the 'State' request parameter.
*/
if (!isset($_REQUEST['State'])) {
throw new Error\BadRequest('Missing "State" parameter.');
}
/*
* Once again, note the second parameter to the loadState function. This must
* match the string we used in the saveState-call above.
*/
/** @var array $state */
$state = Auth\State::loadState($_REQUEST['State'], 'customauth:External');
/*
* Raise SAML Error Response when the 'Create SAML Error Response'
* checkbox was checked
*/
if (isset($_SESSION['ErrorResponse'])) {
unset($_SESSION['ErrorResponse']);
Auth\State::throwException($state,
new \SimpleSAML\Module\saml\Error(
\SAML2\Constants::STATUS_RESPONDER,
\SAML2\Constants::STATUS_AUTHN_FAILED,
'Authentication failed'
)
);
}
/*
* Now we have the $state-array, and can use it to locate the authentication
* source.
*/
$source = Auth\Source::getById($state['customauth:AuthID']);
if ($source === null) {
/*
* The only way this should fail is if we remove or rename the authentication source
* while the user is at the login page.
*/
throw new Error\Exception('Could not find authentication source with id ' . $state[self::AUTHID]);
}
/*
* Make sure that we haven't switched the source type while the
* user was at the authentication page. This can only happen if we
* change config/authsources.php while an user is logging in.
*/
if (!($source instanceof self)) {
throw new Error\Exception('Authentication source type changed.');
}
/*
* OK, now we know that our current state is sane. Time to actually log the user in.
*
* First we check that the user is acutally logged in, and didn't simply skip the login page.
*/
$attributes = $source->getUser();
if ($attributes === null) {
/*
* The user isn't authenticated.
*
* Here we simply throw an exception, but we could also redirect the user back to the
* login page.
*/
throw new Error\Exception('User not authenticated after login page.');
}
/*
* So, we have a valid user. Time to resume the authentication process where we
* paused it in the authenticate()-function above.
*/
$state['Attributes'] = $attributes;
Auth\Source::completeAuth($state);
/*
* The completeAuth-function never returns, so we never get this far.
*/
assert(false);
}
/**
* This function is called when the user start a logout operation, for example
* by logging out of a SP that supports single logout.
*
* @param array &$state The logout state array.
* @return void
*/
public function logout(&$state)
{
assert(is_array($state));
if (!session_id()) {
// session_start not called before. Do it here
session_start();
}
/*
* In this example we simply remove the 'uid' from the session.
*/
unset($_SESSION['attributes']);
/*
* If we need to do a redirect to a different page, we could do this
* here, but in this example we don't need to do this.
*/
}
}
<?php
declare(strict_types=1);
namespace SimpleSAML\Module\customauth\Auth\Source;
use SimpleSAML\Utils;
/**
* Example authentication source.
*
* This class is an example authentication source which will always return a user with
* a static set of attributes.
*
* @author Olav Morken, UNINETT AS.
* @package SimpleSAMLphp
*/
class StaticSource extends \SimpleSAML\Auth\Source
{
/**
* The attributes we return.
* @var array
*/
private $attributes;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public function __construct($info, $config)
{
assert(is_array($info));
assert(is_array($config));
// Call the parent constructor first, as required by the interface
parent::__construct($info, $config);
// Parse attributes
try {
$this->attributes = Utils\Attributes::normalizeAttributesArray($config);
} catch (\Exception $e) {
throw new \Exception('Invalid attributes for authentication source ' .
$this->authId . ': ' . $e->getMessage());
}
}
/**
* Log in using static attributes.
*
* @param array &$state Information about the current authentication.
* @return void
*/
public function authenticate(&$state)
{
assert(is_array($state));
$state['Attributes'] = $this->attributes;
}
}
<?php
declare(strict_types=1);
namespace SimpleSAML\Module\customauth\Auth\Source;
use SimpleSAML\Error;
use SimpleSAML\Utils;
/**
* Example authentication source - username & password.
*
* This class is an example authentication source which stores all username/passwords in an array,
* and authenticates users against this array.
*
* @author Olav Morken, UNINETT AS.
* @package SimpleSAMLphp
*/
class UserPass extends \SimpleSAML\Module\core\Auth\UserPassBase
{
/**
* Our users, stored in an associative array. The key of the array is "<username>:<password>",
* while the value of each element is a new array with the attributes for each user.
*
* @var array
*/
private $users;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public function __construct($info, $config)
{
assert(is_array($info));
assert(is_array($config));
// Call the parent constructor first, as required by the interface
parent::__construct($info, $config);
$this->users = [];
// Validate and parse our configuration
foreach ($config as $userpass => $attributes) {
if (!is_string($userpass)) {
throw new \Exception(
'Invalid <username>:<password> for authentication source ' . $this->authId . ': ' . $userpass
);
}
$userpass = explode(':', $userpass, 2);
if (count($userpass) !== 2) {
throw new \Exception(
'Invalid <username>:<password> for authentication source ' . $this->authId . ': ' . $userpass[0]
);
}
$username = $userpass[0];
$password = $userpass[1];
try {
$attributes = Utils\Attributes::normalizeAttributesArray($attributes);
} catch (\Exception $e) {
throw new \Exception('Invalid attributes for user ' . $username .
' in authentication source ' . $this->authId . ': ' . $e->getMessage());
}
$this->users[$username . ':' . $password] = $attributes;
}
}
/**
* Attempt to log in using the given username and password.
*
* On a successful login, this function should return the users attributes. On failure,
* it should throw an exception. If the error was caused by the user entering the wrong
* username or password, a \SimpleSAML\Error\Error('WRONGUSERPASS') should be thrown.
*
* Note that both the username and the password are UTF-8 encoded.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
* @return array Associative array with the users attributes.
*/
protected function login($username, $password)
{
assert(is_string($username));
assert(is_string($password));
$userpass = $username . ':' . $password;
if (!array_key_exists($userpass, $this->users)) {
throw new Error\Error('WRONGUSERPASS');
}
return $this->users[$userpass];
}
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<title>customauth login page</title>
</head>
<body>
<h1>CustomAuth login page</h1>
<form method="post" action="?">
<p><b>Choose User profile</b><p>
<?php
foreach ($this->data['users'] as $user => $values) {
echo "<input type=radio name=username value='$user'> " . $values['displayName'] . "<br>\n";
}
?>
<p><b>Choose attributes</b></p>
<div style="float: left" id="attributes"></div>
<div id="explanation"></div><br style="clear: both" />
<p><b>Released attributes</b></p>
<div id="output"></div>
<input type="hidden" name="ReturnTo" value="<?= htmlspecialchars($this->data['returnTo']) ?>">
<p><input type="submit" value="Log in"></p>
</form>
</body>
<script>
var users = [];
var keys = [];
var user = '';
<?php
foreach ($this->data['users'] as $user => $values) {
echo "users['$user'] = [];\n";
foreach ($values as $key => $value) {
echo "users['$user']['$key'] = '$value';\n";
echo "keys['$key'] = true;";
}
}
?>
function update() {
var html = "";
for (let key in users[user]) {
if (keys[key]) {
html += key + ": " + users[user][key] + "<br />\n";
}
}
$('#output').html(html);
};
$('input[type=radio][name=username]').change(function() {
var attributes = "";
user = this.value;
for (let key in users[user]) {
attribute = users[user][key];
attributes += "<input id=chkbx_" + key + " type=checkbox name=keys[" + key + "] " + (keys[key]?'checked':'') + ">" + key + "<br>\n";
};
$('#attributes').html(attributes);
$('#explanation').html('');
$('input[id^=chkbx_]').change(function() {
var key = this.name.slice(5,-1);
keys[key] = this.checked;
if (this.checked) $('#explanation').html('Ah! You enabled ' + key + '!<br />\nIt\'s allways good to enable ' + key + ', because it\'s good you know!');
else $('#explanation').html('Never disable ' + key + '! You should leave it there.<br />No good will come from disabling ' + key + '!');
});
update();
});
//$('#attributes').change(update);
$('#attributes').change(function() {
update();
});
</script>
</html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="initial-scale=1.0"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript" src="<?=SimpleSAML\Module::getModuleURL("customauth/assets/script.js")?>"></script>
<title>Please select a profile to release attributes</title>
<link rel="stylesheet" type="text/css" href="<?=SimpleSAML\Module::getModuleURL("customauth/assets/css/default.css")?>"/>
<link rel="icon" type="image/icon" href="<?=SimpleSAML\Module::getModuleURL("customauth/assets/favicon.ico")?>"/>
<meta name="robots" content="noindex, nofollow"/>
</head>
<body onload="SimpleSAML_focus('password');">
<div id="wrap">
<div id="header">
<br>
<img src="https://idp.test.inacademia.org/module.php/inacademia_theme/login_icon.svg" alt="IKONA"/>
<h1><a href="/">Enter your username and password</a></h1>
</div>
<div class="romb"></div>
<div id="content">
<p class="logintext">A service has requested you to authenticate yourself. <br>Please select a profile and optionally which attributes to release from the information below.</p>
<form method="post" action="?">
<p><hr/><b>Choose User profile</b></p>
<div style="float:left; margin-right: 10px">
<select name=username size=5>
<?php
foreach ($this->data['users'] as $user => $values) {
$uarr = explode(':', $user);
$uid = $uarr[0];
$display = $this->data['displays'][$user];
echo "<option name=\"$uid\" value=\"$uid\">$display</option>\n";
}
?>
</select>
</div>
<div id="explanation">Woohaa!</div><br style="clear: both" />
<p><hr/><b>Choose attributes</b></p>
<div style="float: left" id="attributes"></div>
<div id="about"></div><br style="clear: both" />
<p><hr/><b>Released attributes</b></p>
<div id="output"></div>
<p><hr/><b>Special</b></p>
<div><input type="checkbox" name="error" value="true"> Create SAML Error Response</div>
<input type="hidden" name="ReturnTo" value="<?= htmlspecialchars($this->data['returnTo']) ?>">
<p><input id="submit_button" class="btn" type="submit" value="Log in"></p>
</form>
</div>
</body>
<script>
var users = [];
var keys = [];
var message = [];
var explanations = [];
var user = '';
<?php
foreach ($this->data['users'] as $user => $values) {
echo "users['$user'] = [];\n";
foreach ($values as $key => $value) {
echo "users['$user']['$key'] = [\"" . (is_array($value)?implode("\",\"", $value):$value) . "\"]; ";
echo "keys['$key'] = true;\n";
}
}
foreach ($this->data['attributes'] as $attribute => $message) {
echo "message['$attribute'] = \"$message\";\n";
}
foreach ($this->data['explanations'] as $user => $explanation) {
echo "explanations['$user'] = \"$explanation\";\n";
}
?>
function update() {
var html = "";
for (let key in users[user]) {
if (keys[key]) {
html += key + ": " + users[user][key] + "<br />\n";
}
}
$('#output').html(html);
};
$('select[name=username]').change(function() {
var attributes = "";
user = this.value;
for (let key in users[user]) {
attribute = users[user][key];
attributes += "<input id=chkbx_" + key + " type=checkbox name=keys[" + key + "] " + (keys[key]?'checked':'') + ">" + key + "<br>\n";
};
$('#explanation').html(explanations[user]);
$('#attributes').html(attributes);
$('#about').html('');
$('input[id^=chkbx_]').change(function() {
var key = this.name.slice(5,-1);
keys[key] = this.checked;
if (this.checked) $('#about').html(message[key] + '<br>Enabled');
else $('#about').html(message[key] + '<br>Disabled');
});
update();
});
$('#attributes').change(function() {
update();
});
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>customauth login page</title>
</head>
<body>
<h1>customauth login page</h1>
<p>
In this example you can log in with two accounts: <code>student</code> and <code>admin</code>.
In both cases, the password is the same as the username.
</p>
<form method="post" action="?">
<p>
Username:
<input type="text" name="username">
</p>
<p>
Password:
<input type="text" name="password">
</p>
<input type="hidden" name="ReturnTo" value="{{ returnTo|escape('html') }}">
<p><input type="submit" value="Log in"></p>
</form>
{% if badUserPass == true %}
<p>!!! Bad username or password !!!</p>
{% endif %}
</body>
</html>
/* these styles are in the head of this page because this is a unique page */
/* THE BIG GUYS */
* {
margin: 0;
padding: 0;
}
body {
text-align: center;
/*padding: 10px 0;*/
background: #2a333d;
/* background-image: url(icons/ssplogo-fish.png); */
/* background-repeat: no-repeat; */
color: #333;
font: 83%/1.5 Roboto, tahoma, verdana, sans-serif;
}
.body-embed {
padding: 0;
background: #ffffff;
font: 83%/1.5 arial, tahoma, verdana, sans-serif;
}
img {
border: none;
display: block;
}
hr {
margin: 1em 0;
background: #eee;
height: 1px;
color: #eee;
border: none;
clear: both;
}
/* LINKS */
a, a:link, a:link, a:link, a:hover {
text-decoration: none;
color: #777;
border-bottom: 1px dotted #ccc;
font-weight: normal;
}
a:link, a:visited {
text-decoration: none;
color: #777;
border-bottom: 1px dotted #ccc;
font-weight: normal;
}
.ui-tabs-nav a {
border: none ! important;
text-decoration: none;
}
a:visited {
color: #999;
}
a:hover, a:active {
color: #069;
text-decoration: none;
color: #333;
border-bottom: 1px solid #333;
}
#header a {
color: #fff;
text-decoration: none;
}
/* LISTS */
ul {
margin: .3em 0 1.5em 2em;
}
ul.related {
margin-top: -1em;
}
li {
margin-left: 2em;
}
dt {
font-weight: bold;
}
#wrap {
background: #ffffff;
/*border: 1px solid #fff;*/
position: relative;
text-align: left;
/*margin: 20px 75px 2em 75px;*/
/*max-width: 950px;*/
width: 750px;
margin-left: auto;
margin-right: auto;
margin-top: 2%;
/*height: 650px;*/
/*height: auto;*/
box-shadow: 5px 5px 5px 5px #141c25;
}
#languagebar {
padding-left: 10px;
padding-right: 10px;
}
#languagebar a:link, #languagebar a:visited {
text-decoration: none;
color: #777;
border-bottom: 1px dotted #ccc;
font-weight: normal;
}
#languagebar a:hover {
text-decoration: none;
color: #333;
border-bottom: 1px solid #333;
}
#header {
background: #fe5258;
margin: 0px;
padding: 0 0 8px;
height: 140px;
}
#header h1 {
color: #fff;
font-size: 15px;
padding: 20px 20px 12px;
text-align: center;
}
h1 {
letter-spacing: 0px !important;
}
#content, #footer {
padding: 0 20px;
}
/* TYPOGRAPHY */
p, ul, ol {
margin-top: 1em;
}
h1, h2, h3, h4, h5, h6 {
letter-spacing: -1px;
font-family: arial, verdana, sans-serif;
margin: 1.2em 0 .3em;
color: #000;
border-bottom: 1px solid #eee;
padding-bottom: .1em;
}
h1 {
font-size: 196%;
margin-top: 0;
border: none;
}
h2 {
font-size: 136%;
}
h3 {
font-size: 126%;
}
h4 {
font-size: 116%;
font-weight: bold;
}
h5 {
font-size: 106%;
}
h6 {
font-size: 96%;
}
input {
border: 1px solid #bbb;
border-radius: 3px;
padding: 10px;
line-height: 1.5em;
/*width: 60%;*/
margin: 4px;
color: #9d9d9d;
/*margin-left: 18%;*/
/*margin-right: 18%;*/
}
h1 a {
text-decoration: none;
border: none ! important;
color: white;
}
h1 a:hover {
border-bottom: 1px dotted #eee;
}
#content {
margin-top: 4em;
}
.old {
text-decoration: line-through;
}
dl dt {
color: #333;
}
dl dd {
color: #666;
margin-left: 3em;
/* font-family: monospace; */
}
.efieldlist {
padding: .4em;
margin: .8em;
border-top: 1px solid #e6e6e6;
border-left: 1px solid #e6e6e6;
}
.efieldlist.warning {
background-color: #922;
border: 1px solid #333;
color: white;
}
.efieldlist.warning h5 {
color: white;
}
.efieldlist h5 {
font-weight: bold;
color: #200;
margin: .3em;
}
.trackidtext {
border: 1px dashed #aaa;
background: #eaeaea;
padding: .6em;
margin: .4em;
}
.trackidtext .trackid {
border: 1px solid #ccc;
background: #eee;
margin: .4em;
padding: .4em;
font-family: monospace;
font-size: large;
}
div.caution {
background-color: #FF9;
background-image: url('../themes/icons/experience/gtk-dialog-warning.48x48.png');
background-repeat: no-repeat;
border: thin solid #444;
padding: .2em .2em .2em 60px;
margin: 1em 0px 1em 0px;
}
th.rowtitle {
text-align: left;
}
.enablebox table {
border: 1px solid #eee;
margin-left: 1em;
}
.enablebox.mini table {
float: right;
}
.enablebox tr td {
padding: .5px 1em 1px .5em;
margin: 0px;
}
.enablebox {
font-size: 85%;
}
.enablebox tr.enabled td {
background: #eee;
}
.enablebox tr.disabled td {
background: #ccc;
}
.metadatabox {
overflow: scroll;
border: 1px solid #eee;
padding: 0.5em;
border-radius: 3px;
}
div.preferredidp {
border: 1px dashed #ccc;
background: #eee;
padding: 2px 2em 2px 2em;
}
table.modules {
border-collapse: collapse;
}
table.modules tr td {
border-bottom: 1px solid #ddd;
}
table.modules tr.even td {
background: #f0f0f0;
}
/* Attribute presentation in example page */
table.attributes {
width: 100%;
margin: 0px;
border: 1px solid #bbb;
border-collapse: collapse;
}
table.attributes td.attrname {
text-align: right;
}
table.attributes tr.even td {
background: #eee;
}
table.attributes tr td {
border-bottom: 1px solid #bbb;
border-left: 0px;
border-right: 0px;
background: #fff;
padding-top: 5px;
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
.attrvalue {
word-break: break-all;
word-wrap: break-word;
}
table#table_with_attributes tr:last-child td {
border-bottom: none;
}
fieldset.fancyfieldset {
margin: 2em 1em 1em 0px;
border: 1px solid #bbb;
}
fieldset.fancyfieldset legend {
margin-left: 2em;
padding: 3px 2em 3px 2em;
border: 1px solid #bbb;
}
div#confirmation input {
margin-top: .5em;
margin-bottom: .5em;
}
div#confirmation {
border: 1px solid #aaa;
background: #eee;
padding: .6em 1em .1em 1em;
}
caption {
display: none;
}
/* Left-to-Right CSS for RTL (Right to Left Support) */
.float-r {
float: right;
}
.float-l {
float: left;
}
#mobile_remember_username, #mobile_remember_me {
display: none;
}
@media handheld, only screen and (max-width: 480px), only screen and (max-device-width: 480px) {
/*#header, #languagebar, #footer, .erroricon, .loginicon, .logintext,*/
/*#regular_remember_username, #regular_remember_me {*/
/* display: none;*/
/*}*/
body {
font-size: 20px;
}
/*#wrap {*/
/* margin: 0;*/
/*}*/
h1, h2, h3, h4 {
font-size: 110%;
}
#content {
margin-bottom: 10px;
padding: 0;
padding-left: 5px;
}
input[type="text"], input[type="password"] {
height: 1.5em;
font-size: 1em;
}
.youareadmin {
font-size: 50%;
}
#mobilesubmit, #mobile_remember_username, #mobile_remember_me {
display: table-row;
}
}
.btn, .btnaddonright {
border: 1px solid #47494a;
border-radius: 3px;
background-color: #3d3d3d !important;
background-image: linear-gradient(#575757, #2e2e2e);
text-align: center;
padding: 15px;
cursor: hand;
margin: 10px;
color: white;
margin-left: 18%;
margin-right: 18%;
}
.btn:hover, .btnaddonright:hover {
border-color: #ccc;
background-color: #ddd;
background-image: linear-gradient(#eee, #ddd);
}
.btn img,
.btnaddonright img {
max-height: 15px;
max-width: 15px;
}
.topright {
position: absolute;
right: 2em;
}
.input-group {
display: table;
}
.input-group pre {
background: white;
position: relative;
width: 100%;
vertical-align: middle;
border: 1px solid #eee;
padding: 0.5em;
display: table-cell;
}
.input-group .btnaddonright {
position: relative;
display: inline-block;
border-bottom-left-radius: 0;
border-bottom-right-radius: 3px;
border-top-left-radius: 0;
border-top-right-radius: 3px;
border-left: none;
}
.input-group .btnaddonright:hover {
border-left: 1px solid #ccc;
}
.input-group .input-left {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 0;
border-top-left-radius: 3px;
border-top-right-radius: 0;
}
.logintext {
text-align: left;
margin-right: 18%;
margin-left: 18%;
color: #777777;
font-size: 12px;
margin-top: 15px;
}
#footer {
/*background-color: #f2f2f2;*/
text-align: center;
font-size: 10px;
padding-bottom: 10px;
position: absolute;
bottom: 0;
width: 510px;
}
#submit_button {
width: 65%;
background-color: #3d3d3d !important;
}
form {
margin-bottom: 3%;
}
table {
width: 100%;
}
.romb {
background-color: #fe5258;
width: 30px;
height: 30px;
transform: rotate(45deg);
margin-left: 47%;
margin-right: 47%;
margin-top: -15px;
position: absolute;
}
@media handheld, only screen and (max-width: 800px), only screen and (max-device-width: 800px) {
#wrap {
width: 70%;
margin-left: 15%;
/*margin-right: 5%;*/
}
#footer {
width: 92%;
}
.content {
height: 100%;
}
}
@media handheld, only screen and (max-width: 600px), only screen and (max-device-width: 600px) {
#wrap {
/*height: 800px;*/
width: 100%;
margin-left: 0;
margin-top: 10%;
}
#footer {
width: 92%;
}
}
@media handheld, only screen and(min-width: 1024px) and (max-width: 1500px), only screen and (min-device-width: 1024px)and (max-device-width: 1500px) {
#wrap {
margin-left: 30%;
}
}
@media handheld, only screen and (width: 1024px), only screen and (device-width: 1024px) {
#wrap {
margin-left: 25%;
}
}
img {
width: 50%;
height: 50%;
margin-left: 25%;
}
.searchIcon {
padding: 0.5rem;
}
@media handheld, only screen and (max-width: 480px), only screen and (max-device-width: 480px) {
#header h1 {
margin-top: -10px;
}
}
@media handheld, only screen and(min-width: 300px) and (max-width: 400px), only screen and (min-device-width: 300px)and (max-device-width: 400px) {
#footer {
width: 88%;
}
}
input {
/*text-indent: 32px;*/
}
.icon_class #input_img {
position: absolute;
/*top:275px;*/
margin-top: 20px;
left: -15px;
width: 22px;
height: 22px;
float: left;
}
.icon_class #pass_img {
position: absolute;
/*top:340px;*/
margin-top: 20px;
left: -15px;
width: 20px;
height: 20px;
float: left;
}
modules/customauth/www/assets/favicon.ico

1.12 KiB

/**
* Set focus to the element with the given id.
*
* @param id The id of the element which should receive focus.
*/
function SimpleSAML_focus(id)
{
element = document.getElementById(id);
if (element != null) {
element.focus();
}
}
/**
* Show the given DOM element.
*
* @param id The id of the element which should be shown.
*/
function SimpleSAML_show(id)
{
element = document.getElementById(id);
if (element == null) {
return;
}
element.style.display = 'block';
}
/**
* Hide the given DOM element.
*
* @param id The id of the element which should be hidden.
*/
function SimpleSAML_hide(id)
{
element = document.getElementById(id);
if (element == null) {
return;
}
element.style.display = 'none';
}
<?php
/**
* This page serves as a dummy login page.
*
* Note that we don't actually validate the user in this example. This page
* just serves to make the example work out of the box.
*
* @package SimpleSAMLphp
*/
if (!isset($_REQUEST['ReturnTo'])) {
die('Missing ReturnTo parameter.');
}
$returnTo = \SimpleSAML\Utils\HTTP::checkURLAllowed($_REQUEST['ReturnTo']);
/**
* The following piece of code would never be found in a real authentication page. Its
* purpose in this example is to make this example safer in the case where the
* administrator of the IdP leaves the exampleauth-module enabled in a production
* environment.
*
* What we do here is to extract the $state-array identifier, and check that it belongs to
* the exampleauth:External process.
*/
if (!preg_match('@State=(.*)@', $returnTo, $matches)) {
die('Invalid ReturnTo URL for this example.');
}
/**
* The loadState-function will not return if the second parameter does not
* match the parameter passed to saveState, so by now we know that we arrived here
* through the customauth:External authentication page.
*/
\SimpleSAML\Auth\State::loadState(urldecode($matches[1]), 'customauth:External');
// our list of users.
$raw_users = json_decode(file_get_contents('/opt/simplesamlphp/config/logins.json'), true);
$attributes = json_decode(file_get_contents('/opt/simplesamlphp/config/attributes.json'), true);
$users = [];
$explanations = [];
$displays = [];
foreach ($raw_users as $user => $values) {
$explanations[$user] = $values['explanation'];
$displays[$user] = $values['display'];
unset($values['explanation']);
unset($values['display']);
$users[$user] = $values;
}
// time to handle login responses; since this is a dummy example, we accept any data
$badUserPass = false;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = (string) $_REQUEST['username'];
$user_aa = $users[$username];
if (!session_id()) {
// session_start not called before. Do it here.
session_start();
}
foreach ($user_aa as $key => $value) {
if (isset($_POST['keys'][$key])) {
$_SESSION['attributes'][$key] = $value;
}
}
if (isset($_POST['error'])) {
$_SESSION['ErrorResponse'] = TRUE;
}
\SimpleSAML\Utils\HTTP::redirectTrustedURL($returnTo);
}
// if we get this far, we need to show the login page to the user
$config = \SimpleSAML\Configuration::getInstance();
$t = new \SimpleSAML\XHTML\Template($config, 'customauth:authenticate.tpl.php');
$t->data['users'] = $users;
$t->data['attributes'] = $attributes;
$t->data['explanations'] = $explanations;
$t->data['displays'] = $displays;
$t->data['returnTo'] = $returnTo;
$t->show();
<?php
/**
* Request handler for redirect filter test.
*
* @author Olav Morken, UNINETT AS.
* @package SimpleSAMLphp
*/
if (!array_key_exists('StateId', $_REQUEST)) {
throw new \SimpleSAML\Error\BadRequest('Missing required StateId query parameter.');
}
/** @var array $state */
$state = \SimpleSAML\Auth\State::loadState($_REQUEST['StateId'], 'customauth:redirectfilter-test');
$state['Attributes']['RedirectTest2'] = ['OK'];
\SimpleSAML\Auth\ProcessingChain::resumeProcessing($state);
<?php
/**
* This page serves as the point where the user's authentication
* process is resumed after the login page.
*
* It simply passes control back to the class.
*
* @package SimpleSAMLphp
*/
namespace SimpleSAML\Module\customauth\Auth\Source;
External::resume();
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment