public function finalStep(&$state) { SimpleSAML_Logger::debug("oauth wrap: Using this verification code [" . $state['authwindowslive:wrap_verification_code'] . "]"); // Retrieve Access Token // Documentation at: http://msdn.microsoft.com/en-us/library/ff749686.aspx $postData = 'wrap_client_id=' . urlencode($this->key) . '&wrap_client_secret=' . urlencode($this->secret) . '&wrap_callback=' . urlencode(SimpleSAML_Module::getModuleUrl('authwindowslive') . '/linkback.php') . '&wrap_verification_code=' . urlencode($state['authwindowslive:wrap_verification_code']); $context = array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postData)); $result = SimpleSAML_Utilities::fetch('https://consent.live.com/AccessToken.aspx', $context); parse_str($result, $response); // error checking of $response to make sure we can proceed if (!array_key_exists('wrap_access_token', $response)) { throw new Exception('[' . $response['error_code'] . '] ' . $response['wrap_error_reason'] . "\r\nNo wrap_access_token returned - cannot proceed\r\n" . $response['internal_info']); } SimpleSAML_Logger::debug("Got an access token from the OAuth WRAP service provider [" . $response['wrap_access_token'] . "] for user [" . $response['uid'] . "]"); // Documentation at: http://msdn.microsoft.com/en-us/library/ff751708.aspx $opts = array('http' => array('header' => "Accept: application/json\r\nAuthorization: WRAP access_token=" . $response['wrap_access_token'] . "\r\n")); $data = SimpleSAML_Utilities::fetch('https://apis.live.net/V4.1/cid-' . $response['uid'] . '/Profiles', $opts); $userdata = json_decode($data, TRUE); $attributes = array(); $attributes['windowslive_uid'] = array($response['uid']); $attributes['windowslive_targetedID'] = array('http://windowslive.com!' . $response['uid']); $attributes['windowslive_user'] = array($response['uid'] . '@windowslive.com'); if (array_key_exists('Entries', $userdata)) { foreach ($userdata['Entries'][0] as $key => $value) { if (is_string($value)) { $attributes['windowslive.' . $key] = array((string) $value); } } if (array_key_exists('Emails', $userdata['Entries'][0])) { $attributes['windowslive_mail'] = array($userdata['Entries'][0]['Emails'][0]['Address']); } } SimpleSAML_Logger::debug('LiveID Returned Attributes: ' . implode(", ", array_keys($attributes))); $state['Attributes'] = $attributes; }
function casValidate($cas) { $service = SimpleSAML_Utilities::selfURL(); $service = preg_replace("/(\\?|&)?ticket=.*/", "", $service); # always tagged on by cas /** * Got response from CAS server. */ if (isset($_GET['ticket'])) { $ticket = urlencode($_GET['ticket']); #ini_set('default_socket_timeout', 15); if (isset($cas['validate'])) { # cas v1 yes|no\r<username> style $paramPrefix = strpos($cas['validate'], '?') ? '&' : '?'; $result = SimpleSAML_Utilities::fetch($cas['validate'] . $paramPrefix . 'ticket=' . $ticket . '&service=' . urlencode($service)); $res = preg_split("/\r?\n/", $result); if (strcmp($res[0], "yes") == 0) { return array($res[1], array()); } else { throw new Exception("Failed to validate CAS service ticket: {$ticket}"); } } elseif (isset($cas['serviceValidate'])) { # cas v2 xml style $paramPrefix = strpos($cas['serviceValidate'], '?') ? '&' : '?'; $result = SimpleSAML_Utilities::fetch($cas['serviceValidate'] . $paramPrefix . 'ticket=' . $ticket . '&service=' . urlencode($service)); $dom = DOMDocument::loadXML($result); $xPath = new DOMXpath($dom); $xPath->registerNamespace("cas", 'http://www.yale.edu/tp/cas'); $success = $xPath->query("/cas:serviceResponse/cas:authenticationSuccess/cas:user"); if ($success->length == 0) { $failure = $xPath->evaluate("/cas:serviceResponse/cas:authenticationFailure"); throw new Exception("Error when validating CAS service ticket: " . $failure->item(0)->textContent); } else { $attributes = array(); if ($casattributes = $cas['attributes']) { # some has attributes in the xml - attributes is a list of XPath expressions to get them foreach ($casattributes as $name => $query) { $attrs = $xPath->query($query); foreach ($attrs as $attrvalue) { $attributes[$name][] = $attrvalue->textContent; } } } $casusername = $success->item(0)->textContent; return array($casusername, $attributes); } } else { throw new Exception("validate or serviceValidate not specified"); } /** * First request, will redirect the user to the CAS server for authentication. */ } else { SimpleSAML_Logger::info("AUTH - cas-ldap: redirecting to {$cas['login']}"); SimpleSAML_Utilities::redirectTrustedURL($cas['login'], array('service' => $service)); } }
public function getUserInfo($url, $accessToken) { $data_req = OAuthRequest::from_consumer_and_token($this->consumer, $accessToken, "GET", $url, NULL); $data_req->sign_request($this->signer, $this->consumer, $accessToken); $data = SimpleSAML_Utilities::fetch($data_req->to_url()); #print_r($data); $dataDecoded = json_decode($data, TRUE); return $dataDecoded; }
/** * This function parses a file where the root node is either an EntityDescriptor element or an * EntitiesDescriptor element. In both cases it will return an associative array of SAMLParser instances. If * the file contains a single EntityDescriptorElement, then the array will contain a single SAMLParser * instance. * * @param $file The path to the file which contains the EntityDescriptor or EntitiesDescriptor element. * @return An array of SAMLParser instances. */ public static function parseDescriptorsFile($file) { if ($file === NULL) { throw new Exception('Cannot open file NULL. File name not specified.'); } $data = SimpleSAML_Utilities::fetch($file); $doc = new DOMDocument(); $res = $doc->loadXML($data); if ($res !== TRUE) { throw new Exception('Failed to read XML from file: ' . $file); } if ($doc->documentElement === NULL) { throw new Exception('Opened file is not an XML document: ' . $file); } return self::parseDescriptorsElement($doc->documentElement); }
/** * Retrieve and parse the metadata. * * @return SAML2_XML_md_EntitiesDescriptor|SAML2_XML_md_EntityDescriptor|NULL * The downloaded metadata or NULL if we were unable to download or parse it. */ private function downloadMetadata() { SimpleSAML\Logger::debug($this->logLoc . 'Downloading metadata from ' . var_export($this->url, TRUE)); $context = array('ssl' => array()); if ($this->sslCAFile !== NULL) { $context['ssl']['cafile'] = SimpleSAML_Utilities::resolveCert($this->sslCAFile); SimpleSAML\Logger::debug($this->logLoc . 'Validating https connection against CA certificate(s) found in ' . var_export($context['ssl']['cafile'], TRUE)); $context['ssl']['verify_peer'] = TRUE; $context['ssl']['CN_match'] = parse_url($this->url, PHP_URL_HOST); } $data = SimpleSAML_Utilities::fetch($this->url, $context); if ($data === FALSE || $data === NULL) { SimpleSAML\Logger::error($this->logLoc . 'Unable to load metadata from ' . var_export($this->url, TRUE)); return NULL; } $doc = new DOMDocument(); $res = $doc->loadXML($data); if (!$res) { SimpleSAML\Logger::error($this->logLoc . 'Error parsing XML from ' . var_export($this->url, TRUE)); return NULL; } $root = SAML2_Utils::xpQuery($doc->firstChild, '/saml_metadata:EntityDescriptor|/saml_metadata:EntitiesDescriptor'); if (count($root) === 0) { SimpleSAML\Logger::error($this->logLoc . 'No <EntityDescriptor> or <EntitiesDescriptor> in metadata from ' . var_export($this->url, TRUE)); return NULL; } if (count($root) > 1) { SimpleSAML\Logger::error($this->logLoc . 'More than one <EntityDescriptor> or <EntitiesDescriptor> in metadata from ' . var_export($this->url, TRUE)); return NULL; } $root = $root[0]; try { if ($root->localName === 'EntityDescriptor') { $md = new SAML2_XML_md_EntityDescriptor($root); } else { $md = new SAML2_XML_md_EntitiesDescriptor($root); } } catch (Exception $e) { SimpleSAML\Logger::error($this->logLoc . 'Unable to parse metadata from ' . var_export($this->url, TRUE) . ': ' . $e->getMessage()); return NULL; } if ($this->certificate !== NULL) { $file = SimpleSAML_Utilities::resolveCert($this->certificate); $certData = file_get_contents($file); if ($certData === FALSE) { throw new SimpleSAML_Error_Exception('Error loading certificate from ' . var_export($file, TRUE)); } // Extract the public key from the certificate for validation $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public')); $key->loadKey($file, TRUE); if (!$md->validate($key)) { SimpleSAML\Logger::error($this->logLoc . 'Error validating signature on metadata.'); return NULL; } SimpleSAML\Logger::debug($this->logLoc . 'Validated signature on metadata from ' . var_export($this->url, TRUE)); } return $md; }
try { /* Load simpleSAMLphp, configuration and metadata */ $casconfig = SimpleSAML_Configuration::getConfig('module_casserver.php'); $path = $casconfig->resolvePath($casconfig->getValue('ticketcache', 'ticketcache')); $ticketcontent = retrieveTicket($ticket, $path); $usernamefield = $casconfig->getValue('attrname', 'eduPersonPrincipalName'); $dosendattributes = $casconfig->getValue('attributes', FALSE); $attributes = $ticketcontent['attributes']; $pgtiouxml = ""; if ($ticketcontent['service'] == $service && $ticketcontent['forceAuthn'] == $forceAuthn && array_key_exists($usernamefield, $attributes) && $ticketcontent['validbefore'] > time()) { if (isset($_GET['pgtUrl'])) { $pgtUrl = $_GET['pgtUrl']; $pgtiou = str_replace('_', 'PGTIOU-', SimpleSAML_Utilities::generateID()); $pgt = str_replace('_', 'PGT-', SimpleSAML_Utilities::generateID()); $content = array('attributes' => $attributes, 'forceAuthn' => false, 'proxies' => array_merge(array($service), $ticketcontent['proxies']), 'validbefore' => time() + 60); SimpleSAML_Utilities::fetch($pgtUrl . '?pgtIou=' . $pgtiou . '&pgtId=' . $pgt); storeTicket($pgt, $path, $content); $pgtiouxml = "\n<cas:proxyGrantingTicket>{$pgtiou}</cas:proxyGrantingTicket>\n"; } $proxiesxml = join("\n", array_map(create_function('$a', 'return "<cas:proxy>$a</cas:proxy>";'), $ticketcontent['proxies'])); if ($proxiesxml) { $proxiesxml = "<cas:proxies>\n{$proxiesxml}\n</cas:proxies>\n"; } returnResponse('YES', $function, $attributes[$usernamefield][0], $dosendattributes ? $attributes : array(), $pgtiouxml . $proxiesxml); } else { returnResponse('NO', $function); } } catch (Exception $e) { returnResponse('NO', $function, $e->getMessage()); } function returnResponse($value, $function, $usrname = '', $attributes = array(), $xtraxml = "")
/** * This function receives a SAML 1.1 artifact. * * @param SimpleSAML_Configuration $spMetadata The metadata of the SP. * @param SimpleSAML_Configuration $idpMetadata The metadata of the IdP. * @return string The <saml1p:Response> element, as an XML string. */ public static function receive(SimpleSAML_Configuration $spMetadata, SimpleSAML_Configuration $idpMetadata) { $artifacts = self::getArtifacts(); $request = self::buildRequest($artifacts); SimpleSAML_Utilities::debugMessage($msgStr, 'out'); $url = $idpMetadata->getDefaultEndpoint('ArtifactResolutionService', array('urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding')); $url = $url['Location']; $peerPublicKeys = $idpMetadata->getPublicKeys('signing', TRUE); $certData = ''; foreach ($peerPublicKeys as $key) { if ($key['type'] !== 'X509Certificate') { continue; } $certData .= "-----BEGIN CERTIFICATE-----\n" . chunk_split($key['X509Certificate'], 64) . "-----END CERTIFICATE-----\n"; } $file = SimpleSAML_Utilities::getTempDir() . '/' . sha1($certData) . '.crt'; if (!file_exists($file)) { SimpleSAML_Utilities::writeFile($file, $certData); } $spKeyCertFile = SimpleSAML_Utilities::resolveCert($spMetadata->getString('privatekey')); $opts = array('ssl' => array('verify_peer' => TRUE, 'cafile' => $file, 'local_cert' => $spKeyCertFile, 'capture_peer_cert' => TRUE, 'capture_peer_chain' => TRUE), 'http' => array('method' => 'POST', 'content' => $request, 'header' => 'SOAPAction: http://www.oasis-open.org/committees/security' . "\r\n" . 'Content-Type: text/xml')); /* Fetch the artifact. */ $response = SimpleSAML_Utilities::fetch($url, $opts); if ($response === FALSE) { throw new SimpleSAML_Error_Exception('Failed to retrieve assertion from IdP.'); } SimpleSAML_Utilities::debugMessage($response, 'in'); /* Find the response in the SOAP message. */ $response = self::extractResponse($response); return $response; }
/** * Uses the cas service validate, this provides additional attributes * * @param string $ticket * @param string $service * @return list username and attributes */ private function casServiceValidate($ticket, $service) { $url = SimpleSAML_Utilities::addURLparameter($this->_casConfig['serviceValidate'], array('ticket' => $ticket, 'service' => $service)); $result = SimpleSAML_Utilities::fetch($url); $dom = DOMDocument::loadXML($result); $xPath = new DOMXpath($dom); $xPath->registerNamespace("cas", 'http://www.yale.edu/tp/cas'); $success = $xPath->query("/cas:serviceResponse/cas:authenticationSuccess/cas:user"); if ($success->length == 0) { $failure = $xPath->evaluate("/cas:serviceResponse/cas:authenticationFailure"); throw new Exception("Error when validating CAS service ticket: " . $failure->item(0)->textContent); } else { $attributes = array(); if ($casattributes = $this->_casConfig['attributes']) { # some has attributes in the xml - attributes is a list of XPath expressions to get them foreach ($casattributes as $name => $query) { $attrs = $xPath->query($query); foreach ($attrs as $attrvalue) { $attributes[$name][] = $attrvalue->textContent; } } } $casusername = $success->item(0)->textContent; return array($casusername, $attributes); } }
/** * This function processes a SAML metadata file. * * @param $source */ public function loadSource($source) { if (preg_match('@^https?://@i', $source['src'])) { // Build new HTTP context $context = $this->createContext($source); // GET! try { list($data, $responseHeaders) = SimpleSAML_Utilities::fetch($source['src'], $context, TRUE); } catch (Exception $e) { SimpleSAML_Logger::warning('metarefresh: ' . $e->getMessage()); } // We have response headers, so the request succeeded if (!isset($responseHeaders)) { // No response headers, this means the request failed in some way, so re-use old data SimpleSAML_Logger::debug('No response from ' . $source['src'] . ' - attempting to re-use cached metadata'); $this->addCachedMetadata($source); return; } elseif (preg_match('@^HTTP/1\\.[01]\\s304\\s@', $responseHeaders[0])) { // 304 response SimpleSAML_Logger::debug('Received HTTP 304 (Not Modified) - attempting to re-use cached metadata'); $this->addCachedMetadata($source); return; } elseif (!preg_match('@^HTTP/1\\.[01]\\s200\\s@', $responseHeaders[0])) { // Other error. SimpleSAML_Logger::debug('Error from ' . $source['src'] . ' - attempting to re-use cached metadata'); $this->addCachedMetadata($source); return; } } else { /* Local file. */ $data = file_get_contents($source['src']); $responseHeaders = NULL; } /* Everything OK. Proceed. */ if (isset($source['conditionalGET']) && $source['conditionalGET']) { // Stale or no metadata, so a fresh copy SimpleSAML_Logger::debug('Downloaded fresh copy'); } $entities = $this->loadXML($data, $source); foreach ($entities as $entity) { if (isset($source['blacklist'])) { if (!empty($source['blacklist']) && in_array($entity->getEntityID(), $source['blacklist'])) { SimpleSAML_Logger::info('Skipping "' . $entity->getEntityID() . '" - blacklisted.' . "\n"); continue; } } if (isset($source['whitelist'])) { if (!empty($source['whitelist']) && !in_array($entity->getEntityID(), $source['whitelist'])) { SimpleSAML_Logger::info('Skipping "' . $entity->getEntityID() . '" - not in the whitelist.' . "\n"); continue; } } if (array_key_exists('validateFingerprint', $source) && $source['validateFingerprint'] !== NULL) { if (!$entity->validateFingerprint($source['validateFingerprint'])) { SimpleSAML_Logger::info('Skipping "' . $entity->getEntityId() . '" - could not verify signature.' . "\n"); continue; } } $template = NULL; if (array_key_exists('template', $source)) { $template = $source['template']; } $this->addMetadata($source['src'], $entity->getMetadata1xSP(), 'shib13-sp-remote', $template); $this->addMetadata($source['src'], $entity->getMetadata1xIdP(), 'shib13-idp-remote', $template); $this->addMetadata($source['src'], $entity->getMetadata20SP(), 'saml20-sp-remote', $template); $this->addMetadata($source['src'], $entity->getMetadata20IdP(), 'saml20-idp-remote', $template); $attributeAuthorities = $entity->getAttributeAuthorities(); if (!empty($attributeAuthorities)) { $this->addMetadata($source['src'], $attributeAuthorities[0], 'attributeauthority-remote', $template); } } $this->saveState($source, $responseHeaders); }
} else { $type = 'definition'; } $basefile = basename($fileWithoutExt); echo 'Action: [' . $action . ']' . "\n"; echo 'Application: [' . $application . ']' . "\n"; echo 'File orig: [' . $file . ']' . "\n"; echo 'File base: [' . $basefile . ']' . "\n"; switch ($action) { case 'pulldef': $content = SimpleSAML_Utilities::fetch($base . 'export.php?aid=' . $application . '&type=def&file=' . $basefile); file_put_contents($fileWithoutExt . '.definition.json', $content); break; case 'pull': try { $content = SimpleSAML_Utilities::fetch($base . 'export.php?aid=' . $application . '&type=translation&file=' . $basefile); file_put_contents($fileWithoutExt . '.translation.json', $content); } catch (SimpleSAML_Error_Exception $e) { echo 'Translation unavailable for ' . $basefile; SimpleSAML_Logger::warning("Translation unavailable for {$basefile} in {$base}: " . $e->getMessage()); } break; case 'push': #$content = file_get_contents($base . 'export.php?aid=' . $application . '&type=translation&file=' . $basefile); #file_put_contents($fileWithoutExt . '.translation.json' , $content); push($file, $basefile, $application, $type); break; case 'convert': include $file; $definition = json_format(convert_definition($lang)); $translation = json_format(convert_translation($lang)) . "\n";
* NOTE: * This is implemented as an array for DEMONSTRATION PURPOSES ONLY. * On a production system, this information should be stored as approprate * With each key below mapping to your concept of "customer company", * "group", "organization", "team", etc. * This should also be stored in your production datastore. */ $metadata_url_for = array(); foreach ($metadata_url_for as $idp_name => $metadata_url) { /* * Fetch SAML metadata from the URL. * NOTE: * SAML metadata changes very rarely. On a production system, * this data should be cached as approprate for your production system. */ $metadata_xml = SimpleSAML_Utilities::fetch($metadata_url); /* * Parse the SAML metadata using SimpleSAMLphp's parser. * See also: modules/metaedit/www/edit.php:34 */ SimpleSAML_Utilities::validateXMLDocument($metadata_xml, 'saml-meta'); $entities = SimpleSAML_Metadata_SAMLParser::parseDescriptorsString($metadata_xml); $entity = array_pop($entities); $idp = $entity->getMetadata20IdP(); $entity_id = $idp['entityid']; /* * Remove HTTP-POST endpoints from metadata, * since we only want to make HTTP-GET AuthN requests. */ for ($x = 0; $x < sizeof($idp['SingleSignOnService']); $x++) { $endpoint = $idp['SingleSignOnService'][$x];