vendor/onelogin/php-saml/src/Saml2/Auth.php line 177

Open in your IDE?
  1. <?php
  2. /**
  3.  * This file is part of php-saml.
  4.  *
  5.  * (c) OneLogin Inc
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  *
  10.  * @package OneLogin
  11.  * @author  OneLogin Inc <saml-info@onelogin.com>
  12.  * @license MIT https://github.com/onelogin/php-saml/blob/master/LICENSE
  13.  * @link    https://github.com/onelogin/php-saml
  14.  */
  15. namespace OneLogin\Saml2;
  16. use RobRichards\XMLSecLibs\XMLSecurityKey;
  17. use Exception;
  18. /**
  19.  * Main class of OneLogin's PHP Toolkit
  20.  */
  21. class Auth
  22. {
  23.     /**
  24.      * Settings data.
  25.      *
  26.      * @var Settings
  27.      */
  28.     private $_settings;
  29.     /**
  30.      * User attributes data.
  31.      *
  32.      * @var array
  33.      */
  34.     private $_attributes = array();
  35.     /**
  36.      * User attributes data with FriendlyName index.
  37.      *
  38.      * @var array
  39.      */
  40.     private $_attributesWithFriendlyName = array();
  41.     /**
  42.      * NameID
  43.      *
  44.      * @var string
  45.      */
  46.     private $_nameid;
  47.     /**
  48.      * NameID Format
  49.      *
  50.      * @var string
  51.      */
  52.     private $_nameidFormat;
  53.     /**
  54.      * NameID NameQualifier
  55.      *
  56.      * @var string
  57.      */
  58.     private $_nameidNameQualifier;
  59.     /**
  60.      * NameID SP NameQualifier
  61.      *
  62.      * @var string
  63.      */
  64.     private $_nameidSPNameQualifier;
  65.     /**
  66.      * If user is authenticated.
  67.      *
  68.      * @var bool
  69.      */
  70.     private $_authenticated false;
  71.     /**
  72.      * SessionIndex. When the user is logged, this stored it
  73.      * from the AuthnStatement of the SAML Response
  74.      *
  75.      * @var string
  76.      */
  77.     private $_sessionIndex;
  78.     /**
  79.      * SessionNotOnOrAfter. When the user is logged, this stored it
  80.      * from the AuthnStatement of the SAML Response
  81.      *
  82.      * @var int|null
  83.      */
  84.     private $_sessionExpiration;
  85.     /**
  86.      * The ID of the last message processed
  87.      *
  88.      * @var string
  89.      */
  90.     private $_lastMessageId;
  91.     /**
  92.      * The ID of the last assertion processed
  93.      *
  94.      * @var string
  95.      */
  96.     private $_lastAssertionId;
  97.     /**
  98.      * The NotOnOrAfter value of the valid SubjectConfirmationData
  99.      * node (if any) of the last assertion processed
  100.      *
  101.      * @var int
  102.      */
  103.     private $_lastAssertionNotOnOrAfter;
  104.     /**
  105.      * If any error.
  106.      *
  107.      * @var array
  108.      */
  109.     private $_errors = array();
  110.     /**
  111.      * Last error object.
  112.      *
  113.      * @var Error|null
  114.      */
  115.     private $_lastErrorException;
  116.     /**
  117.      * Last error.
  118.      *
  119.      * @var string|null
  120.      */
  121.     private $_lastError;
  122.     /**
  123.      * Last AuthNRequest ID or LogoutRequest ID generated by this Service Provider
  124.      *
  125.      * @var string
  126.      */
  127.     private $_lastRequestID;
  128.     /**
  129.      * The most recently-constructed/processed XML SAML request
  130.      * (AuthNRequest, LogoutRequest)
  131.      *
  132.      * @var string
  133.      */
  134.     private $_lastRequest;
  135.     /**
  136.      * The most recently-constructed/processed XML SAML response
  137.      * (SAMLResponse, LogoutResponse). If the SAMLResponse was
  138.      * encrypted, by default tries to return the decrypted XML
  139.      *
  140.      * @var string|\DomDocument|null
  141.      */
  142.     private $_lastResponse;
  143.     /**
  144.      * Initializes the SP SAML instance.
  145.      *
  146.      * @param array|null $settings Setting data
  147.      *
  148.      * @throws Exception
  149.      * @throws Error
  150.      */
  151.     public function __construct(array $settings null)
  152.     {
  153.         $this->_settings = new Settings($settings);
  154.     }
  155.     /**
  156.      * Returns the settings info
  157.      *
  158.      * @return Settings The settings data.
  159.      */
  160.     public function getSettings()
  161.     {
  162.         return $this->_settings;
  163.     }
  164.     /**
  165.      * Set the strict mode active/disable
  166.      *
  167.      * @param bool $value Strict parameter
  168.      *
  169.      * @throws Error
  170.      */
  171.     public function setStrict($value)
  172.     {
  173.         if (!is_bool($value)) {
  174.             throw new Error(
  175.                 'Invalid value passed to setStrict()',
  176.                 Error::SETTINGS_INVALID_SYNTAX
  177.             );
  178.         }
  179.         $this->_settings->setStrict($value);
  180.     }
  181.     /**
  182.      * Set schemas path
  183.      *
  184.      * @param string $path
  185.      * @return $this
  186.      */
  187.     public function setSchemasPath($path)
  188.     {
  189.         $this->_paths['schemas'] = $path;
  190.     }
  191.     /**
  192.      * Process the SAML Response sent by the IdP.
  193.      *
  194.      * @param string|null $requestId The ID of the AuthNRequest sent by this SP to the IdP
  195.      *
  196.      * @throws Error
  197.      * @throws ValidationError
  198.      */
  199.     public function processResponse($requestId null)
  200.     {
  201.         $this->_errors = array();
  202.         $this->_lastError $this->_lastErrorException null;
  203.         if (isset($_POST['SAMLResponse'])) {
  204.             // AuthnResponse -- HTTP_POST Binding
  205.             $response = new Response($this->_settings$_POST['SAMLResponse']);
  206.             $this->_lastResponse $response->getXMLDocument();
  207.             if ($response->isValid($requestId)) {
  208.                 $this->_attributes $response->getAttributes();
  209.                 $this->_attributesWithFriendlyName $response->getAttributesWithFriendlyName();
  210.                 $this->_nameid $response->getNameId();
  211.                 $this->_nameidFormat $response->getNameIdFormat();
  212.                 $this->_nameidNameQualifier $response->getNameIdNameQualifier();
  213.                 $this->_nameidSPNameQualifier $response->getNameIdSPNameQualifier();
  214.                 $this->_authenticated true;
  215.                 $this->_sessionIndex $response->getSessionIndex();
  216.                 $this->_sessionExpiration $response->getSessionNotOnOrAfter();
  217.                 $this->_lastMessageId $response->getId();
  218.                 $this->_lastAssertionId $response->getAssertionId();
  219.                 $this->_lastAssertionNotOnOrAfter $response->getAssertionNotOnOrAfter();
  220.             } else {
  221.                 $this->_errors[] = 'invalid_response';
  222.                 $this->_lastErrorException $response->getErrorException();
  223.                 $this->_lastError $response->getError();
  224.             }
  225.         } else {
  226.             $this->_errors[] = 'invalid_binding';
  227.             throw new Error(
  228.                 'SAML Response not found, Only supported HTTP_POST Binding',
  229.                 Error::SAML_RESPONSE_NOT_FOUND
  230.             );
  231.         }
  232.     }
  233.     /**
  234.      * Process the SAML Logout Response / Logout Request sent by the IdP.
  235.      *
  236.      * @param bool        $keepLocalSession             When false will destroy the local session, otherwise will keep it
  237.      * @param string|null $requestId                    The ID of the LogoutRequest sent by this SP to the IdP
  238.      * @param bool        $retrieveParametersFromServer True if we want to use parameters from $_SERVER to validate the signature
  239.      * @param callable    $cbDeleteSession              Callback to be executed to delete session
  240.      * @param bool        $stay                         True if we want to stay (returns the url string) False to redirect
  241.      *
  242.      * @return string|null
  243.      *
  244.      * @throws Error
  245.      */
  246.     public function processSLO($keepLocalSession false$requestId null$retrieveParametersFromServer false$cbDeleteSession null$stay false)
  247.     {
  248.         $this->_errors = array();
  249.         $this->_lastError $this->_lastErrorException null;
  250.         if (isset($_GET['SAMLResponse'])) {
  251.             $logoutResponse = new LogoutResponse($this->_settings$_GET['SAMLResponse']);
  252.             $this->_lastResponse $logoutResponse->getXML();
  253.             if (!$logoutResponse->isValid($requestId$retrieveParametersFromServer)) {
  254.                 $this->_errors[] = 'invalid_logout_response';
  255.                 $this->_lastErrorException $logoutResponse->getErrorException();
  256.                 $this->_lastError $logoutResponse->getError();
  257.             } else if ($logoutResponse->getStatus() !== Constants::STATUS_SUCCESS) {
  258.                 $this->_errors[] = 'logout_not_success';
  259.             } else {
  260.                 $this->_lastMessageId $logoutResponse->id;
  261.                 if (!$keepLocalSession) {
  262.                     if ($cbDeleteSession === null) {
  263.                         Utils::deleteLocalSession();
  264.                     } else {
  265.                         call_user_func($cbDeleteSession);
  266.                     }
  267.                 }
  268.             }
  269.         } else if (isset($_GET['SAMLRequest'])) {
  270.             $logoutRequest = new LogoutRequest($this->_settings$_GET['SAMLRequest']);
  271.             $this->_lastRequest $logoutRequest->getXML();
  272.             if (!$logoutRequest->isValid($retrieveParametersFromServer)) {
  273.                 $this->_errors[] = 'invalid_logout_request';
  274.                 $this->_lastErrorException $logoutRequest->getErrorException();
  275.                 $this->_lastError $logoutRequest->getError();
  276.             } else {
  277.                 if (!$keepLocalSession) {
  278.                     if ($cbDeleteSession === null) {
  279.                         Utils::deleteLocalSession();
  280.                     } else {
  281.                         call_user_func($cbDeleteSession);
  282.                     }
  283.                 }
  284.                 $inResponseTo $logoutRequest->id;
  285.                 $this->_lastMessageId $logoutRequest->id;
  286.                 $responseBuilder = new LogoutResponse($this->_settings);
  287.                 $responseBuilder->build($inResponseTo);
  288.                 $this->_lastResponse $responseBuilder->getXML();
  289.                 $logoutResponse $responseBuilder->getResponse();
  290.                 $parameters = array('SAMLResponse' => $logoutResponse);
  291.                 if (isset($_GET['RelayState'])) {
  292.                     $parameters['RelayState'] = $_GET['RelayState'];
  293.                 }
  294.                 $security $this->_settings->getSecurityData();
  295.                 if (isset($security['logoutResponseSigned']) && $security['logoutResponseSigned']) {
  296.                     $signature $this->buildResponseSignature($logoutResponse, isset($parameters['RelayState'])? $parameters['RelayState']: null$security['signatureAlgorithm']);
  297.                     $parameters['SigAlg'] = $security['signatureAlgorithm'];
  298.                     $parameters['Signature'] = $signature;
  299.                 }
  300.                 return $this->redirectTo($this->getSLOResponseUrl(), $parameters$stay);
  301.             }
  302.         } else {
  303.             $this->_errors[] = 'invalid_binding';
  304.             throw new Error(
  305.                 'SAML LogoutRequest/LogoutResponse not found. Only supported HTTP_REDIRECT Binding',
  306.                 Error::SAML_LOGOUTMESSAGE_NOT_FOUND
  307.             );
  308.         }
  309.     }
  310.     /**
  311.      * Redirects the user to the url past by parameter
  312.      * or to the url that we defined in our SSO Request.
  313.      *
  314.      * @param string $url        The target URL to redirect the user.
  315.      * @param array  $parameters Extra parameters to be passed as part of the url
  316.      * @param bool   $stay       True if we want to stay (returns the url string) False to redirect
  317.      *
  318.      * @return string|null
  319.      */
  320.     public function redirectTo($url '', array $parameters = array(), $stay false)
  321.     {
  322.         assert(is_string($url));
  323.         if (empty($url) && isset($_REQUEST['RelayState'])) {
  324.             $url $_REQUEST['RelayState'];
  325.         }
  326.         return Utils::redirect($url$parameters$stay);
  327.     }
  328.     /**
  329.      * Checks if the user is authenticated or not.
  330.      *
  331.      * @return bool  True if the user is authenticated
  332.      */
  333.     public function isAuthenticated()
  334.     {
  335.         return $this->_authenticated;
  336.     }
  337.     /**
  338.      * Returns the set of SAML attributes.
  339.      *
  340.      * @return array  Attributes of the user.
  341.      */
  342.     public function getAttributes()
  343.     {
  344.         return $this->_attributes;
  345.     }
  346.     /**
  347.      * Returns the set of SAML attributes indexed by FriendlyName
  348.      *
  349.      * @return array  Attributes of the user.
  350.      */
  351.     public function getAttributesWithFriendlyName()
  352.     {
  353.         return $this->_attributesWithFriendlyName;
  354.     }
  355.     /**
  356.      * Returns the nameID
  357.      *
  358.      * @return string  The nameID of the assertion
  359.      */
  360.     public function getNameId()
  361.     {
  362.         return $this->_nameid;
  363.     }
  364.     /**
  365.      * Returns the nameID Format
  366.      *
  367.      * @return string  The nameID Format of the assertion
  368.      */
  369.     public function getNameIdFormat()
  370.     {
  371.         return $this->_nameidFormat;
  372.     }
  373.     /**
  374.      * Returns the nameID NameQualifier
  375.      *
  376.      * @return string  The nameID NameQualifier of the assertion
  377.      */
  378.     public function getNameIdNameQualifier()
  379.     {
  380.         return $this->_nameidNameQualifier;
  381.     }
  382.     /**
  383.      * Returns the nameID SP NameQualifier
  384.      *
  385.      * @return string  The nameID SP NameQualifier of the assertion
  386.      */
  387.     public function getNameIdSPNameQualifier()
  388.     {
  389.         return $this->_nameidSPNameQualifier;
  390.     }
  391.     /**
  392.      * Returns the SessionIndex
  393.      *
  394.      * @return string|null  The SessionIndex of the assertion
  395.      */
  396.     public function getSessionIndex()
  397.     {
  398.         return $this->_sessionIndex;
  399.     }
  400.     /**
  401.      * Returns the SessionNotOnOrAfter
  402.      *
  403.      * @return int|null  The SessionNotOnOrAfter of the assertion
  404.      */
  405.     public function getSessionExpiration()
  406.     {
  407.         return $this->_sessionExpiration;
  408.     }
  409.     /**
  410.      * Returns if there were any error
  411.      *
  412.      * @return array  Errors
  413.      */
  414.     public function getErrors()
  415.     {
  416.         return $this->_errors;
  417.     }
  418.     /**
  419.      * Returns the reason for the last error
  420.      *
  421.      * @return string|null  Error reason
  422.      */
  423.     public function getLastErrorReason()
  424.     {
  425.         return $this->_lastError;
  426.     }
  427.     /**
  428.      * Returns the last error
  429.      *
  430.      * @return Exception|null Error
  431.      */
  432.     public function getLastErrorException()
  433.     {
  434.         return $this->_lastErrorException;
  435.     }
  436.     /**
  437.      * Returns the requested SAML attribute
  438.      *
  439.      * @param string $name The requested attribute of the user.
  440.      *
  441.      * @return array|null Requested SAML attribute ($name).
  442.      */
  443.     public function getAttribute($name)
  444.     {
  445.         assert(is_string($name));
  446.         $value null;
  447.         if (isset($this->_attributes[$name])) {
  448.             return $this->_attributes[$name];
  449.         }
  450.         return $value;
  451.     }
  452.     /**
  453.      * Returns the requested SAML attribute indexed by FriendlyName
  454.      *
  455.      * @param string $friendlyName The requested attribute of the user.
  456.      *
  457.      * @return array|null Requested SAML attribute ($friendlyName).
  458.      */
  459.     public function getAttributeWithFriendlyName($friendlyName)
  460.     {
  461.         assert(is_string($friendlyName));
  462.         $value null;
  463.         if (isset($this->_attributesWithFriendlyName[$friendlyName])) {
  464.             return $this->_attributesWithFriendlyName[$friendlyName];
  465.         }
  466.         return $value;
  467.     }
  468.     /**
  469.      * Initiates the SSO process.
  470.      *
  471.      * @param string|null $returnTo        The target URL the user should be returned to after login.
  472.      * @param array       $parameters      Extra parameters to be added to the GET
  473.      * @param bool        $forceAuthn      When true the AuthNRequest will set the ForceAuthn='true'
  474.      * @param bool        $isPassive       When true the AuthNRequest will set the Ispassive='true'
  475.      * @param bool        $stay            True if we want to stay (returns the url string) False to redirect
  476.      * @param bool        $setNameIdPolicy When true the AuthNRequest will set a nameIdPolicy element
  477.      * @param string      $nameIdValueReq  Indicates to the IdP the subject that should be authenticated
  478.      *
  479.      * @return string|null If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
  480.      *
  481.      * @throws Error
  482.      */
  483.     public function login($returnTo null, array $parameters = array(), $forceAuthn false$isPassive false$stay false$setNameIdPolicy true$nameIdValueReq null)
  484.     {
  485.         $authnRequest $this->buildAuthnRequest($this->_settings$forceAuthn$isPassive$setNameIdPolicy$nameIdValueReq);
  486.         $this->_lastRequest $authnRequest->getXML();
  487.         $this->_lastRequestID $authnRequest->getId();
  488.         $samlRequest $authnRequest->getRequest();
  489.         $parameters['SAMLRequest'] = $samlRequest;
  490.         if (!empty($returnTo)) {
  491.             $parameters['RelayState'] = $returnTo;
  492.         } else {
  493.             $parameters['RelayState'] = Utils::getSelfRoutedURLNoQuery();
  494.         }
  495.         $security $this->_settings->getSecurityData();
  496.         if (isset($security['authnRequestsSigned']) && $security['authnRequestsSigned']) {
  497.             $signature $this->buildRequestSignature($samlRequest$parameters['RelayState'], $security['signatureAlgorithm']);
  498.             $parameters['SigAlg'] = $security['signatureAlgorithm'];
  499.             $parameters['Signature'] = $signature;
  500.         }
  501.         return $this->redirectTo($this->getSSOurl(), $parameters$stay);
  502.     }
  503.     /**
  504.      * Initiates the SLO process.
  505.      *
  506.      * @param string|null $returnTo            The target URL the user should be returned to after logout.
  507.      * @param array       $parameters          Extra parameters to be added to the GET
  508.      * @param string|null $nameId              The NameID that will be set in the LogoutRequest.
  509.      * @param string|null $sessionIndex        The SessionIndex (taken from the SAML Response in the SSO process).
  510.      * @param bool        $stay                True if we want to stay (returns the url string) False to redirect
  511.      * @param string|null $nameIdFormat        The NameID Format will be set in the LogoutRequest.
  512.      * @param string|null $nameIdNameQualifier The NameID NameQualifier will be set in the LogoutRequest.
  513.      *
  514.      * @return string|null If $stay is True, it return a string with the SLO URL + LogoutRequest + parameters
  515.      *
  516.      * @throws Error
  517.      */
  518.     public function logout($returnTo null, array $parameters = array(), $nameId null$sessionIndex null$stay false$nameIdFormat null$nameIdNameQualifier null$nameIdSPNameQualifier null)
  519.     {
  520.         $sloUrl $this->getSLOurl();
  521.         if (empty($sloUrl)) {
  522.             throw new Error(
  523.                 'The IdP does not support Single Log Out',
  524.                 Error::SAML_SINGLE_LOGOUT_NOT_SUPPORTED
  525.             );
  526.         }
  527.         if (empty($nameId) && !empty($this->_nameid)) {
  528.             $nameId $this->_nameid;
  529.         }
  530.         if (empty($nameIdFormat) && !empty($this->_nameidFormat)) {
  531.             $nameIdFormat $this->_nameidFormat;
  532.         }
  533.         $logoutRequest = new LogoutRequest($this->_settingsnull$nameId$sessionIndex$nameIdFormat$nameIdNameQualifier$nameIdSPNameQualifier);
  534.         $this->_lastRequest $logoutRequest->getXML();
  535.         $this->_lastRequestID $logoutRequest->id;
  536.         $samlRequest $logoutRequest->getRequest();
  537.         $parameters['SAMLRequest'] = $samlRequest;
  538.         if (!empty($returnTo)) {
  539.             $parameters['RelayState'] = $returnTo;
  540.         } else {
  541.             $parameters['RelayState'] = Utils::getSelfRoutedURLNoQuery();
  542.         }
  543.         $security $this->_settings->getSecurityData();
  544.         if (isset($security['logoutRequestSigned']) && $security['logoutRequestSigned']) {
  545.             $signature $this->buildRequestSignature($samlRequest$parameters['RelayState'], $security['signatureAlgorithm']);
  546.             $parameters['SigAlg'] = $security['signatureAlgorithm'];
  547.             $parameters['Signature'] = $signature;
  548.         }
  549.         return $this->redirectTo($sloUrl$parameters$stay);
  550.     }
  551.    /**
  552.      * Gets the IdP SSO url.
  553.      *
  554.      * @return string The url of the IdP Single Sign On Service
  555.      */
  556.     public function getSSOurl()
  557.     {
  558.         return $this->_settings->getIdPSSOUrl();
  559.     }
  560.     /**
  561.      * Gets the IdP SLO url.
  562.      *
  563.      * @return string|null The url of the IdP Single Logout Service
  564.      */
  565.     public function getSLOurl()
  566.     {
  567.         return $this->_settings->getIdPSLOUrl();
  568.     }
  569.     /**
  570.      * Gets the IdP SLO response url.
  571.      *
  572.      * @return string|null The response url of the IdP Single Logout Service
  573.      */
  574.     public function getSLOResponseUrl()
  575.     {
  576.         return $this->_settings->getIdPSLOResponseUrl();
  577.     }
  578.     /**
  579.      * Gets the ID of the last AuthNRequest or LogoutRequest generated by the Service Provider.
  580.      *
  581.      * @return string The ID of the Request SAML message.
  582.      */
  583.     public function getLastRequestID()
  584.     {
  585.         return $this->_lastRequestID;
  586.     }
  587.     /**
  588.      * Creates an AuthnRequest
  589.      *
  590.      * @param Settings $settings        Setting data
  591.      * @param bool     $forceAuthn      When true the AuthNRequest will set the ForceAuthn='true'
  592.      * @param bool     $isPassive       When true the AuthNRequest will set the Ispassive='true'
  593.      * @param bool     $setNameIdPolicy When true the AuthNRequest will set a nameIdPolicy element
  594.      * @param string   $nameIdValueReq  Indicates to the IdP the subject that should be authenticated
  595.      *
  596.      * @return AuthnRequest The AuthnRequest object
  597.      */
  598.     public function buildAuthnRequest($settings$forceAuthn$isPassive$setNameIdPolicy$nameIdValueReq null)
  599.     {
  600.         return new AuthnRequest($settings$forceAuthn$isPassive$setNameIdPolicy$nameIdValueReq);
  601.     }
  602.     /**
  603.      * Generates the Signature for a SAML Request
  604.      *
  605.      * @param string $samlRequest   The SAML Request
  606.      * @param string $relayState    The RelayState
  607.      * @param string $signAlgorithm Signature algorithm method
  608.      *
  609.      * @return string A base64 encoded signature
  610.      *
  611.      * @throws Exception
  612.      * @throws Error
  613.      */
  614.     public function buildRequestSignature($samlRequest$relayState$signAlgorithm XMLSecurityKey::RSA_SHA256)
  615.     {
  616.         return $this->buildMessageSignature($samlRequest$relayState$signAlgorithm"SAMLRequest");
  617.     }
  618.     /**
  619.      * Generates the Signature for a SAML Response
  620.      *
  621.      * @param string $samlResponse  The SAML Response
  622.      * @param string $relayState    The RelayState
  623.      * @param string $signAlgorithm Signature algorithm method
  624.      *
  625.      * @return string A base64 encoded signature
  626.      *
  627.      * @throws Exception
  628.      * @throws Error
  629.      */
  630.     public function buildResponseSignature($samlResponse$relayState$signAlgorithm XMLSecurityKey::RSA_SHA256)
  631.     {
  632.         return $this->buildMessageSignature($samlResponse$relayState$signAlgorithm"SAMLResponse");
  633.     }
  634.     /**
  635.      * Generates the Signature for a SAML Message
  636.      *
  637.      * @param string $samlMessage   The SAML Message
  638.      * @param string $relayState    The RelayState
  639.      * @param string $signAlgorithm Signature algorithm method
  640.      * @param string $type          "SAMLRequest" or "SAMLResponse"
  641.      *
  642.      * @return string A base64 encoded signature
  643.      *
  644.      * @throws Exception
  645.      * @throws Error
  646.      */
  647.     private function buildMessageSignature($samlMessage$relayState$signAlgorithm XMLSecurityKey::RSA_SHA256$type "SAMLRequest")
  648.     {
  649.         $key $this->_settings->getSPkey();
  650.         if (empty($key)) {
  651.             if ($type == "SAMLRequest") {
  652.                 $errorMsg "Trying to sign the SAML Request but can't load the SP private key";
  653.             } else {
  654.                 $errorMsg "Trying to sign the SAML Response but can't load the SP private key";
  655.             }
  656.             throw new Error($errorMsgError::PRIVATE_KEY_NOT_FOUND);
  657.         }
  658.         $objKey = new XMLSecurityKey($signAlgorithm, array('type' => 'private'));
  659.         $objKey->loadKey($keyfalse);
  660.         $security $this->_settings->getSecurityData();
  661.         if ($security['lowercaseUrlencoding']) {
  662.             $msg $type.'='.rawurlencode($samlMessage);
  663.             if (isset($relayState)) {
  664.                 $msg .= '&RelayState='.rawurlencode($relayState);
  665.             }
  666.             $msg .= '&SigAlg=' rawurlencode($signAlgorithm);
  667.         } else {
  668.             $msg $type.'='.urlencode($samlMessage);
  669.             if (isset($relayState)) {
  670.                 $msg .= '&RelayState='.urlencode($relayState);
  671.             }
  672.             $msg .= '&SigAlg=' urlencode($signAlgorithm);
  673.         }
  674.         $signature $objKey->signData($msg);
  675.         return base64_encode($signature);
  676.     }
  677.     /**
  678.      * @return string The ID of the last message processed
  679.      */
  680.     public function getLastMessageId()
  681.     {
  682.         return $this->_lastMessageId;
  683.     }
  684.     /**
  685.      * @return string The ID of the last assertion processed
  686.      */
  687.     public function getLastAssertionId()
  688.     {
  689.         return $this->_lastAssertionId;
  690.     }
  691.     /**
  692.      * @return int The NotOnOrAfter value of the valid
  693.      *         SubjectConfirmationData node (if any)
  694.      *         of the last assertion processed
  695.      */
  696.     public function getLastAssertionNotOnOrAfter()
  697.     {
  698.         return $this->_lastAssertionNotOnOrAfter;
  699.     }
  700.     /**
  701.      * Returns the most recently-constructed/processed
  702.      * XML SAML request (AuthNRequest, LogoutRequest)
  703.      *
  704.      * @return string|null The Request XML
  705.      */
  706.     public function getLastRequestXML()
  707.     {
  708.         return $this->_lastRequest;
  709.     }
  710.     /**
  711.      * Returns the most recently-constructed/processed
  712.      * XML SAML response (SAMLResponse, LogoutResponse).
  713.      * If the SAMLResponse was encrypted, by default tries
  714.      * to return the decrypted XML.
  715.      *
  716.      * @return string|null The Response XML
  717.      */
  718.     public function getLastResponseXML()
  719.     {
  720.         $response null;
  721.         if (isset($this->_lastResponse)) {
  722.             if (is_string($this->_lastResponse)) {
  723.                 $response $this->_lastResponse;
  724.             } else {
  725.                 $response $this->_lastResponse->saveXML();
  726.             }
  727.         }
  728.         return $response;
  729.     }
  730. }