/** * @expectedException \LightSaml\Error\LightSamlContextException * @expectedExceptionMessage Response must contain at least one bearer assertion */ public function test_throws_context_exception_if_no_bearer_assertion() { $action = new HasBearerAssertionsValidatorAction(TestHelper::getLoggerMock($this)); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getInboundContext()->setMessage($response = new Response()); $action->execute($context); }
/** * @param ProfileContext $context */ protected function doExecute(ProfileContext $context) { $partyContext = $context->getPartyEntityContext(); if ($partyContext->getEntityDescriptor() && $partyContext->getTrustOptions()) { $this->logger->debug(sprintf('Party EntityDescriptor and TrustOptions already set for "%s"', $partyContext->getEntityDescriptor()->getEntityID()), LogHelper::getActionContext($context, $this, array('partyEntityId' => $partyContext->getEntityDescriptor()->getEntityID()))); return; } $entityId = $partyContext->getEntityDescriptor() ? $partyContext->getEntityDescriptor()->getEntityID() : null; $entityId = $entityId ? $entityId : $partyContext->getEntityId(); if (null == $entityId) { $message = 'EntityID is not set in the party context'; $this->logger->critical($message, LogHelper::getActionErrorContext($context, $this)); throw new LightSamlContextException($context, $message); } if (null == $partyContext->getEntityDescriptor()) { $partyEntityDescriptor = $this->getPartyEntityDescriptor($context, $context->getOwnRole() === ProfileContext::ROLE_IDP ? $this->spEntityDescriptorProvider : $this->idpEntityDescriptorProvider, $context->getPartyEntityContext()->getEntityId()); $partyContext->setEntityDescriptor($partyEntityDescriptor); $this->logger->debug(sprintf('Known issuer resolved: "%s"', $partyEntityDescriptor->getEntityID()), LogHelper::getActionContext($context, $this, array('partyEntityId' => $partyEntityDescriptor->getEntityID()))); } if (null == $partyContext->getTrustOptions()) { $trustOptions = $this->trustOptionsProvider->get($partyContext->getEntityDescriptor()->getEntityID()); if (null === $trustOptions) { $trustOptions = new TrustOptions(); } $partyContext->setTrustOptions($trustOptions); } }
/** * @param ProfileContext $context * * @return void */ public function doExecute(ProfileContext $context) { $binding = $this->bindingFactory->create($context->getEndpoint()->getBinding()); $outboundContext = $context->getOutboundContext(); $context->getHttpResponseContext()->setResponse($binding->send($outboundContext)); $this->logger->info('Sending message', LogHelper::getActionContext($context, $this, array('message' => $outboundContext->getSerializationContext()->getDocument()->saveXML()))); }
protected function doExecute(ProfileContext $context) { if ($context->getRelayState()) { $this->logger->debug(sprintf('RelayState from context set to outbound message: "%s"', $context->getRelayState()), LogHelper::getActionContext($context, $this)); MessageContextHelper::asSamlMessage($context->getOutboundContext())->setRelayState($context->getRelayState()); } }
/** * @param ProfileContext $context */ protected function doExecute(ProfileContext $context) { $response = MessageContextHelper::asResponse($context->getInboundContext()); if (count($response->getAllEncryptedAssertions()) === 0) { $this->logger->debug('Response has no encrypted assertions', LogHelper::getActionContext($context, $this)); return; } $ownEntityDescriptor = $context->getOwnEntityDescriptor(); $query = $this->credentialResolver->query(); $query->add(new EntityIdCriteria($ownEntityDescriptor->getEntityID()))->add(new MetadataCriteria(ProfileContext::ROLE_IDP === $context->getOwnRole() ? MetadataCriteria::TYPE_IDP : MetadataCriteria::TYPE_SP, SamlConstants::PROTOCOL_SAML2))->add(new UsageCriteria(UsageType::ENCRYPTION)); $query->resolve(); $privateKeys = $query->getPrivateKeys(); if (empty($privateKeys)) { $message = 'No credentials resolved for assertion decryption'; $this->logger->emergency($message, LogHelper::getActionErrorContext($context, $this)); throw new LightSamlContextException($context, $message); } $this->logger->info('Trusted decryption candidates', LogHelper::getActionContext($context, $this, array('credentials' => array_map(function (CredentialInterface $credential) { return sprintf("Entity: '%s'; PK X509 Thumb: '%s'", $credential->getEntityId(), $credential->getPublicKey() ? $credential->getPublicKey()->getX509Thumbprint() : ''); }, $privateKeys)))); foreach ($response->getAllEncryptedAssertions() as $index => $encryptedAssertion) { if ($encryptedAssertion instanceof EncryptedAssertionReader) { $name = sprintf('assertion_encrypted_%s', $index); /** @var DeserializationContext $deserializationContext */ $deserializationContext = $context->getInboundContext()->getSubContext($name, DeserializationContext::class); $assertion = $encryptedAssertion->decryptMultiAssertion($privateKeys, $deserializationContext); $response->addAssertion($assertion); $this->logger->info('Assertion decrypted', LogHelper::getActionContext($context, $this, array('assertion' => $deserializationContext->getDocument()->saveXML()))); } } }
/** * @expectedException \LightSaml\Error\LightSamlContextException * @expectedExceptionMessage Inbound messages does not have Issuer */ public function test_throws_when_inbound_message_has_no_issuer() { $action = new EntityIdFromMessageIssuerAction(TestHelper::getLoggerMock($this)); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getInboundContext()->setMessage(new AuthnRequest()); $action->execute($context); }
/** * @param ProfileContext $context */ protected function doExecute(ProfileContext $context) { if (false === in_array($context->getInboundContext()->getBindingType(), $this->expectedBindingTypes)) { $message = sprintf('Unexpected binding type "%s" - expected binding types are: %s', $context->getInboundContext()->getBindingType(), implode(' ', $this->expectedBindingTypes)); $this->logger->critical($message, LogHelper::getActionErrorContext($context, $this, array('actualBindingType' => $context->getInboundContext()->getBindingType(), 'expectedBindingTypes' => $this->expectedBindingTypes))); throw new LightSamlContextException($context, $message); } }
/** * @param ProfileContext $context */ protected function doExecute(ProfileContext $context) { $message = MessageContextHelper::asSamlMessage($context->getOutboundContext()); $state = new RequestState(); $state->setId($message->getID()); $state->setNonce($message); $this->requestStore->set($state); }
/** * @param ProfileContext $context * * @return void */ protected function doExecute(ProfileContext $context) { $ownEntityDescriptor = $context->getOwnEntityDescriptor(); $issuer = new Issuer($ownEntityDescriptor->getEntityID()); $issuer->setFormat(SamlConstants::NAME_ID_FORMAT_ENTITY); MessageContextHelper::asSamlMessage($context->getOutboundContext())->setIssuer($issuer); $this->logger->debug(sprintf('Issuer set to "%s"', $ownEntityDescriptor->getEntityID()), LogHelper::getActionContext($context, $this)); }
protected function doExecute(ProfileContext $context) { if (null == $context->getInboundContext()->getMessage()) { return; } $this->logger->debug(sprintf('Forwarding relay state: "%s"', $context->getInboundMessage()->getRelayState())); $context->getOutboundMessage()->setRelayState($context->getInboundMessage()->getRelayState()); }
protected function doExecute(ProfileContext $context) { $message = MessageContextHelper::asSamlMessage($context->getInboundContext()); if (null == $message->getIssuer()) { throw new LightSamlContextException($context, 'Inbound messages does not have Issuer'); } $context->getPartyEntityContext()->setEntityId($message->getIssuer()->getValue()); }
/** * @param ProfileContext $context */ protected function doExecute(ProfileContext $context) { $logoutRequest = MessageContextHelper::asLogoutRequest($context->getOutboundContext()); $ssoSessionState = $context->getLogoutSsoSessionState(); $nameId = new NameID(); $nameId->setValue($ssoSessionState->getNameId()); $nameId->setFormat($ssoSessionState->getNameIdFormat()); $logoutRequest->setNameID($nameId); }
/** * @param ProfileContext $context * * @return void */ protected function doExecute(ProfileContext $context) { $this->flush($context->getInboundContext()->getSubContext(ProfileContexts::REQUEST_STATE, null)); foreach ($context as $child) { if ($child instanceof AssertionContext) { $this->flush($child->getSubContext(ProfileContexts::REQUEST_STATE, null)); } } }
/** * @expectedException \LightSaml\Error\LightSamlContextException * @expectedExceptionMessage Missing ACS Service with HTTP POST binding in own SP SSO Descriptor */ public function test_throws_context_exception_if_no_own_acs_service() { $action = new ACSUrlAction($loggerMock = TestHelper::getLoggerMock($this), $endpointResolverMock = $this->getEndpointResolverMock()); $context = new ProfileContext(Profiles::SSO_SP_SEND_AUTHN_REQUEST, ProfileContext::ROLE_SP); $context->getOwnEntityContext()->setEntityDescriptor($entityDescriptorMock = $this->getEntityDescriptorMock()); $entityDescriptorMock->expects($this->once())->method('getAllEndpoints')->willReturn([]); $endpointResolverMock->expects($this->once())->method('resolve')->willReturn([]); $loggerMock->expects($this->once())->method('error'); $action->execute($context); }
/** * @expectedException \LightSaml\Error\LightSamlContextException * @expectedExceptionMessage Unknown InResponseTo '1234567890' */ public function test_throws_context_exception_if_no_request_state_for_in_response_to_from_message() { $action = new InResponseToValidatorAction($loggerMock = TestHelper::getLoggerMock($this), $requestStateStoreMock = $this->getRequestStateStoreMock()); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getInboundContext()->setMessage($response = $this->getStatusResponseMock()); $response->setInResponseTo($inResponseTo = '1234567890'); $requestStateStoreMock->expects($this->once())->method('get')->willReturn(null); $loggerMock->expects($this->once())->method('critical'); $action->execute($context); }
/** * @param string $ownRole * @param string $destination * * @return ProfileContext */ private function buildContext($ownRole, $destination) { $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, $ownRole); $context->getInboundContext()->setMessage(new AuthnRequest()); if ($destination) { $context->getInboundMessage()->setDestination($destination); } $context->getOwnEntityContext()->setEntityDescriptor(new EntityDescriptor()); return $context; }
public function test_sets_relat_state_from_inbound_to_outbound_message() { $action = new ForwardRelayStateAction(TestHelper::getLoggerMock($this)); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getInboundContext()->setMessage($inboundMessage = new AuthnRequest()); $context->getOutboundContext()->setMessage($outboundMessage = new Response()); $inboundMessage->setRelayState($relayState = '123'); $action->execute($context); $this->assertEquals($relayState, $context->getOutboundMessage()->getRelayState()); }
protected function doExecute(ProfileContext $context) { $response = MessageContextHelper::asResponse($context->getInboundContext()); if ($response->getBearerAssertions()) { return; } $message = 'Response must contain at least one bearer assertion'; $this->logger->error($message, LogHelper::getActionErrorContext($context, $this)); throw new LightSamlContextException($context, $message); }
/** * @expectedException \LightSaml\Error\LightSamlAuthenticationException * @expectedExceptionMessage("Unsuccessful SAML response: urn:oasis:names:tc:SAML:2.0:status:Requester * urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding") */ public function test_throws_authentication_exception_if_status_not_success() { $action = new StatusAction($loggerMock = TestHelper::getLoggerMock($this)); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getInboundContext()->setMessage($response = new Response()); $response->setStatus(new Status($statusCode = new StatusCode(SamlConstants::STATUS_REQUESTER))); $statusCode->setStatusCode(new StatusCode(SamlConstants::STATUS_UNSUPPORTED_BINDING)); $loggerMock->expects($this->once())->method('error'); $action->execute($context); }
public function test_sets_outbounding_message_destination_to_endpoint_context_value() { $action = new DestinationAction(TestHelper::getLoggerMock($this)); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getOutboundContext()->setMessage($message = new AuthnRequest()); $context->getEndpointContext()->setEndpoint($endpoint = new SingleSignOnService()); $endpoint->setLocation($location = 'http://idp.com/login'); $action->execute($context); $this->assertEquals($location, $message->getDestination()); }
public function test_sets_name_id_to_outbound_logout_request() { $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getOutboundContext()->setMessage($logoutRequest = new LogoutRequest()); $context->getLogoutContext()->setSsoSessionState((new SsoSessionState())->setNameId($nameId = 'name.id')->setNameIdFormat($nameIdFormat = 'name.id.format')); $action = new SetNameIdAction($this->getLoggerMock()); $action->execute($context); $this->assertNotNull($logoutRequest->getNameID()); $this->assertEquals($nameId, $logoutRequest->getNameID()->getValue()); $this->assertEquals($nameIdFormat, $logoutRequest->getNameID()->getFormat()); }
/** * @expectedException \LightSaml\Error\LightSamlContextException * @expectedExceptionMessage No credentials resolved for assertion decryption */ public function test_throws_context_exception_when_no_credentials_resolved() { $action = new DecryptAssertionsAction($loggerMock = TestHelper::getLoggerMock($this), $credentialResolverMock = $this->getCredentialResolverMock()); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getOwnEntityContext()->setEntityDescriptor(new EntityDescriptor($entityId = 'http://entity.id')); $context->getInboundContext()->setMessage($response = new Response()); $response->addEncryptedAssertion($encryptedAssertionMock1 = $this->getEncryptedAssertionReaderMock()); $credentialResolverMock->expects($this->once())->method('query')->willReturn($query = new CredentialResolverQuery($credentialResolverMock)); $credentialResolverMock->expects($this->once())->method('resolve')->with($query)->willReturn([]); $action->execute($context); }
/** * @param ProfileContext $context */ protected function doExecute(ProfileContext $context) { $response = MessageContextHelper::asResponse($context->getInboundContext()); foreach ($response->getAllAssertions() as $index => $assertion) { $name = sprintf('assertion_%s', $index); /** @var AssertionContext $assertionContext */ $assertionContext = $context->getSubContext($name, AssertionContext::class); $assertionContext->setAssertion($assertion)->setId($name); $this->assertionAction->execute($assertionContext); } }
public function test_sets_own_entity_id_to_outbounding_message_issuer_with_name_id_format_entity() { $action = new CreateMessageIssuerAction(TestHelper::getLoggerMock($this)); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getOutboundContext()->setMessage($message = new AuthnRequest()); $context->getOwnEntityContext()->setEntityDescriptor(new EntityDescriptor($ownEntityId = 'http://own.entity.id')); $action->execute($context); $this->assertNotNull($message->getIssuer()); $this->assertEquals($ownEntityId, $message->getIssuer()->getValue()); $this->assertEquals(SamlConstants::NAME_ID_FORMAT_ENTITY, $message->getIssuer()->getFormat()); }
private function getPartyEntityDescriptor(ProfileContext $context) { $ssoSessionState = $context->getLogoutSsoSessionState(); $ownEntityId = $context->getOwnEntityDescriptor()->getEntityID(); $partyId = $ssoSessionState->getOtherPartyId($ownEntityId); $partyEntityDescriptor = $this->findParty($partyId, [$this->idpEntityDescriptorStore, $this->spEntityDescriptorStore]); if ($partyEntityDescriptor) { return $partyEntityDescriptor; } throw new LightSamlContextException($context, sprintf('Unknown party "%s"', $partyId)); }
/** * @expectedException \LightSaml\Error\LightSamlContextException * @expectedExceptionMessage Error from name id validator */ public function test_wrapps_validation_exception_in_context_exception() { $nameIdValidatorMock = $this->getNameIdValidatorMock(); $action = new IssuerValidatorAction(TestHelper::getLoggerMock($this), $nameIdValidatorMock, $allowedFormat = SamlConstants::NAME_ID_FORMAT_EMAIL); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getInboundContext()->setMessage(new AuthnRequest()); $expectedIssuer = new Issuer('http://localhost', $allowedFormat); $context->getInboundMessage()->setIssuer($expectedIssuer); $nameIdValidatorMock->expects($this->once())->method('validateNameId')->with($expectedIssuer)->willThrowException(new LightSamlValidationException('Error from name id validator')); $action->execute($context); }
/** * @expectedException \LightSaml\Error\LightSamlContextException * @expectedExceptionMessage Unexpected binding type "urn:oasis:names:tc:SAML:2.0:bindings:SOAP" - expected binding types are: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST */ public function test_throws_when_inbound_binding_type_not_one_of_expected() { $action = new AssertBindingTypeAction($logger = TestHelper::getLoggerMock($this), [SamlConstants::BINDING_SAML2_HTTP_POST]); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getInboundContext()->setBindingType(SamlConstants::BINDING_SAML2_SOAP); $logger->expects($this->once())->method('critical')->willReturnCallback(function ($message, $arr) { $this->assertEquals('Unexpected binding type "urn:oasis:names:tc:SAML:2.0:bindings:SOAP" - expected binding types are: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', $message); $this->assertTrue(is_array($arr)); }); $action->execute($context); }
public function test_sets_not_on_or_after_to_outbound_logout_request() { $timeProviderMock = $this->getTimeProviderMock(); $action = new SetNotOnOrAfterAction($this->getLoggerMock(), $timeProviderMock, $skew = 100); $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP); $context->getOutboundContext()->setMessage($logoutRequest = new LogoutRequest()); $timeProviderMock->expects($this->once())->method('getTimestamp')->willReturn($baseTimestamp = 1445953125); $action->execute($context); $expectedTimestamp = $baseTimestamp + $skew; $this->assertEquals($expectedTimestamp, $logoutRequest->getNotOnOrAfterTimestamp()); }
protected function doExecute(ProfileContext $context) { $response = MessageContextHelper::asResponse($context->getInboundContext()); foreach ($response->getAllAssertions() as $assertion) { if ($assertion->getAllAuthnStatements()) { return; } } $message = 'Response must have at least one Assertion containing AuthnStatement element'; $this->logger->error($message, LogHelper::getActionErrorContext($context, $this)); throw new LightSamlContextException($context, $message); }
protected function getDescriptorType(ProfileContext $context) { $ssoSessionState = $context->getLogoutSsoSessionState(); $ownEntityId = $context->getOwnEntityDescriptor()->getEntityID(); if ($ssoSessionState->getIdpEntityId() == $ownEntityId) { return SpSsoDescriptor::class; } elseif ($ssoSessionState->getSpEntityId() == $ownEntityId) { return IdpSsoDescriptor::class; } else { throw new LightSamlContextException($context, 'Unable to resolve logout target descriptor type'); } }