/**
  * @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);
     }
 }
Example #3
0
 /**
  * @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));
         }
     }
 }
Example #14
0
 /**
  * @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);
 }
Example #19
0
 /**
  * @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);
 }
Example #23
0
 /**
  * @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');
     }
 }