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

exampleauth:External: Example of integration with external authentication.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2460 44740490-163a-0410-bde0-09ae8108e29a
parent 3834fe46
No related branches found
No related tags found
No related merge requests found
...@@ -63,6 +63,16 @@ $config = array( ...@@ -63,6 +63,16 @@ $config = array(
), ),
*/ */
/*
// This authentication source serves as an example of integration with an
// external authentication engine. Take a look at the comment in the beginning
// of modules/exampleauth/lib/Auth/Source/External.php for a description of
// how to adjust it to your own site.
'example-external' => array(
'exampleauth:External',
),
*/
/* /*
'yubikey' => array( 'yubikey' => array(
'authYubiKey:YubiKey', 'authYubiKey:YubiKey',
......
<?php
/**
* Example external authentication source.
*
* This class is an example 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/exampleauth/www/resume.php to their corresponding
* location in the new module.
* 4. Replace all occurrences of "exampleauth" 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
* @version $Id$
*/
class sspmod_exampleauth_Auth_Source_External extends SimpleSAML_Auth_Source {
/**
* 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() {
/*
* 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();
}
if (!isset($_SESSION['uid'])) {
/* The user isn't authenticated. */
return NULL;
}
/*
* Find the attributes for the user.
* Note that all attributes in simpleSAMLphp are multivalued, so we need
* to store them as arrays.
*/
$attributes = array(
'uid' => array($_SESSION['uid']),
'displayName' => array($_SESSION['name']),
'mail' => array($_SESSION['mail']),
);
/* Here we generate a multivalued attribute based on the account type. */
$attributes['eduPersonAffiliation'] = array(
$_SESSION['type'], /* In this example, either 'student' or 'employee'. */
'member',
);
return $attributes;
}
/**
* Log in using an external authentication helper.
*
* @param array &$state Information about the current authentication.
*/
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['exampleauth: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 = SimpleSAML_Auth_State::saveState($state, 'exampleauth:External');
/*
* Now we generate an 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 = SimpleSAML_Module::getModuleURL('exampleauth/resume.php', array(
'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 = SimpleSAML_Module::getModuleURL('exampleauth/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.
*/
SimpleSAML_Utilities::redirect($authPage, array(
'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.
*
* @param array &$state The authentication state.
*/
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 SimpleSAML_Error_BadRequest('Missing "State" parameter.');
}
$stateId = (string)$_REQUEST['State'];
/*
* Once again, note the second parameter to the loadState function. This must
* match the string we used in the saveState-call above.
*/
$state = SimpleSAML_Auth_State::loadState($stateId, 'exampleauth:External');
/*
* Now we have the $state-array, and can use it to locate the authentication
* source.
*/
$source = SimpleSAML_Auth_Source::getById($state['exampleauth: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 SimpleSAML_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 SimpleSAML_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 SimpleSAML_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;
SimpleSAML_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.
*/
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['uid']);
/*
* 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
/**
* 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
* @version $Id$
*/
if (!isset($_REQUEST['ReturnTo'])) {
die('Missing ReturnTo parameter.');
}
$returnTo = $_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.');
}
$stateId = urldecode($matches[1]);
SimpleSAML_Auth_State::loadState($stateId, 'exampleauth:External');
/*
* 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 exampleauth:External authentication page.
*/
/*
* Our list of users.
*/
$users = array(
'student' => array(
'password' => 'student',
'uid' => 'student',
'name' => 'Student Name',
'mail' => 'somestudent@example.org',
'type' => 'student',
),
'admin' => array(
'password' => 'admin',
'uid' => 'admin',
'name' => 'Admin Name',
'mail' => 'someadmin@example.org',
'type' => 'employee',
),
);
/*
* 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'];
$password = (string)$_REQUEST['password'];
if (!isset($users[$username]) || $users[$username]['password'] !== $password) {
$badUserPass = TRUE;
} else {
$user = $users[$username];
if (!session_id()) {
/* session_start not called before. Do it here. */
session_start();
}
$_SESSION['uid'] = $user['uid'];
$_SESSION['name'] = $user['name'];
$_SESSION['mail'] = $user['mail'];
$_SESSION['type'] = $user['type'];
header('Location: ' . $returnTo);
exit();
}
}
/*
* If we get this far, we need to show the login page to the user.
*/
?><!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>exampleauth login page</title>
</head>
<body>
<h1>exampleauth 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>
<?php if ($badUserPass) { ?>
<p>Bad username or password.</p>
<?php } ?>
<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="<?php echo htmlspecialchars($returnTo); ?>">
<p><input type="submit" value="Log in"></p>
</form>
</body>
</html>
<?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
* @version $Id$
*/
sspmod_exampleauth_Auth_Source_External::resume();
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment