ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
ADFS.php
Go to the documentation of this file.
1<?php
2
4{
5 public static function receiveAuthnRequest(SimpleSAML_IdP $idp)
6 {
7 try {
8 parse_str($_SERVER['QUERY_STRING'], $query);
9
10 $requestid = $query['wctx'];
11 $issuer = $query['wtrealm'];
13 $spMetadata = $metadata->getMetaDataConfig($issuer, 'adfs-sp-remote');
14
15 SimpleSAML\Logger::info('ADFS - IdP.prp: Incoming Authentication request: '.$issuer.' id '.$requestid);
16 } catch(Exception $exception) {
17 throw new SimpleSAML_Error_Error('PROCESSAUTHNREQUEST', $exception);
18 }
19
20 $state = array(
21 'Responder' => array('sspmod_adfs_IdP_ADFS', 'sendResponse'),
22 'SPMetadata' => $spMetadata->toArray(),
23 'ForceAuthn' => false,
24 'isPassive' => false,
25 'adfs:wctx' => $requestid,
26 );
27
28 $idp->handleAuthenticationRequest($state);
29 }
30
32 {
34 $notBefore = SimpleSAML\Utils\Time::generateTimestamp(time() - 30);
35 $assertionExpire = SimpleSAML\Utils\Time::generateTimestamp(time() + 60 * 5);
37 $nameidFormat = 'http://schemas.xmlsoap.org/claims/UPN';
38 $nameid = htmlspecialchars($nameid);
39
40 $result = <<<MSG
41<wst:RequestSecurityTokenResponse xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
42 <wst:RequestedSecurityToken>
43 <saml:Assertion Issuer="$issuer" IssueInstant="$issueInstant" AssertionID="$assertionID" MinorVersion="1" MajorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
44 <saml:Conditions NotOnOrAfter="$assertionExpire" NotBefore="$notBefore">
45 <saml:AudienceRestrictionCondition>
46 <saml:Audience>$target</saml:Audience>
47 </saml:AudienceRestrictionCondition>
48 </saml:Conditions>
49 <saml:AuthenticationStatement AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified" AuthenticationInstant="$issueInstant">
50 <saml:Subject>
51 <saml:NameIdentifier Format="$nameidFormat">$nameid</saml:NameIdentifier>
52 </saml:Subject>
53 </saml:AuthenticationStatement>
54 <saml:AttributeStatement>
55 <saml:Subject>
56 <saml:NameIdentifier Format="$nameidFormat">$nameid</saml:NameIdentifier>
57 </saml:Subject>
58MSG;
59
60 foreach ($attributes as $name => $values) {
61 if ((!is_array($values)) || (count($values) == 0)) {
62 continue;
63 }
64
65 list($namespace, $name) = SimpleSAML\Utils\Attributes::getAttributeNamespace($name, 'http://schemas.xmlsoap.org/claims');
66 foreach ($values as $value) {
67 if ((!isset($value)) || ($value === '')) {
68 continue;
69 }
70 $value = htmlspecialchars($value);
71
72 $result .= <<<MSG
73 <saml:Attribute AttributeNamespace="$namespace" AttributeName="$name">
74 <saml:AttributeValue>$value</saml:AttributeValue>
75 </saml:Attribute>
76MSG;
77
78 }
79 }
80
81 $result .= <<<MSG
82 </saml:AttributeStatement>
83 </saml:Assertion>
84 </wst:RequestedSecurityToken>
85 <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
86 <wsa:EndpointReference xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
87 <wsa:Address>$target</wsa:Address>
88 </wsa:EndpointReference>
89 </wsp:AppliesTo>
90</wst:RequestSecurityTokenResponse>
91MSG;
92
93 return $result;
94 }
95
96 private static function signResponse($response, $key, $cert)
97 {
98 $objXMLSecDSig = new XMLSecurityDSig();
99 $objXMLSecDSig->idKeys = array('AssertionID');
100 $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
101 $responsedom = \SAML2\DOMDocumentFactory::fromString(str_replace ("\r", "", $response));
102 $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0);
103 $objXMLSecDSig->addReferenceList(
104 array($firstassertionroot), XMLSecurityDSig::SHA1,
105 array('http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N),
106 array('id_name' => 'AssertionID')
107 );
108 $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
109 $objKey->loadKey($key, true);
110 $objXMLSecDSig->sign($objKey);
111 if ($cert) {
112 $public_cert = file_get_contents($cert);
113 $objXMLSecDSig->add509Cert($public_cert, true);
114 }
115 $newSig = $responsedom->importNode($objXMLSecDSig->sigNode, true);
116 $firstassertionroot->appendChild($newSig);
117 return $responsedom->saveXML();
118 }
119
120 private static function postResponse($url, $wresult, $wctx)
121 {
122 $wresult = htmlspecialchars($wresult);
123 $wctx = htmlspecialchars($wctx);
124
125 $post = <<<MSG
126 <body onload="document.forms[0].submit()">
127 <form method="post" action="$url">
128 <input type="hidden" name="wa" value="wsignin1.0">
129 <input type="hidden" name="wresult" value="$wresult">
130 <input type="hidden" name="wctx" value="$wctx">
131 <noscript>
132 <input type="submit" value="Continue">
133 </noscript>
134 </form>
135 </body>
136MSG;
137
138 echo $post;
139 exit;
140 }
141
142 public static function sendResponse(array $state)
143 {
144 $spMetadata = $state["SPMetadata"];
145 $spEntityId = $spMetadata['entityid'];
147 '$metadata[' . var_export($spEntityId, true) . ']');
148
149 $attributes = $state['Attributes'];
150
151 $nameidattribute = $spMetadata->getValue('simplesaml.nameidattribute');
152 if (!empty($nameidattribute)) {
153 if (!array_key_exists($nameidattribute, $attributes)) {
154 throw new Exception('simplesaml.nameidattribute does not exist in resulting attribute set');
155 }
156 $nameid = $attributes[$nameidattribute][0];
157 } else {
159 }
160
162 $idpMetadata = $idp->getConfig();
163 $idpEntityId = $idpMetadata->getString('entityid');
164
165 $idp->addAssociation(array(
166 'id' => 'adfs:' . $spEntityId,
167 'Handler' => 'sspmod_adfs_IdP_ADFS',
168 'adfs:entityID' => $spEntityId,
169 ));
170
172
173 $privateKeyFile = \SimpleSAML\Utils\Config::getCertPath($idpMetadata->getString('privatekey'));
174 $certificateFile = \SimpleSAML\Utils\Config::getCertPath($idpMetadata->getString('certificate'));
175 $wresult = sspmod_adfs_IdP_ADFS::signResponse($response, $privateKeyFile, $certificateFile);
176
177 $wctx = $state['adfs:wctx'];
178 sspmod_adfs_IdP_ADFS::postResponse($spMetadata->getValue('prp'), $wresult, $wctx);
179 }
180
181 public static function sendLogoutResponse(SimpleSAML_IdP $idp, array $state)
182 {
183 // NB:: we don't know from which SP the logout request came from
185 $idpMetadata = $idp->getConfig();
186 \SimpleSAML\Utils\HTTP::redirectTrustedURL($idpMetadata->getValue('redirect-after-logout', \SimpleSAML\Utils\HTTP::getBaseURL()));
187 }
188
190 {
191 // if a redirect is to occur based on wreply, we will redirect to url as
192 // this implies an override to normal sp notification
193 if (isset($_GET['wreply']) && !empty($_GET['wreply'])) {
194 $idp->doLogoutRedirect(\SimpleSAML\Utils\HTTP::checkURLAllowed($_GET['wreply']));
195 assert('false');
196 }
197
198 $state = array(
199 'Responder' => array('sspmod_adfs_IdP_ADFS', 'sendLogoutResponse'),
200 );
201 $assocId = null;
202 // TODO: verify that this is really no problem for:
203 // a) SSP, because there's no caller SP.
204 // b) ADFS SP because caller will be called back..
205 $idp->handleLogoutRequest($state, $assocId);
206 }
207
208 // accepts an association array, and returns a URL that can be accessed to terminate the association
210 {
212 $idpMetadata = $idp->getConfig();
213 $spMetadata = $metadata->getMetaDataConfig($association['adfs:entityID'], 'adfs-sp-remote');
214 $returnTo = SimpleSAML\Module::getModuleURL('adfs/idp/prp.php?assocId=' . urlencode($association["id"]) . '&relayState=' . urlencode($relayState));
215 return $spMetadata->getValue('prp') . '?' . 'wa=wsignoutcleanup1.0&wreply=' . urlencode($returnTo);
216 }
217}
catch(Exception $e) if(!($request instanceof \SAML2\ArtifactResolve)) $issuer
$result
$metadata['__DYNAMIC:1__']
$spEntityId
$sc SubjectConfirmationData NotOnOrAfter
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
if(!isset($_REQUEST['ReturnTo'])) $returnTo
Definition: authpage.php:16
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
static info($string)
Definition: Logger.php:201
static getModuleURL($resource, array $parameters=array())
Get absolute URL to a specified module resource.
Definition: Module.php:303
static getAttributeNamespace($name, $defaultns)
Extract an attribute's namespace, or revert to default.
Definition: Attributes.php:123
static getCertPath($path)
Resolves a path that may be relative to the cert-directory.
Definition: Config.php:22
static redirectTrustedURL($url, $parameters=array())
This function redirects to the specified URL without performing any security checks.
Definition: HTTP.php:962
static generateID()
Generate a random identifier, ID_LENGTH bytes long.
Definition: Random.php:26
static generateTimestamp($instant=null)
This function generates a timestamp on the form used by the SAML protocols.
Definition: Time.php:32
static loadFromArray($config, $location='[ARRAY]', $instance=null)
Loads a configuration from the given array.
static getByState(array &$state)
Retrieve the IdP "owning" the state.
Definition: IdP.php:152
static getMetadataHandler()
This function retrieves the current instance of the metadata handler.
static receiveLogoutMessage(SimpleSAML_IdP $idp)
Definition: ADFS.php:189
static sendResponse(array $state)
Definition: ADFS.php:142
static getLogoutURL(SimpleSAML_IdP $idp, array $association, $relayState)
Definition: ADFS.php:209
static signResponse($response, $key, $cert)
Definition: ADFS.php:96
static receiveAuthnRequest(SimpleSAML_IdP $idp)
Definition: ADFS.php:5
static postResponse($url, $wresult, $wctx)
Definition: ADFS.php:120
static sendLogoutResponse(SimpleSAML_IdP $idp, array $state)
Definition: ADFS.php:181
static generateResponse($issuer, $target, $nameid, $attributes)
Definition: ADFS.php:31
$key
Definition: croninfo.php:18
if($err=$client->getError()) $namespace
if($format !==null) $name
Definition: metadata.php:146
$relayState
if(!isset($associations[$assocId])) $association
if(!isset($_REQUEST['association'])) $assocId
$idpMetadata
$spMetadata
Attribute-related utility methods.
$post
Definition: post.php:34
$query
$url
$response
$idpEntityId
Definition: prp.php:12
$idp
Definition: prp.php:13
$attributes
getBaseURL($t, $type='get', $key=null, $value=null)
Definition: showstats.php:133
$nameid
Definition: status.php:36
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']