getSelfURLNoQuery() public static method

Returns the URL of the current host + current view.
public static getSelfURLNoQuery ( ) : string
return string
Example #1
0
 /**
  * Obtains the SSO URL containing the AuthRequest
  * message deflated.
  *
  * @param OneLogin_Saml2_Settings $settings Settings
  */
 public function getRedirectUrl($returnTo = null)
 {
     $settings = $this->auth->getSettings();
     $authnRequest = new OneLogin_Saml2_AuthnRequest($settings);
     $parameters = array('SAMLRequest' => $authnRequest->getRequest());
     if (!empty($returnTo)) {
         $parameters['RelayState'] = $returnTo;
     } else {
         $parameters['RelayState'] = OneLogin_Saml2_Utils::getSelfURLNoQuery();
     }
     $url = OneLogin_Saml2_Utils::redirect($this->auth->getSSOurl(), $parameters, true);
     return $url;
 }
 /**
  * Tests the isValid method of the OneLogin_Saml2_LogoutResponse
  *
  * @covers OneLogin_Saml2_LogoutResponse::isValid
  */
 public function testIsValid()
 {
     $message = file_get_contents(TEST_ROOT . '/data/logout_responses/logout_response_deflated.xml.base64');
     $response = new OneLogin_Saml2_LogoutResponse($this->_settings, $message);
     $this->assertTrue($response->isValid());
     $this->_settings->setStrict(true);
     $response2 = new OneLogin_Saml2_LogoutResponse($this->_settings, $message);
     $this->assertFalse($response2->isValid());
     $this->assertContains('The LogoutResponse was received at', $response2->getError());
     $plainMessage = gzinflate(base64_decode($message));
     $currentURL = OneLogin_Saml2_Utils::getSelfURLNoQuery();
     $plainMessage = str_replace('http://stuff.com/endpoints/endpoints/sls.php', $currentURL, $plainMessage);
     $message3 = base64_encode(gzdeflate($plainMessage));
     $response3 = new OneLogin_Saml2_LogoutResponse($this->_settings, $message3);
     $this->assertTrue($response3->isValid());
 }
Example #3
0
 /**
  * Tests the processSLO method of the OneLogin_Saml2_Auth class
  * Case Valid Logout Request, validating the relayState,
  * a signed LogoutResponse is created and a redirection executed
  *
  * @covers OneLogin_Saml2_Auth::processSLO
  * @runInSeparateProcess
  */
 public function testProcessSLORequestSignedResponse()
 {
     $settingsDir = TEST_ROOT . '/settings/';
     include $settingsDir . 'settings1.php';
     $settingsInfo['security']['logoutResponseSigned'] = true;
     $auth = new OneLogin_Saml2_Auth($settingsInfo);
     $message = file_get_contents(TEST_ROOT . '/data/logout_requests/logout_request_deflated.xml.base64');
     // In order to avoid the destination problem
     $plainMessage = gzinflate(base64_decode($message));
     $currentURL = OneLogin_Saml2_Utils::getSelfURLNoQuery();
     $plainMessage = str_replace('http://stuff.com/endpoints/endpoints/sls.php', $currentURL, $plainMessage);
     $message = base64_encode(gzdeflate($plainMessage));
     $_GET['SAMLRequest'] = $message;
     $_GET['RelayState'] = 'http://relaystate.com';
     try {
         $auth->setStrict(true);
         $auth->processSLO(false);
         $this->assertFalse(true);
     } catch (Exception $e) {
         $this->assertContains('Cannot modify header information', $e->getMessage());
         $trace = $e->getTrace();
         $targetUrl = getUrlFromRedirect($trace);
         $parsedQuery = getParamsFromUrl($targetUrl);
         $sloUrl = $settingsInfo['idp']['singleLogoutService']['url'];
         $this->assertContains($sloUrl, $targetUrl);
         $this->assertArrayHasKey('SAMLResponse', $parsedQuery);
         $this->assertArrayHasKey('RelayState', $parsedQuery);
         $this->assertArrayHasKey('SigAlg', $parsedQuery);
         $this->assertArrayHasKey('Signature', $parsedQuery);
         $this->assertEquals('http://relaystate.com', $parsedQuery['RelayState']);
         $this->assertEquals(XMLSecurityKey::RSA_SHA1, $parsedQuery['SigAlg']);
     }
 }
Example #4
0
/**
 * SAMPLE Code to demonstrate how to initiate a SAML Authorization request
 *
 * When the user visits this URL, the browser will be redirected to the SSO
 * IdP with an authorization request. If successful, it will then be
 * redirected to the consume URL (specified in settings) with the auth
 * details.
 */
session_start();
require_once '../_toolkit_loader.php';
if (!isset($_SESSION['samlUserdata'])) {
    $settings = new OneLogin_Saml2_Settings();
    $authRequest = new OneLogin_Saml2_AuthnRequest($settings);
    $samlRequest = $authRequest->getRequest();
    $parameters = array('SAMLRequest' => $samlRequest);
    $parameters['RelayState'] = OneLogin_Saml2_Utils::getSelfURLNoQuery();
    $idpData = $settings->getIdPData();
    $ssoUrl = $idpData['singleSignOnService']['url'];
    $url = OneLogin_Saml2_Utils::redirect($ssoUrl, $parameters, true);
    header("Location: {$url}");
} else {
    if (!empty($_SESSION['samlUserdata'])) {
        $attributes = $_SESSION['samlUserdata'];
        echo 'You have the following attributes:<br>';
        echo '<table><thead><th>Name</th><th>Values</th></thead><tbody>';
        foreach ($attributes as $attributeName => $attributeValues) {
            echo '<tr><td>' . htmlentities($attributeName) . '</td><td><ul>';
            foreach ($attributeValues as $attributeValue) {
                echo '<li>' . htmlentities($attributeValue) . '</li>';
            }
            echo '</ul></td></tr>';
Example #5
0
 /**
  * Tests the getSelfURLNoQuery method of the OneLogin_Saml2_Utils
  *
  * @covers OneLogin_Saml2_Utils::getSelfURLNoQuery
  */
 public function testGetSelfURLNoQuery()
 {
     $url = OneLogin_Saml2_Utils::getSelfURLhost();
     $url .= $_SERVER['SCRIPT_NAME'];
     $this->assertEquals($url, OneLogin_Saml2_Utils::getSelfURLNoQuery());
     $_SERVER['PATH_INFO'] = '/test';
     $this->assertEquals($url . '/test', OneLogin_Saml2_Utils::getSelfURLNoQuery());
 }
Example #6
0
 /**
  * Tests the isValid method of the OneLogin_Saml2_Response
  * Case valid encrypted assertion
  *
  * Signed data can't be modified, so Destination will always fail in strict mode
  *
  * @covers OneLogin_Saml2_Response::isValid
  */
 public function testIsValidEnc()
 {
     $xml = file_get_contents(TEST_ROOT . '/data/responses/double_signed_encrypted_assertion.xml.base64');
     $response = new OneLogin_Saml2_Response($this->_settings, $xml);
     $this->assertTrue($response->isValid());
     $xml2 = file_get_contents(TEST_ROOT . '/data/responses/signed_encrypted_assertion.xml.base64');
     $response2 = new OneLogin_Saml2_Response($this->_settings, $xml2);
     $this->assertTrue($response2->isValid());
     $xml3 = file_get_contents(TEST_ROOT . '/data/responses/signed_message_encrypted_assertion.xml.base64');
     $response3 = new OneLogin_Saml2_Response($this->_settings, $xml3);
     $this->assertTrue($response3->isValid());
     $settingsDir = TEST_ROOT . '/settings/';
     include $settingsDir . 'settings1.php';
     $settingsInfo['strict'] = true;
     $settings = new OneLogin_Saml2_Settings($settingsInfo);
     $xml4 = file_get_contents(TEST_ROOT . '/data/responses/valid_encrypted_assertion.xml.base64');
     // In order to avoid the destination problem
     $plainMessage4 = base64_decode($xml4);
     $currentURL = OneLogin_Saml2_Utils::getSelfURLNoQuery();
     $plainMessage4 = str_replace('http://stuff.com/endpoints/endpoints/acs.php', $currentURL, $plainMessage4);
     $message4 = base64_encode($plainMessage4);
     $response4 = new OneLogin_Saml2_Response($settings, $message4);
     $response4->isValid();
     $this->assertContains('No Signature found. SAML Response rejected', $response4->getError());
 }
Example #7
0
 /**
  * Determines if the SAML LogoutResponse is valid
  *
  * @param string $requestId The ID of the LogoutRequest sent by this SP to the IdP
  *
  * @throws Exception
  * @return bool Returns if the SAML LogoutResponse is or not valid
  */
 public function isValid($requestId = null)
 {
     try {
         $idpData = $this->_settings->getIdPData();
         $idPEntityId = $idpData['entityId'];
         if ($this->_settings->isStrict()) {
             $res = OneLogin_Saml2_Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
             if (!$res instanceof DOMDocument) {
                 throw new Exception("Invalid SAML Logout Response. Not match the saml-schema-protocol-2.0.xsd");
             }
             $security = $this->_settings->getSecurityData();
             // Check if the InResponseTo of the Logout Response matchs the ID of the Logout Request (requestId) if provided
             if (isset($requestId) && $this->document->documentElement->hasAttribute('InResponseTo')) {
                 $inResponseTo = $this->document->documentElement->getAttribute('InResponseTo');
                 if ($requestId != $inResponseTo) {
                     throw new Exception("The InResponseTo of the Logout Response: {$inResponseTo}, does not match the ID of the Logout request sent by the SP: {$requestId}");
                 }
             }
             // Check issuer
             $issuer = $this->getIssuer();
             if (empty($issuer) || $issuer != $idPEntityId) {
                 throw new Exception("Invalid issuer in the Logout Request");
             }
             $currentURL = OneLogin_Saml2_Utils::getSelfURLNoQuery();
             // Check destination
             if ($this->document->documentElement->hasAttribute('Destination')) {
                 $destination = $this->document->documentElement->getAttribute('Destination');
                 if (!empty($destination)) {
                     if (strpos($destination, $currentURL) === false) {
                         throw new Exception("The LogoutRequest was received at {$currentURL} instead of {$destination}");
                     }
                 }
             }
             if ($security['wantMessagesSigned']) {
                 if (!isset($_GET['Signature'])) {
                     throw new Exception("The Message of the Logout Response is not signed and the SP requires it");
                 }
             }
         }
         if (isset($_GET['Signature'])) {
             if (!isset($_GET['SigAlg'])) {
                 $signAlg = XMLSecurityKey::RSA_SHA1;
             } else {
                 $signAlg = $_GET['SigAlg'];
             }
             if ($signAlg != XMLSecurityKey::RSA_SHA1) {
                 throw new Exception('Invalid signAlg in the recieved Logout Response');
             }
             $signedQuery = 'SAMLResponse=' . urlencode($_GET['SAMLResponse']);
             if (isset($_GET['RelayState'])) {
                 $signedQuery .= '&RelayState=' . urlencode($_GET['RelayState']);
             }
             $signedQuery .= '&SigAlg=' . urlencode($signAlg);
             if (!isset($idpData['x509cert']) || empty($idpData['x509cert'])) {
                 throw new Exception('In order to validate the sign on the Logout Response, the x509cert of the IdP is required');
             }
             $cert = $idpData['x509cert'];
             $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
             $objKey->loadKey($cert, false, true);
             if (!$objKey->verifySignature($signedQuery, base64_decode($_GET['Signature']))) {
                 throw new Exception('Signature validation failed. Logout Response rejected');
             }
         }
         return true;
     } catch (Exception $e) {
         $debug = $this->_settings->isDebugActive();
         if ($debug) {
             echo $e->getMessage();
         }
         return false;
     }
 }
Example #8
0
 /**
  * Tests the isValid method of the OneLogin_Saml2_LogoutRequest
  *
  * @covers OneLogin_Saml2_LogoutRequest::isValid
  */
 public function testIsInValidSign()
 {
     $currentURL = OneLogin_Saml2_Utils::getSelfURLNoQuery();
     $this->_settings->setStrict(false);
     $_GET = array('SAMLRequest' => 'lVLBitswEP0Vo7tjeWzJtki8LIRCYLvbNksPewmyPc6K2pJqyXQ/v1LSQlroQi/DMJr33rwZbZ2cJysezNms/gt+X9H55G2etBOXlx1ZFy2MdMoJLWd0wvfieP/xQcCGCrsYb3ozkRvI+wjpHC5eGU2Sw35HTg3lA8hqZFwWFcMKsStpxbEsxoLXeQN9OdY1VAgk+YqLC8gdCUQB7tyKB+281D6UaF6mtEiBPudcABcMXkiyD26Ulv6CevXeOpFlVvlunb5ttEmV3ZjlnGn8YTRO5qx0NuBs8kzpAd829tXeucmR5NH4J/203I8el6gFRUqbFPJnyEV51Wq30by4TLW0/9ZyarYTxt4sBsjUYLMZvRykl1Fxm90SXVkfwx4P++T4KSafVzmpUcVJ/sfSrQZJPphllv79W8WKGtLx0ir8IrVTqD1pT2MH3QAMSs4KTvui71jeFFiwirOmprwPkYW063+5uRq4urHiiC4e8hCX3J5wqAEGaPpw9XB5JmkBdeDqSlkz6CmUXdl0Qae5kv2F/1384wu3PwE=', 'RelayState' => '_1037fbc88ec82ce8e770b2bed1119747bb812a07e6', 'SigAlg' => 'http://www.w3.org/2000/09/xmldsig#rsa-sha1', 'Signature' => 'XCwCyI5cs7WhiJlB5ktSlWxSBxv+6q2xT3c8L7dLV6NQG9LHWhN7gf8qNsahSXfCzA0Ey9dp5BQ0EdRvAk2DIzKmJY6e3hvAIEp1zglHNjzkgcQmZCcrkK9Czi2Y1WkjOwR/WgUTUWsGJAVqVvlRZuS3zk3nxMrLH6f7toyvuJc=');
     $request = gzinflate(base64_decode($_GET['SAMLRequest']));
     $encodedRequest = $_GET['SAMLRequest'];
     $logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings, $encodedRequest);
     $this->assertTrue($logoutRequest->isValid());
     $this->_settings->setStrict(true);
     $logoutRequest2 = new OneLogin_Saml2_LogoutRequest($this->_settings, $encodedRequest);
     $this->assertFalse($logoutRequest2->isValid());
     $this->assertContains('The LogoutRequest was received at', $logoutRequest2->getError());
     $this->_settings->setStrict(false);
     $oldSignature = $_GET['Signature'];
     $_GET['Signature'] = 'vfWbbc47PkP3ejx4bjKsRX7lo9Ml1WRoE5J5owF/0mnyKHfSY6XbhO1wwjBV5vWdrUVX+xp6slHyAf4YoAsXFS0qhan6txDiZY4Oec6yE+l10iZbzvie06I4GPak4QrQ4gAyXOSzwCrRmJu4gnpeUxZ6IqKtdrKfAYRAcVf3333=';
     $logoutRequest3 = new OneLogin_Saml2_LogoutRequest($this->_settings, $encodedRequest);
     $this->assertFalse($logoutRequest3->isValid());
     $this->assertContains('Signature validation failed. Logout Request rejected', $logoutRequest3->getError());
     $_GET['Signature'] = $oldSignature;
     $oldSigAlg = $_GET['SigAlg'];
     unset($_GET['SigAlg']);
     $this->assertTrue($logoutRequest3->isValid());
     $oldRelayState = $_GET['RelayState'];
     $_GET['RelayState'] = 'http://example.com/relaystate';
     $this->assertFalse($logoutRequest3->isValid());
     $this->assertContains('Signature validation failed. Logout Request rejected', $logoutRequest3->getError());
     $this->_settings->setStrict(true);
     $request2 = str_replace('https://pitbulk.no-ip.org/newonelogin/demo1/index.php?sls', $currentURL, $request);
     $request2 = str_replace('https://pitbulk.no-ip.org/simplesaml/saml2/idp/metadata.php', 'http://idp.example.com/', $request2);
     $deflatedRequest2 = gzdeflate($request2);
     $encodedRequest2 = base64_encode($deflatedRequest2);
     $_GET['SAMLRequest'] = $encodedRequest2;
     $logoutRequest4 = new OneLogin_Saml2_LogoutRequest($this->_settings, $encodedRequest2);
     $this->assertFalse($logoutRequest4->isValid());
     $this->assertEquals('Signature validation failed. Logout Request rejected', $logoutRequest4->getError());
     $this->_settings->setStrict(false);
     $logoutRequest5 = new OneLogin_Saml2_LogoutRequest($this->_settings, $encodedRequest2);
     $this->assertFalse($logoutRequest5->isValid());
     $this->assertEquals('Signature validation failed. Logout Request rejected', $logoutRequest5->getError());
     $_GET['SigAlg'] = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
     $this->assertFalse($logoutRequest5->isValid());
     $this->assertEquals('Invalid signAlg in the recieved Logout Request', $logoutRequest5->getError());
     $settingsDir = TEST_ROOT . '/settings/';
     include $settingsDir . 'settings1.php';
     $settingsInfo['strict'] = true;
     $settingsInfo['security']['wantMessagesSigned'] = true;
     $settings = new OneLogin_Saml2_Settings($settingsInfo);
     $_GET['SigAlg'] = $oldSigAlg;
     $oldSignature = $_GET['Signature'];
     unset($_GET['Signature']);
     $logoutRequest6 = new OneLogin_Saml2_LogoutRequest($settings, $encodedRequest2);
     $this->assertFalse($logoutRequest6->isValid());
     $this->assertEquals('The Message of the Logout Request is not signed and the SP require it', $logoutRequest6->getError());
     $_GET['Signature'] = $oldSignature;
     $settingsInfo['idp']['certFingerprint'] = 'afe71c28ef740bc87425be13a2263d37971da1f9';
     unset($settingsInfo['idp']['x509cert']);
     $settings2 = new OneLogin_Saml2_Settings($settingsInfo);
     $logoutRequest7 = new OneLogin_Saml2_LogoutRequest($settings2, $encodedRequest2);
     $this->assertFalse($logoutRequest7->isValid());
     $this->assertContains('In order to validate the sign on the Logout Request, the x509cert of the IdP is required', $logoutRequest7->getError());
 }
Example #9
0
 /**
  * Determines if the SAML Response is valid using the certificate.
  *
  * @param string $requestId The ID of the AuthNRequest sent by this SP to the IdP
  *
  * @throws Exception
  * @return bool Validate the document
  */
 public function isValid($requestId = null)
 {
     try {
         // Check SAML version
         if ($this->document->documentElement->getAttribute('Version') != '2.0') {
             throw new Exception('Unsupported SAML version');
         }
         if (!$this->document->documentElement->hasAttribute('ID')) {
             throw new Exception('Missing ID attribute on SAML Response');
         }
         $singleAssertion = $this->validateNumAssertions();
         if (!$singleAssertion) {
             throw new Exception('SAML Response must contain 1 assertion');
         }
         $status = $this->checkStatus();
         $idpData = $this->_settings->getIdPData();
         $idPEntityId = $idpData['entityId'];
         $spData = $this->_settings->getSPData();
         $spEntityId = $spData['entityId'];
         $signedElements = array();
         if ($this->encrypted) {
             $signNodes = $this->decryptedDocument->getElementsByTagName('Signature');
         } else {
             $signNodes = $this->document->getElementsByTagName('Signature');
         }
         foreach ($signNodes as $signNode) {
             $signedElements[] = $signNode->parentNode->tagName;
         }
         if ($this->_settings->isStrict()) {
             $res = OneLogin_Saml2_Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
             if (!$res instanceof DOMDocument) {
                 print_r($res);
                 throw new Exception("Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd");
             }
             $security = $this->_settings->getSecurityData();
             $currentURL = OneLogin_Saml2_Utils::getSelfURLNoQuery();
             if ($this->document->documentElement->hasAttribute('InResponseTo')) {
                 $responseInResponseTo = $this->document->documentElement->getAttribute('InResponseTo');
             }
             // Check if the InResponseTo of the Response matchs the ID of the AuthNRequest (requestId) if provided
             if (isset($requestId) && isset($responseInResponseTo)) {
                 if ($requestId != $responseInResponseTo) {
                     throw new Exception("The InResponseTo of the Response: {$responseInResponseTo}, does not match the ID of the AuthNRequest sent by the SP: {$requestId}");
                 }
             }
             if (!$this->encrypted && $security['wantAssertionsEncrypted']) {
                 throw new Exception("The assertion of the Response is not encrypted and the SP requires it");
             }
             if ($security['wantNameIdEncrypted']) {
                 $encryptedIdNodes = $this->_queryAssertion('/saml:Subject/saml:EncryptedID/xenc:EncryptedData');
                 if ($encryptedIdNodes->length == 0) {
                     throw new Exception("The NameID of the Response is not encrypted and the SP requires it");
                 }
             }
             // Validate Asserion timestamps
             $validTimestamps = $this->validateTimestamps();
             if (!$validTimestamps) {
                 throw new Exception('Timing issues (please check your clock settings)');
             }
             // EncryptedAttributes are not supported
             $encryptedAttributeNodes = $this->_queryAssertion('/saml:AttributeStatement/saml:EncryptedAttribute');
             if ($encryptedAttributeNodes->length > 0) {
                 throw new Exception("There is an EncryptedAttribute in the Response and this SP not support them");
             }
             // Check destination
             if ($this->document->documentElement->hasAttribute('Destination')) {
                 $destination = $this->document->documentElement->getAttribute('Destination');
                 if (!empty($destination)) {
                     if (strpos($destination, $currentURL) !== 0) {
                         $currentURLrouted = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
                         if (strpos($destination, $currentURLrouted) !== 0) {
                             throw new Exception("The response was received at {$currentURL} instead of {$destination}");
                         }
                     }
                 }
             }
             // Check audience
             $validAudiences = $this->getAudiences();
             if (!empty($validAudiences) && !in_array($spEntityId, $validAudiences)) {
                 throw new Exception("{$spEntityId} is not a valid audience for this Response");
             }
             // Check the issuers
             $issuers = $this->getIssuers();
             foreach ($issuers as $issuer) {
                 if (empty($issuer) || $issuer != $idPEntityId) {
                     throw new Exception("Invalid issuer in the Assertion/Response");
                 }
             }
             // Check the session Expiration
             $sessionExpiration = $this->getSessionNotOnOrAfter();
             if (!empty($sessionExpiration) && $sessionExpiration <= time()) {
                 throw new Exception("The attributes have expired, based on the SessionNotOnOrAfter of the AttributeStatement of this Response");
             }
             // Check the SubjectConfirmation, at least one SubjectConfirmation must be valid
             $anySubjectConfirmation = false;
             $subjectConfirmationNodes = $this->_queryAssertion('/saml:Subject/saml:SubjectConfirmation');
             foreach ($subjectConfirmationNodes as $scn) {
                 if ($scn->hasAttribute('Method') && $scn->getAttribute('Method') != OneLogin_Saml2_Constants::CM_BEARER) {
                     continue;
                 }
                 $subjectConfirmationDataNodes = $scn->getElementsByTagName('SubjectConfirmationData');
                 if ($subjectConfirmationDataNodes->length == 0) {
                     continue;
                 } else {
                     $scnData = $subjectConfirmationDataNodes->item(0);
                     if ($scnData->hasAttribute('InResponseTo')) {
                         $inResponseTo = $scnData->getAttribute('InResponseTo');
                         if ($responseInResponseTo != $inResponseTo) {
                             continue;
                         }
                     }
                     if ($scnData->hasAttribute('Recipient')) {
                         $recipient = $scnData->getAttribute('Recipient');
                         if (!empty($recipient) && strpos($recipient, $currentURL) === false) {
                             continue;
                         }
                     }
                     if ($scnData->hasAttribute('NotOnOrAfter')) {
                         $noa = OneLogin_Saml2_Utils::parseSAML2Time($scnData->getAttribute('NotOnOrAfter'));
                         if ($noa <= time()) {
                             continue;
                         }
                     }
                     if ($scnData->hasAttribute('NotBefore')) {
                         $nb = OneLogin_Saml2_Utils::parseSAML2Time($scnData->getAttribute('NotBefore'));
                         if ($nb > time()) {
                             continue;
                         }
                     }
                     $anySubjectConfirmation = true;
                     break;
                 }
             }
             if (!$anySubjectConfirmation) {
                 throw new Exception("A valid SubjectConfirmation was not found on this Response");
             }
             if ($security['wantAssertionsSigned'] && !in_array('saml:Assertion', $signedElements)) {
                 throw new Exception("The Assertion of the Response is not signed and the SP requires it");
             }
             if ($security['wantMessagesSigned'] && !in_array('samlp:Response', $signedElements)) {
                 throw new Exception("The Message of the Response is not signed and the SP requires it");
             }
         }
         if (!empty($signedElements)) {
             $cert = $idpData['x509cert'];
             $fingerprint = $idpData['certFingerprint'];
             // Only validates the first sign found
             if (in_array('samlp:Response', $signedElements)) {
                 $documentToValidate = $this->document;
             } else {
                 if ($this->encrypted) {
                     $documentToValidate = $this->decryptedDocument;
                 } else {
                     $documentToValidate = $this->document;
                 }
             }
             if (!OneLogin_Saml2_Utils::validateSign($documentToValidate, $cert, $fingerprint)) {
                 throw new Exception('Signature validation failed. SAML Response rejected');
             }
         }
         return true;
     } catch (Exception $e) {
         $debug = $this->_settings->isDebugActive();
         if ($debug) {
             echo $e->getMessage();
         }
         return false;
     }
 }
Example #10
0
<?php

/**
 * SAMPLE Code to demonstrate how to initiate a SAML Authorization request
 *
 * When the user visits this URL, the browser will be redirected to the SSO
 * IdP with an authorization request. If successful, it will then be
 * redirected to the consume URL (specified in settings) with the auth
 * details.
 */
session_start();
require_once '../_toolkit_loader.php';
$auth = new OneLogin_Saml2_Auth();
if (!isset($_SESSION['samlUserdata'])) {
    $auth->login();
} else {
    $indexUrl = str_replace('/sso.php', '/index.php', OneLogin_Saml2_Utils::getSelfURLNoQuery());
    OneLogin_Saml2_Utils::redirect($indexUrl);
}
Example #11
0
 /**
  * Determines if the SAML Response is valid using the certificate.
  *
  * @param string|null $requestId The ID of the AuthNRequest sent by this SP to the IdP
  *
  * @return bool Validate the document
  *
  * @throws Exception
  */
 public function isValid($requestId = null)
 {
     $this->_error = null;
     try {
         // Check SAML version
         if ($this->document->documentElement->getAttribute('Version') != '2.0') {
             throw new Exception('Unsupported SAML version');
         }
         if (!$this->document->documentElement->hasAttribute('ID')) {
             throw new Exception('Missing ID attribute on SAML Response');
         }
         $status = $this->checkStatus();
         $singleAssertion = $this->validateNumAssertions();
         if (!$singleAssertion) {
             throw new Exception('SAML Response must contain 1 assertion');
         }
         $idpData = $this->_settings->getIdPData();
         $idPEntityId = $idpData['entityId'];
         $spData = $this->_settings->getSPData();
         $spEntityId = $spData['entityId'];
         $signedElements = $this->processSignedElements();
         $responseTag = '{' . OneLogin_Saml2_Constants::NS_SAMLP . '}Response';
         $assertionTag = '{' . OneLogin_Saml2_Constants::NS_SAML . '}Assertion';
         $hasSignedResponse = in_array($responseTag, $signedElements);
         $hasSignedAssertion = in_array($assertionTag, $signedElements);
         if ($this->_settings->isStrict()) {
             $security = $this->_settings->getSecurityData();
             if ($security['wantXMLValidation']) {
                 $errorXmlMsg = "Invalid SAML Response. Not match the saml-schema-protocol-2.0.xsd";
                 $res = OneLogin_Saml2_Utils::validateXML($this->document, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
                 if (!$res instanceof DOMDocument) {
                     throw new Exception($errorXmlMsg);
                 }
                 # If encrypted, check also the decrypted document
                 if ($this->encrypted) {
                     $res = OneLogin_Saml2_Utils::validateXML($this->decryptedDocument, 'saml-schema-protocol-2.0.xsd', $this->_settings->isDebugActive());
                     if (!$res instanceof DOMDocument) {
                         throw new Exception($errorXmlMsg);
                     }
                 }
             }
             $currentURL = OneLogin_Saml2_Utils::getSelfRoutedURLNoQuery();
             if ($this->document->documentElement->hasAttribute('InResponseTo')) {
                 $responseInResponseTo = $this->document->documentElement->getAttribute('InResponseTo');
             }
             // Check if the InResponseTo of the Response matchs the ID of the AuthNRequest (requestId) if provided
             if (isset($requestId) && isset($responseInResponseTo)) {
                 if ($requestId != $responseInResponseTo) {
                     throw new Exception("The InResponseTo of the Response: {$responseInResponseTo}, does not match the ID of the AuthNRequest sent by the SP: {$requestId}");
                 }
             }
             if (!$this->encrypted && $security['wantAssertionsEncrypted']) {
                 throw new Exception("The assertion of the Response is not encrypted and the SP requires it");
             }
             if ($security['wantNameIdEncrypted']) {
                 $encryptedIdNodes = $this->_queryAssertion('/saml:Subject/saml:EncryptedID/xenc:EncryptedData');
                 if ($encryptedIdNodes->length != 1) {
                     throw new Exception("The NameID of the Response is not encrypted and the SP requires it");
                 }
             }
             // Validate Conditions element exists
             if (!$this->checkOneCondition()) {
                 throw new Exception("The Assertion must include a Conditions element");
             }
             // Validate Asserion timestamps
             $validTimestamps = $this->validateTimestamps();
             if (!$validTimestamps) {
                 throw new Exception('Timing issues (please check your clock settings)');
             }
             // Validate AuthnStatement element exists and is unique
             if (!$this->checkOneAuthnStatement()) {
                 throw new Exception("The Assertion must include an AuthnStatement element");
             }
             // EncryptedAttributes are not supported
             $encryptedAttributeNodes = $this->_queryAssertion('/saml:AttributeStatement/saml:EncryptedAttribute');
             if ($encryptedAttributeNodes->length > 0) {
                 throw new Exception("There is an EncryptedAttribute in the Response and this SP not support them");
             }
             // Check destination
             if ($this->document->documentElement->hasAttribute('Destination')) {
                 $destination = trim($this->document->documentElement->getAttribute('Destination'));
                 if (empty($destination)) {
                     throw new Exception("The response has an empty Destination value");
                 } else {
                     if (strpos($destination, $currentURL) !== 0) {
                         $currentURLNoRouted = OneLogin_Saml2_Utils::getSelfURLNoQuery();
                         if (strpos($destination, $currentURLNoRouted) !== 0) {
                             throw new Exception("The response was received at {$currentURL} instead of {$destination}");
                         }
                     }
                 }
             }
             // Check audience
             $validAudiences = $this->getAudiences();
             if (!empty($validAudiences) && !in_array($spEntityId, $validAudiences)) {
                 throw new Exception("{$spEntityId} is not a valid audience for this Response");
             }
             // Check the issuers
             $issuers = $this->getIssuers();
             foreach ($issuers as $issuer) {
                 $trimmedIssuer = trim($issuer);
                 if (empty($trimmedIssuer) || $trimmedIssuer !== $idPEntityId) {
                     throw new Exception("Invalid issuer in the Assertion/Response");
                 }
             }
             // Check the session Expiration
             $sessionExpiration = $this->getSessionNotOnOrAfter();
             if (!empty($sessionExpiration) && $sessionExpiration <= time()) {
                 throw new Exception("The attributes have expired, based on the SessionNotOnOrAfter of the AttributeStatement of this Response");
             }
             // Check the SubjectConfirmation, at least one SubjectConfirmation must be valid
             $anySubjectConfirmation = false;
             $subjectConfirmationNodes = $this->_queryAssertion('/saml:Subject/saml:SubjectConfirmation');
             foreach ($subjectConfirmationNodes as $scn) {
                 if ($scn->hasAttribute('Method') && $scn->getAttribute('Method') != OneLogin_Saml2_Constants::CM_BEARER) {
                     continue;
                 }
                 $subjectConfirmationDataNodes = $scn->getElementsByTagName('SubjectConfirmationData');
                 if ($subjectConfirmationDataNodes->length == 0) {
                     continue;
                 } else {
                     $scnData = $subjectConfirmationDataNodes->item(0);
                     if ($scnData->hasAttribute('InResponseTo')) {
                         $inResponseTo = $scnData->getAttribute('InResponseTo');
                         if ($responseInResponseTo != $inResponseTo) {
                             continue;
                         }
                     }
                     if ($scnData->hasAttribute('Recipient')) {
                         $recipient = $scnData->getAttribute('Recipient');
                         if (!empty($recipient) && strpos($recipient, $currentURL) === false) {
                             continue;
                         }
                     }
                     if ($scnData->hasAttribute('NotOnOrAfter')) {
                         $noa = OneLogin_Saml2_Utils::parseSAML2Time($scnData->getAttribute('NotOnOrAfter'));
                         if ($noa <= time()) {
                             continue;
                         }
                     }
                     if ($scnData->hasAttribute('NotBefore')) {
                         $nb = OneLogin_Saml2_Utils::parseSAML2Time($scnData->getAttribute('NotBefore'));
                         if ($nb > time()) {
                             continue;
                         }
                     }
                     $anySubjectConfirmation = true;
                     break;
                 }
             }
             if (!$anySubjectConfirmation) {
                 throw new Exception("A valid SubjectConfirmation was not found on this Response");
             }
             if ($security['wantAssertionsSigned'] && !$hasSignedAssertion) {
                 throw new Exception("The Assertion of the Response is not signed and the SP requires it");
             }
             if ($security['wantMessagesSigned'] && !$hasSignedResponse) {
                 throw new Exception("The Message of the Response is not signed and the SP requires it");
             }
         }
         // Detect case not supported
         if ($this->encrypted) {
             $encryptedIDNodes = OneLogin_Saml2_Utils::query($this->decryptedDocument, '/samlp:Response/saml:Assertion/saml:Subject/saml:EncryptedID');
             if ($encryptedIDNodes->length > 0) {
                 throw new Exception('Unsigned SAML Response that contains a signed and encrypted Assertion with encrypted nameId is not supported.');
             }
         }
         if (empty($signedElements) || !$hasSignedResponse && !$hasSignedAssertion) {
             throw new Exception('No Signature found. SAML Response rejected');
         } else {
             $cert = $idpData['x509cert'];
             $fingerprint = $idpData['certFingerprint'];
             $fingerprintalg = $idpData['certFingerprintAlgorithm'];
             # If find a Signature on the Response, validates it checking the original response
             if ($hasSignedResponse && !OneLogin_Saml2_Utils::validateSign($this->document, $cert, $fingerprint, $fingerprintalg, OneLogin_Saml2_Utils::RESPONSE_SIGNATURE_XPATH)) {
                 throw new Exception("Signature validation failed. SAML Response rejected");
             }
             # If find a Signature on the Assertion (decrypted assertion if was encrypted)
             $documentToCheckAssertion = $this->encrypted ? $this->decryptedDocument : $this->document;
             if ($hasSignedAssertion && !OneLogin_Saml2_Utils::validateSign($documentToCheckAssertion, $cert, $fingerprint, $fingerprintalg, OneLogin_Saml2_Utils::ASSERTION_SIGNATURE_XPATH)) {
                 throw new Exception("Signature validation failed. SAML Response rejected");
             }
         }
         return true;
     } catch (Exception $e) {
         $this->_error = $e->getMessage();
         $debug = $this->_settings->isDebugActive();
         if ($debug) {
             echo $this->_error;
         }
         return false;
     }
 }
Example #12
0
 /**
  * Initiates the SLO process.
  *
  * @param string $returnTo The target URL the user should be returned to after logout.
  */
 public function logout($returnTo = null)
 {
     $sloUrl = $this->getSLOurl();
     if (!isset($sloUrl)) {
         throw new OneLogin_Saml2_Error('The IdP does not support Single Log Out', OneLogin_Saml2_Error::SAML_SINGLE_LOGOUT_NOT_SUPPORTED);
     }
     $logoutRequest = new OneLogin_Saml2_LogoutRequest($this->_settings);
     $samlRequest = $logoutRequest->getRequest();
     $parameters = array('SAMLRequest' => $samlRequest);
     if (!empty($returnTo)) {
         $parameters['RelayState'] = $returnTo;
     } else {
         $parameters['RelayState'] = OneLogin_Saml2_Utils::getSelfURLNoQuery();
     }
     $security = $this->_settings->getSecurityData();
     if (isset($security['logoutRequestSigned']) && $security['logoutRequestSigned']) {
         $signature = $this->buildRequestSignature($samlRequest, $parameters['RelayState']);
         $parameters['SigAlg'] = XMLSecurityKey::RSA_SHA1;
         $parameters['Signature'] = $signature;
     }
     $this->redirectTo($sloUrl, $parameters);
 }
Example #13
0
 /**
  * Checks if the Logout Request recieved is valid.
  *
  * @param OneLogin_Saml2_Settings $settings Settings
  * @param string|DOMDocument      $request  Logout Request decoded
  *
  * @return boolean If the Logout Request is or not valid
  */
 public static function isValid(OneLogin_Saml2_Settings $settings, $request, $debug = false)
 {
     try {
         if ($request instanceof DOMDocument) {
             $dom = $request;
         } else {
             $dom = new DOMDocument();
             $dom = OneLogin_Saml2_Utils::loadXML($dom, $request);
         }
         $idpData = $settings->getIdPData();
         $idPEntityId = $idpData['entityId'];
         if ($settings->isStrict()) {
             $res = OneLogin_Saml2_Utils::validateXML($dom, 'saml-schema-protocol-2.0.xsd', $debug);
             if (!$res instanceof DOMDocument) {
                 throw new Exception("Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd");
             }
             $security = $settings->getSecurityData();
             $currentURL = OneLogin_Saml2_Utils::getSelfURLNoQuery();
             // Check NotOnOrAfter
             if ($dom->documentElement->hasAttribute('NotOnOrAfter')) {
                 $na = OneLogin_Saml2_Utils::parseSAML2Time($dom->documentElement->getAttribute('NotOnOrAfter'));
                 if ($na <= time()) {
                     throw new Exception('Timing issues (please check your clock settings)');
                 }
             }
             // Check destination
             if ($dom->documentElement->hasAttribute('Destination')) {
                 $destination = $dom->documentElement->getAttribute('Destination');
                 if (!empty($destination)) {
                     if (strpos($destination, $currentURL) === false) {
                         throw new Exception("The LogoutRequest was received at {$currentURL} instead of {$destination}");
                     }
                 }
             }
             $nameId = self::getNameId($dom);
             // Check issuer
             $issuer = self::getIssuer($dom);
             if (empty($issuer) || $issuer != $idPEntityId) {
                 throw new Exception("Invalid issuer in the Logout Request");
             }
             if ($security['wantMessagesSigned']) {
                 if (!isset($_GET['Signature'])) {
                     throw new Exception("The Message of the Logout Request is not signed and the SP require it");
                 }
             }
         }
         if (isset($_GET['Signature'])) {
             if (!isset($_GET['SigAlg'])) {
                 $signAlg = XMLSecurityKey::RSA_SHA1;
             } else {
                 $signAlg = $_GET['SigAlg'];
             }
             if ($signAlg != XMLSecurityKey::RSA_SHA1) {
                 throw new Exception('Invalid signAlg in the recieved Logout Request');
             }
             $signedQuery = 'SAMLRequest=' . urlencode($_GET['SAMLRequest']);
             if (isset($_GET['RelayState'])) {
                 $signedQuery .= '&RelayState=' . urlencode($_GET['RelayState']);
             }
             $signedQuery .= '&SigAlg=' . urlencode($signAlg);
             if (!isset($idpData['x509cert']) || empty($idpData['x509cert'])) {
                 throw new Exception('In order to validate the sign on the Logout Request, the x509cert of the IdP is required');
             }
             $cert = $idpData['x509cert'];
             $objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
             $objKey->loadKey($cert, false, true);
             if (!$objKey->verifySignature($signedQuery, base64_decode($_GET['Signature']))) {
                 throw new Exception('Signature validation failed. Logout Request rejected');
             }
         }
         return true;
     } catch (Exception $e) {
         $debug = $settings->isDebugActive();
         if ($debug) {
             echo $e->getMessage();
         }
         return false;
     }
 }