migrate ADFS IDP code to new IDP core and support logout with it
git-svn-id: http://simplesamlphp.googlecode.com/svn/trunk@2179 44740490-163a-0410-bde0-09ae8108e29a
This commit is contained in:
parent
52e178287e
commit
6232b9f17d
|
@ -126,6 +126,7 @@ $config = array (
|
|||
*/
|
||||
'enable.saml20-idp' => false,
|
||||
'enable.shib13-idp' => false,
|
||||
'enable.adfs-idp' => false,
|
||||
'enable.wsfed-sp' => false,
|
||||
'enable.authmemcookie' => false,
|
||||
|
||||
|
|
|
@ -57,6 +57,11 @@ class SimpleSAML_IdP {
|
|||
throw new SimpleSAML_Error_Exception('enable.shib13-idp disabled in config.php.');
|
||||
}
|
||||
$this->config = $metadata->getMetaDataConfig(substr($id, 6), 'shib13-idp-hosted');
|
||||
} elseif (substr($id, 0, 5) === 'adfs:') {
|
||||
if (!$globalConfig->getBoolean('enable.adfs-idp', FALSE)) {
|
||||
throw new SimpleSAML_Error_Exception('enable.adfs-idp disabled in config.php.');
|
||||
}
|
||||
$this->config = $metadata->getMetaDataConfig(substr($id, 5), 'adfs-idp-hosted');
|
||||
} else {
|
||||
assert(FALSE);
|
||||
}
|
||||
|
|
|
@ -130,6 +130,8 @@ class SimpleSAML_Metadata_MetaDataStorageHandlerFlatFile extends SimpleSAML_Meta
|
|||
return $baseurl . 'shib13/sp/metadata.php';
|
||||
} elseif($set === 'wsfed-sp-hosted') {
|
||||
return 'urn:federation:' . SimpleSAML_Utilities::getSelfHost();
|
||||
} elseif($set === 'adfs-idp-hosted') {
|
||||
return 'urn:federation:' . SimpleSAML_Utilities::getSelfHost() . ':idp';
|
||||
} else {
|
||||
throw new Exception('Can not generate dynamic EntityID for metadata of this type: [' . $set . ']');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
$metadata['__DYNAMIC:1__'] = array(
|
||||
'host' => '__DEFAULT__',
|
||||
'privatekey' => 'server.pem',
|
||||
'certificate' => 'server.crt',
|
||||
'auth' => 'example-userpass',
|
||||
);
|
||||
|
||||
?>
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
$metadata['urn:federation:localhost'] = array(
|
||||
'prp' => 'https://localhost/adfs/ls/',
|
||||
'simplesaml.nameidattribute' => 'uid',
|
||||
'authproc' => array(
|
||||
50 => array(
|
||||
'class' => 'core:AttributeLimit',
|
||||
'cn', 'mail', 'uid', 'eduPersonAffiliation',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
|
||||
class sspmod_adfs_IdP_ADFS {
|
||||
|
||||
public static function receiveAuthnRequest(SimpleSAML_IdP $idp) {
|
||||
try {
|
||||
// accomodate for disfunctional $_GET "windows" slash decoding in PHP
|
||||
$wctx = $_GET['wctx'];
|
||||
foreach (explode('&', $_SERVER['REQUEST_URI']) as $e) {
|
||||
$a = explode('=', $e);
|
||||
if ($a[0] == 'wctx') $wctx = urldecode($a[1]);
|
||||
}
|
||||
$requestid = $wctx;
|
||||
$issuer = $_GET['wtrealm'];
|
||||
$requestcache = array(
|
||||
'RequestID' => $requestid,
|
||||
'Issuer' => $issuer,
|
||||
'RelayState' => $requestid
|
||||
);
|
||||
|
||||
$spEntityId = $requestcache['Issuer'];
|
||||
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
|
||||
$spMetadata = $metadata->getMetaDataConfig($spEntityId, 'adfs-sp-remote');
|
||||
|
||||
SimpleSAML_Logger::info('ADFS - IdP.prp: Incoming Authentication request: '.$issuer.' id '.$requestid);
|
||||
|
||||
} catch(Exception $exception) {
|
||||
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'PROCESSAUTHNREQUEST', $exception);
|
||||
}
|
||||
|
||||
$sessionLostURL = NULL; // TODO?
|
||||
$forceAuthn = FALSE;
|
||||
$isPassive = FALSE;
|
||||
|
||||
$state = array(
|
||||
'Responder' => array('sspmod_adfs_IdP_ADFS', 'sendResponse'),
|
||||
// SimpleSAML_Auth_State::EXCEPTION_HANDLER_FUNC => array('sspmod_adfs_IdP', 'handleAuthError'),
|
||||
// SimpleSAML_Auth_State::RESTART => $sessionLostURL,
|
||||
'SPMetadata' => $spMetadata->toArray(),
|
||||
'ForceAuthn' => $forceAuthn,
|
||||
'isPassive' => $isPassive,
|
||||
'adfs:wctx' => $wctx,
|
||||
);
|
||||
|
||||
$idp->handleAuthenticationRequest($state);
|
||||
}
|
||||
|
||||
public static function ADFS_GenerateResponse($issuer, $target, $nameid, $attributes) {
|
||||
#$nameid = 'hans@surfnet.nl';
|
||||
$issueInstant = SimpleSAML_Utilities::generateTimestamp();
|
||||
$notBefore = SimpleSAML_Utilities::generateTimestamp(time() - 30);
|
||||
$assertionExpire = SimpleSAML_Utilities::generateTimestamp(time() + 60 * 5);
|
||||
$assertionID = SimpleSAML_Utilities::generateID();
|
||||
$nameidFormat = 'http://schemas.xmlsoap.org/claims/UPN';
|
||||
$result =
|
||||
'<wst:RequestSecurityTokenResponse xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
|
||||
<wst:RequestedSecurityToken>
|
||||
<saml:Assertion Issuer="' . $issuer . '" IssueInstant="' . $issueInstant . '" AssertionID="' . $assertionID . '" MinorVersion="1" MajorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
|
||||
<saml:Conditions NotOnOrAfter="' . $assertionExpire . '" NotBefore="' . $notBefore . '">
|
||||
<saml:AudienceRestrictionCondition>
|
||||
<saml:Audience>' . $target .'</saml:Audience>
|
||||
</saml:AudienceRestrictionCondition>
|
||||
</saml:Conditions>
|
||||
<saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified" AuthenticationInstant="' . $issueInstant . '">
|
||||
<saml:Subject>
|
||||
<saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
|
||||
</saml:Subject>
|
||||
</saml:AuthenticationStatement>
|
||||
<saml:AttributeStatement>
|
||||
<saml:Subject>
|
||||
<saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
|
||||
</saml:Subject>';
|
||||
foreach ($attributes as $name => $values) {
|
||||
if ((!is_array($values)) || (count($values) == 0)) continue;
|
||||
$hasValue = FALSE;
|
||||
$r = '<saml:Attribute AttributeNamespace="http://schemas.xmlsoap.org/claims" AttributeName="' . htmlspecialchars($name) .'">';
|
||||
foreach ($values as $value) {
|
||||
if ( (!isset($value)) or ($value === '')) continue;
|
||||
$r .= '<saml:AttributeValue>' . htmlspecialchars($value) . '</saml:AttributeValue>';
|
||||
$hasValue = TRUE;
|
||||
}
|
||||
$r .= '</saml:Attribute>';
|
||||
if ($hasValue) $result .= $r;
|
||||
}
|
||||
$result .= '
|
||||
</saml:AttributeStatement>
|
||||
</saml:Assertion>
|
||||
</wst:RequestedSecurityToken>
|
||||
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><wsa:EndpointReference xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||
<wsa:Address>' . $target . '</wsa:Address>
|
||||
</wsa:EndpointReference></wsp:AppliesTo>
|
||||
</wst:RequestSecurityTokenResponse>';
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function ADFS_SignResponse($response, $key, $cert) {
|
||||
$objXMLSecDSig = new XMLSecurityDSig();
|
||||
$objXMLSecDSig->idKeys = array('AssertionID');
|
||||
$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
|
||||
$responsedom = new DOMDocument();
|
||||
$responsedom->loadXML(str_replace ("\r", "", $response));
|
||||
$firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
|
||||
$objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1,
|
||||
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
|
||||
array('id_name' => 'AssertionID'));
|
||||
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
|
||||
$objKey->loadKey($key, TRUE);
|
||||
$objXMLSecDSig->sign($objKey);
|
||||
if ($cert) {
|
||||
$public_cert = file_get_contents($cert);
|
||||
$objXMLSecDSig->add509Cert($public_cert, TRUE);
|
||||
}
|
||||
$newSig = $responsedom->importNode($objXMLSecDSig->sigNode, TRUE);
|
||||
$firstassertionroot->appendChild($newSig);
|
||||
return $responsedom->saveXML();
|
||||
}
|
||||
|
||||
public static function ADFS_PostResponse($url, $wresult, $wctx) {
|
||||
print '
|
||||
<body onload="document.forms[0].submit()"><form method="post" action="' . $url . '">
|
||||
<input type="hidden" name="wa" value="wsignin1.0">
|
||||
<input type="hidden" name="wresult" value="' . htmlspecialchars($wresult) . '">
|
||||
<input type="hidden" name="wctx" value="' . htmlspecialchars($wctx) . '">
|
||||
<noscript><input type="submit" value="Continue"></noscript>
|
||||
</form></body>';
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function sendResponse(array $state) {
|
||||
$spMetadata = $state["SPMetadata"];
|
||||
$spEntityId = $spMetadata['entityid'];
|
||||
$spMetadata = SimpleSAML_Configuration::loadFromArray($spMetadata,
|
||||
'$metadata[' . var_export($spEntityId, TRUE) . ']');
|
||||
|
||||
$attributes = $state['Attributes'];
|
||||
|
||||
$nameidattribute = $spMetadata->getValue('simplesaml.nameidattribute');
|
||||
if (!empty($nameidattribute)) {
|
||||
if (!array_key_exists($nameidattribute, $attributes)) {
|
||||
throw new Exception('simplesaml.nameidattribute does not exist in resulting attribute set');
|
||||
}
|
||||
$nameid = $attributes[$nameidattribute][0];
|
||||
} else {
|
||||
$nameid = SimpleSAML_Utilities::generateID();
|
||||
}
|
||||
|
||||
$idp = SimpleSAML_IdP::getByState($state);
|
||||
$idpMetadata = $idp->getConfig();
|
||||
$idpEntityId = $idpMetadata->getString('entityid');
|
||||
|
||||
$idp->addAssociation(array(
|
||||
'id' => 'adfs:' . $spEntityId,
|
||||
'Handler' => 'sspmod_adfs_IdP_ADFS',
|
||||
'adfs:entityID' => $spEntityId,
|
||||
));
|
||||
|
||||
$response = sspmod_adfs_IdP_ADFS::ADFS_GenerateResponse($idpEntityId, $spEntityId, $nameid, $attributes);
|
||||
|
||||
$config = SimpleSAML_Configuration::getInstance();
|
||||
$certdir = $config->getPathValue('certdir', 'cert/');
|
||||
$wresult = sspmod_adfs_IdP_ADFS::ADFS_SignResponse($response, $certdir . $idpMetadata->getString('privatekey'), $certdir . $idpMetadata->getString('certificate'));
|
||||
|
||||
$wctx = $state['adfs:wctx'];
|
||||
sspmod_adfs_IdP_ADFS::ADFS_PostResponse($spMetadata->getValue('prp'), $wresult, $wctx);
|
||||
}
|
||||
/*
|
||||
public static function handleAuthError(SimpleSAML_Error_Exception $exception, array $state) {
|
||||
}
|
||||
*/
|
||||
public static function sendLogoutResponse(SimpleSAML_IdP $idp, array $state) {
|
||||
// NB:: we don't know from which SP the logout request came from
|
||||
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
|
||||
$idpMetadata = $idp->getConfig();
|
||||
SimpleSAML_Utilities::redirect($idpMetadata->getValue('redirect-after-logout', SimpleSAML_Utilities::getBaseURL()));
|
||||
}
|
||||
|
||||
public static function receiveLogoutMessage(SimpleSAML_IdP $idp) {
|
||||
$state = array(
|
||||
'Responder' => array('sspmod_adfs_IdP_ADFS', 'sendLogoutResponse'),
|
||||
);
|
||||
//$spEntityId = NULL;
|
||||
//$assocId = 'adfs:' . $spEntityId;
|
||||
$assocId = NULL;
|
||||
// TODO: verify that this is really no problem for:
|
||||
// a) SSP, because there's no caller SP...
|
||||
// b) ADFS SP because caller will be called back...
|
||||
$idp->handleLogoutRequest($state, $assocId);
|
||||
}
|
||||
|
||||
// accepts an association array, and returns an URL that can be accessed to terminate the association.
|
||||
public static function getLogoutURL(SimpleSAML_IdP $idp, array $association, $relayState) {
|
||||
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
|
||||
$idpMetadata = $idp->getConfig();
|
||||
$spMetadata = $metadata->getMetaDataConfig($association['adfs:entityID'], 'adfs-sp-remote');
|
||||
// 'https://adfs-test.showcase.surfnet.nl/adfs/ls/?wa=wsignoutcleanup1.0&wreply=https%3A%2F%2Flocalhost%2Fsimplesaml');
|
||||
$returnTo = SimpleSAML_Module::getModuleURL('adfs/idp/prp.php?assocId=' . urlencode($association["id"]) . '&relayState=' . urlencode($relayState));
|
||||
return $spMetadata->getValue('prp') . '?' . 'wa=wsignoutcleanup1.0&wreply=' . urlencode($returnTo);
|
||||
}
|
||||
}
|
|
@ -2,274 +2,30 @@
|
|||
/**
|
||||
* ADFS PRP IDP protocol support for simpleSAMLphp.
|
||||
*
|
||||
* @author Hans Zandbelt, SURFnet BV. <hans.zandbelt@surfnet.nl>
|
||||
* @author Hans Zandbelt, SURFnet bv, <hans.zandbelt@surfnet.nl>
|
||||
* @package simpleSAMLphp
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
$config = SimpleSAML_Configuration::getInstance();
|
||||
$adfsconfig = SimpleSAML_Configuration::getConfig('adfs-idp-hosted.php');
|
||||
$session = SimpleSAML_Session::getInstance();
|
||||
SimpleSAML_Logger::info('ADFS - IdP.prp: Accessing ADFS IdP endpoint prp');
|
||||
|
||||
SimpleSAML_Logger::info('ADFS - IdP.SSOService: Accessing ADFS IdP endpoint SSOService');
|
||||
|
||||
try {
|
||||
if (array_key_exists('entityId', $config)) {
|
||||
$idpentityid = $config['entityId'];
|
||||
} else {
|
||||
$idpentityid = 'urn:federation:' . SimpleSAML_Utilities::getSelfHost() . ':idp';
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'METADATA', $exception);
|
||||
}
|
||||
|
||||
SimpleSAML_Logger::info('ADFS - IdP.SSOService: Accessing ADFS IdP endpoint SSOService');
|
||||
|
||||
function ADFS_GenerateResponse($issuer, $target, $nameid, $attributes) {
|
||||
# $nameid = 'hans@surfnet.nl';
|
||||
$issueInstant = SimpleSAML_Utilities::generateTimestamp();
|
||||
$notBefore = SimpleSAML_Utilities::generateTimestamp(time() - 30);
|
||||
$assertionExpire = SimpleSAML_Utilities::generateTimestamp(time() + 60 * 5);
|
||||
$assertionID = SimpleSAML_Utilities::generateID();
|
||||
$nameidFormat = 'http://schemas.xmlsoap.org/claims/UPN';
|
||||
$result =
|
||||
'<wst:RequestSecurityTokenResponse xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
|
||||
<wst:RequestedSecurityToken>
|
||||
<saml:Assertion Issuer="' . $issuer . '" IssueInstant="' . $issueInstant . '" AssertionID="' . $assertionID . '" MinorVersion="1" MajorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
|
||||
<saml:Conditions NotOnOrAfter="' . $assertionExpire . '" NotBefore="' . $notBefore . '">
|
||||
<saml:AudienceRestrictionCondition>
|
||||
<saml:Audience>' . $target .'</saml:Audience>
|
||||
</saml:AudienceRestrictionCondition>
|
||||
</saml:Conditions>
|
||||
<saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified" AuthenticationInstant="' . $issueInstant . '">
|
||||
<saml:Subject>
|
||||
<saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
|
||||
</saml:Subject>
|
||||
</saml:AuthenticationStatement>
|
||||
<saml:AttributeStatement>
|
||||
<saml:Subject>
|
||||
<saml:NameIdentifier Format="' . $nameidFormat . '">' . htmlspecialchars($nameid) . '</saml:NameIdentifier>
|
||||
</saml:Subject>';
|
||||
foreach ($attributes as $name => $values) {
|
||||
if ((!is_array($values)) || (count($values) == 0)) continue;
|
||||
$hasValue = FALSE;
|
||||
$r = '<saml:Attribute AttributeNamespace="http://schemas.xmlsoap.org/claims" AttributeName="' . htmlspecialchars($name) .'">';
|
||||
foreach ($values as $value) {
|
||||
if ( (!isset($value)) or ($value === '')) continue;
|
||||
$r .= '<saml:AttributeValue>' . htmlspecialchars($value) . '</saml:AttributeValue>';
|
||||
$hasValue = TRUE;
|
||||
}
|
||||
$r .= '</saml:Attribute>';
|
||||
if ($hasValue) $result .= $r;
|
||||
}
|
||||
$result .= '
|
||||
</saml:AttributeStatement>
|
||||
</saml:Assertion>
|
||||
</wst:RequestedSecurityToken>
|
||||
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><wsa:EndpointReference xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||
<wsa:Address>' . $target . '</wsa:Address>
|
||||
</wsa:EndpointReference></wsp:AppliesTo>
|
||||
</wst:RequestSecurityTokenResponse>';
|
||||
return $result;
|
||||
}
|
||||
|
||||
function ADFS_SignResponse($response, $key, $cert) {
|
||||
$objXMLSecDSig = new XMLSecurityDSig();
|
||||
$objXMLSecDSig->idKeys = array('AssertionID');
|
||||
$objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
|
||||
$responsedom = new DOMDocument();
|
||||
$responsedom->loadXML(str_replace ("\r", "", $response));
|
||||
$firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
|
||||
$objXMLSecDSig->addReferenceList(array($firstassertionroot), XMLSecurityDSig::SHA1,
|
||||
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
|
||||
array('id_name' => 'AssertionID'));
|
||||
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
|
||||
$objKey->loadKey($key, TRUE);
|
||||
$objXMLSecDSig->sign($objKey);
|
||||
if ($cert) {
|
||||
$public_cert = file_get_contents($cert);
|
||||
$objXMLSecDSig->add509Cert($public_cert, TRUE);
|
||||
}
|
||||
$newSig = $responsedom->importNode($objXMLSecDSig->sigNode, TRUE);
|
||||
$firstassertionroot->appendChild($newSig);
|
||||
return $responsedom->saveXML();
|
||||
}
|
||||
|
||||
function ADFS_PostResponse($url, $wresult, $wctx) {
|
||||
print '
|
||||
<body onload="document.forms[0].submit()"><form method="post" action="' . $url . '">
|
||||
<input type="hidden" name="wa" value="wsignin1.0">
|
||||
<input type="hidden" name="wresult" value="' . htmlspecialchars($wresult) . '">
|
||||
<input type="hidden" name="wctx" value="' . htmlspecialchars($wctx) . '">
|
||||
<noscript><input type="submit" value="Continue"></noscript>
|
||||
</form></body>';
|
||||
exit;
|
||||
}
|
||||
$metadata = SimpleSAML_Metadata_MetaDataStorageHandler::getMetadataHandler();
|
||||
$idpEntityId = $metadata->getMetaDataCurrentEntityID('adfs-idp-hosted');
|
||||
$idp = SimpleSAML_IdP::getById('adfs:' . $idpEntityId);
|
||||
|
||||
if (isset($_GET['wa'])) {
|
||||
|
||||
if ($_GET['wa'] == 'wsignin1.0') {
|
||||
try {
|
||||
// accomodate for disfunctional $_GET "windows" slash decoding in PHP
|
||||
$wctx = $_GET['wctx'];
|
||||
foreach (explode('&', $_SERVER['REQUEST_URI']) as $e) {
|
||||
$a = explode('=', $e);
|
||||
if ($a[0] == 'wctx') $wctx = urldecode($a[1]);
|
||||
}
|
||||
$requestid = $wctx;
|
||||
$issuer = $_GET['wtrealm'];
|
||||
$requestcache = array(
|
||||
'RequestID' => $requestid,
|
||||
'Issuer' => $issuer,
|
||||
'RelayState' => $requestid
|
||||
);
|
||||
|
||||
$spentityid = $requestcache['Issuer'];
|
||||
|
||||
SimpleSAML_Logger::info('ADFS - IdP.SSOService: Incoming Authentication request: '.$issuer.' id '.$requestid);
|
||||
|
||||
} catch(Exception $exception) {
|
||||
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'PROCESSAUTHNREQUEST', $exception);
|
||||
}
|
||||
if ($_GET['wa'] === 'wsignout1.0') {
|
||||
sspmod_adfs_IdP_ADFS::receiveLogoutMessage($idp);
|
||||
} else if ($_GET['wa'] === 'wsignin1.0') {
|
||||
sspmod_adfs_IdP_ADFS::receiveAuthnRequest($idp);
|
||||
}
|
||||
|
||||
} elseif(isset($_GET['RequestID'])) {
|
||||
|
||||
try {
|
||||
|
||||
SimpleSAML_Logger::info('ADFS - IdP.SSOService: Got incoming authentication ID');
|
||||
|
||||
$authId = $_GET['RequestID'];
|
||||
$requestcache = $session->getAuthnRequest('adfs', $authId);
|
||||
if (!$requestcache) {
|
||||
throw new Exception('Could not retrieve cached RequestID = ' . $authId);
|
||||
}
|
||||
|
||||
} catch(Exception $exception) {
|
||||
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'CACHEAUTHNREQUEST', $exception);
|
||||
}
|
||||
|
||||
} elseif(isset($_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM])) {
|
||||
|
||||
$authProcId = $_REQUEST[SimpleSAML_Auth_ProcessingChain::AUTHPARAM];
|
||||
$authProcState = SimpleSAML_Auth_ProcessingChain::fetchProcessedState($authProcId);
|
||||
$requestcache = $authProcState['core:adfs-idp:requestcache'];
|
||||
|
||||
} else {
|
||||
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'SSOSERVICEPARAMS');
|
||||
}
|
||||
|
||||
if(SimpleSAML_Auth_Source::getById($adfsconfig->getValue('auth')) !== NULL) {
|
||||
$authSource = TRUE;
|
||||
$authority = $adfsconfig->getValue('auth');
|
||||
} else {
|
||||
$authSource = FALSE;
|
||||
$authority = $adfsconfig->getValue('authority');
|
||||
}
|
||||
|
||||
if (!$session->isValid($authority) ) {
|
||||
|
||||
SimpleSAML_Logger::info('ADFS - IdP.SSOService: Will go to authentication module ' . $adfsconfig->getValue('auth'));
|
||||
|
||||
$authId = SimpleSAML_Utilities::generateID();
|
||||
$session->setAuthnRequest('adfs', $authId, $requestcache);
|
||||
|
||||
$redirectTo = SimpleSAML_Utilities::selfURLNoQuery() . '?RequestID=' . urlencode($authId);
|
||||
|
||||
if($authSource) {
|
||||
|
||||
SimpleSAML_Auth_Default::initLogin($adfsconfig->getValue('auth'), $redirectTo);
|
||||
} else {
|
||||
$authurl = '/' . $config->getBaseURL() . $adfsconfig->getValue('auth');
|
||||
|
||||
SimpleSAML_Utilities::redirect($authurl, array(
|
||||
'RelayState' => $redirectTo,
|
||||
'AuthId' => $authId,
|
||||
'protocol' => 'adfs',
|
||||
));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
try {
|
||||
|
||||
$spentityid = $requestcache['Issuer'];
|
||||
$spmetadata = SimpleSAML_Configuration::getConfig('adfs-sp-remote.php');
|
||||
|
||||
$arr = $spmetadata->getValue($spentityid);
|
||||
if (!isset($arr)) {
|
||||
throw new Exception('Metadata for ADFS SP "' . $spentityid . '" could not be found in adfs-sp-remote.php!');
|
||||
}
|
||||
$spmetadata = SimpleSAML_Configuration::loadFromArray($arr);
|
||||
|
||||
SimpleSAML_Logger::info('ADFS - IdP.SSOService: Sending back AuthnResponse to ' . $spentityid);
|
||||
|
||||
$attributes = $session->getAttributes();
|
||||
|
||||
if (!isset($authProcState)) {
|
||||
|
||||
$idpap = $adfsconfig->getValue('authproc');
|
||||
if ($idpap) $idpap = array('authproc' => $idpap); else $idpap = array();
|
||||
$idpap['entityid'] = $idpentityid;
|
||||
|
||||
$spap = $spmetadata->getValue('authproc');
|
||||
if ($spap) $spap = array('authproc' => $spap); else $spap = array();
|
||||
$spap['entityid'] = $spentityid;
|
||||
|
||||
$pc = new SimpleSAML_Auth_ProcessingChain($idpap, $spap, 'idp');
|
||||
|
||||
$authProcState = array(
|
||||
'core:adfs-idp:requestcache' => $requestcache,
|
||||
'ReturnURL' => SimpleSAML_Utilities::selfURLNoQuery(),
|
||||
'Attributes' => $attributes,
|
||||
'Destination' => $spap,
|
||||
'Source' => $idpap,
|
||||
'isPassive' => false,
|
||||
);
|
||||
|
||||
$previousSSOTime = $session->getData('adfs-idp-ssotime', $spentityid);
|
||||
if ($previousSSOTime !== NULL) {
|
||||
$authProcState['PreviousSSOTimestamp'] = $previousSSOTime;
|
||||
}
|
||||
|
||||
try {
|
||||
$pc->processState($authProcState);
|
||||
} catch (SimpleSAML_Error_NoPassive $e) {
|
||||
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATEAUTHNRESPONSE', $exception);
|
||||
}
|
||||
|
||||
$requestcache['AuthProcState'] = $authProcState;
|
||||
}
|
||||
|
||||
$attributes = $authProcState['Attributes'];
|
||||
|
||||
$session->setData('adfs-idp-ssotime', $spentityid, time(),
|
||||
SimpleSAML_Session::DATA_TIMEOUT_LOGOUT);
|
||||
|
||||
$requestID = NULL; $relayState = NULL;
|
||||
if (array_key_exists('RequestID', $requestcache)) $requestID = $requestcache['RequestID'];
|
||||
if (array_key_exists('RelayState', $requestcache)) $relayState = $requestcache['RelayState'];
|
||||
|
||||
$nameid = $session->getNameID();
|
||||
$nameid = $nameid['Value'];
|
||||
|
||||
$nameidattribute = $spmetadata->getValue('simplesaml.nameidattribute');
|
||||
if (isset($nameidattribute)) {
|
||||
if (!array_key_exists($nameidattribute, $attributes)) {
|
||||
throw new Exception('simplesaml.nameidattribute does not exist in resulting attribute set');
|
||||
}
|
||||
$nameid = $attributes[$nameidattribute][0];
|
||||
}
|
||||
|
||||
$response = ADFS_GenerateResponse($idpentityid, $spentityid, $nameid, $attributes);
|
||||
$wresult = ADFS_SignResponse($response, $config->getPathValue('certdir', 'cert/') . $adfsconfig->getValue('key'), $config->getPathValue('certdir', 'cert/') . $adfsconfig->getValue('cert'));
|
||||
|
||||
ADFS_PostResponse($spmetadata->getValue('prp'), $wresult, $relayState);
|
||||
|
||||
} catch(Exception $exception) {
|
||||
SimpleSAML_Utilities::fatalError($session->getTrackID(), 'GENERATEAUTHNRESPONSE', $exception);
|
||||
}
|
||||
|
||||
assert('FALSE');
|
||||
} elseif(isset($_GET['assocId'])) {
|
||||
// logout response from ADFS SP
|
||||
$assocId = $_GET['assocId']; /* Association ID of the SP that sent the logout response. */
|
||||
$relayState = $_GET['relayState']; /* Data that was sent in the logout request to the SP. Can be null. */
|
||||
$logoutError = NULL; /* NULL on success, or an instance of a SimpleSAML_Error_Exception on failure. */
|
||||
$idp->handleLogoutResponse($assocId, $relayState, $logoutError);
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
Reference in New Issue