21 require_once SQ_INCLUDE_PATH.
'/asset.inc';
48 parent::__construct($assetid);
64 return $this->
attr(
'name');
82 if (!parent::_createAdditional($link))
return FALSE;
86 if (empty($link))
return TRUE;
102 $saml_account_manager_data = $GLOBALS[
'SQ_SYSTEM']->am->getLink($this->
id, SQ_LINK_TYPE_2,
'saml_account_manager', TRUE,
'saml2_assertion_consumer_service',
'minor');
103 $saml_account_manager = $GLOBALS[
'SQ_SYSTEM']->am->getAsset($saml_account_manager_data[
'majorid']);
105 if(!$saml_account_manager->isSimplesamlphpInstalled()) {
106 echo(
'simplesamlphp library is not installed');
110 require_once SQ_TOOL_SIMPLESAMLPHP_PATH.
'/lib/_autoload.php';
111 require_once SQ_PACKAGES_PATH.
'/saml/lib/saml_sp.inc';
114 $sourceId = $saml_account_manager->attr(
'auth_source');
116 $config = SimpleSAML_Configuration::getConfig(
'authsources.php');
117 $authConfig = $config->getArray($sourceId, NULL);
120 $spMetadata = $source->getMetadata();
122 $b = SAML2_Binding::getCurrentBinding();
124 catch (Exception $e) {
125 echo($e->getMessage());
129 if ($b instanceof SAML2_HTTPArtifact) {
130 $b->setSPMetadata($spMetadata);
133 $response = $b->receive();
135 if (!($response instanceof SAML2_Response)) {
136 throw new SimpleSAML_Error_BadRequest(
'Invalid message received to AssertionConsumerService endpoint.');
139 $idp = $response->getIssuer();
142 foreach ($response->getAssertions() as $a) {
143 if ($a instanceof SAML2_Assertion) {
145 $idp = $a->getIssuer();
151 throw new Exception(
'Missing <saml:Issuer> in message delivered to AssertionConsumerService.');
155 $session = SimpleSAML_Session::getInstance();
156 $prevAuth = $session->getAuthData($sourceId,
'saml:sp:prevAuth');
157 if ($prevAuth !== NULL && $prevAuth[
'id'] === $response->getId() && $prevAuth[
'issuer'] === $idp) {
165 SimpleSAML_Logger::info(
'Duplicate SAML 2 response detected - ignoring the response and redirecting the user to the correct page.');
166 SimpleSAML_Utilities::redirect($prevAuth[
'redirect']);
169 $stateId = $response->getInResponseTo();
170 if (!empty($stateId)) {
172 $state = SimpleSAML_Auth_State::loadState($stateId,
'saml:sp:sso');
175 assert(
'array_key_exists("saml:sp:AuthId", $state)');
176 if ($state[
'saml:sp:AuthId'] !== $sourceId) {
177 throw new SimpleSAML_Error_Exception(
'The authentication source id in the URL does not match the authentication source which sent the request.');
182 'saml:sp:isUnsolicited' => TRUE,
183 'saml:sp:AuthId' => $sourceId,
184 'saml:sp:RelayState' => $response->getRelayState(),
188 SimpleSAML_Logger::debug(
'Received SAML2 Response from ' . var_export($idp, TRUE) .
'.');
190 $idpMetadata = $source->getIdPmetadata($idp);
193 $assertions = sspmod_saml_Message::processResponse($spMetadata, $idpMetadata, $response);
194 }
catch (sspmod_saml_Error $e) {
198 $_SESSION[
'sq_saml_account_manager_auth_error'] = $e->getStatusMessage();
199 $return = $state[
'SimpleSAML_Auth_Default.Return'];
200 if (is_string($return)) {
202 SimpleSAML_Utilities::redirect($return);
209 $authenticatingAuthority = NULL;
211 $sessionIndex = NULL;
213 $attributes = array();
214 $foundAuthnStatement = FALSE;
215 foreach ($assertions as $assertion) {
218 $store = SimpleSAML_Store::getInstance();
219 if ($store !== FALSE) {
220 $aID = $assertion->getId();
221 if ($store->get(
'saml.AssertionReceived', $aID) !== NULL) {
222 $e =
new SimpleSAML_Error_Exception(
'Received duplicate assertion.');
223 SimpleSAML_Auth_State::throwException($state, $e);
226 $notOnOrAfter = $assertion->getNotOnOrAfter();
227 if ($notOnOrAfter === NULL) {
228 $notOnOrAfter = time() + 24*60*60;
233 $store->set(
'saml.AssertionReceived', $aID, TRUE, $notOnOrAfter);
237 if ($authenticatingAuthority === NULL) {
238 $authenticatingAuthority = $assertion->getAuthenticatingAuthority();
240 if ($nameId === NULL) {
241 $nameId = $assertion->getNameId();
243 if ($sessionIndex === NULL) {
244 $sessionIndex = $assertion->getSessionIndex();
246 if ($expire === NULL) {
247 $expire = $assertion->getSessionNotOnOrAfter();
250 $attributes = array_merge($attributes, $assertion->getAttributes());
252 if ($assertion->getAuthnInstant() !== NULL) {
254 $foundAuthnStatement = TRUE;
258 if (!$foundAuthnStatement) {
259 $e =
new SimpleSAML_Error_Exception(
'No AuthnStatement found in assertion(s).');
260 SimpleSAML_Auth_State::throwException($state, $e);
263 if ($expire === NULL) {
265 $expire = time() + 24*60*60;
269 sspmod_saml_SP_LogoutStore::addSession($sourceId, $nameId, $sessionIndex, $expire);
272 $logoutState = array(
273 'saml:logout:Type' =>
'saml2',
274 'saml:logout:IdP' => $idp,
275 'saml:logout:NameID' => $nameId,
276 'saml:logout:SessionIndex' => $sessionIndex,
278 $state[
'LogoutState'] = $logoutState;
279 $state[
'saml:AuthenticatingAuthority'] = $authenticatingAuthority;
280 $state[
'saml:AuthenticatingAuthority'][] = $idp;
281 $state[
'PersistentAuthData'][] =
'saml:AuthenticatingAuthority';
283 $state[
'saml:sp:IdP'] = $idp;
284 $state[
'PersistentAuthData'][] =
'saml:sp:IdP';
285 $state[
'saml:sp:NameID'] = $nameId;
286 $state[
'PersistentAuthData'][] =
'saml:sp:NameID';
287 $state[
'saml:sp:SessionIndex'] = $sessionIndex;
288 $state[
'PersistentAuthData'][] =
'saml:sp:SessionIndex';
289 $state[
'saml:sp:AuthnContext'] = $assertion->getAuthnContext();
290 $state[
'PersistentAuthData'][] =
'saml:sp:AuthnContext';
293 if (isset($state[
'SimpleSAML_Auth_Default.ReturnURL'])) {
297 $state[
'saml:sp:prevAuth'] = array(
298 'id' => $response->getId(),
300 'redirect' => $state[
'SimpleSAML_Auth_Default.ReturnURL'],
302 $state[
'PersistentAuthData'][] =
'saml:sp:prevAuth';
305 $source->handleResponse($state, $idp, $attributes);