/**
  * @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);
 }
 public function test_does_nothing_if_issuer_has_no_format()
 {
     $action = new AssertionIssuerFormatValidatorAction($loggerMock = TestHelper::getLoggerMock($this), $expectedIssuerFormat = SamlConstants::NAME_ID_FORMAT_EMAIL);
     $context = TestHelper::getAssertionContext($assertion = new Assertion());
     $assertion->setIssuer(new Issuer('http://issuer.com'));
     $action->execute($context);
 }
 public function test_creates_outbounding_authn_request()
 {
     $action = new CreateAuthnRequestAction(TestHelper::getLoggerMock($this));
     $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_SP);
     $action->execute($context);
     $this->assertInstanceOf(AuthnRequest::class, $context->getOutboundMessage());
 }
 /**
  * @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);
 }
 public function test_calls_assertion_validator_with_assertion_from_context()
 {
     $action = new AssertionValidatorAction(TestHelper::getLoggerMock($this), $assertionValidatorMock = TestHelper::getAssertionValidatorMock($this));
     $context = TestHelper::getAssertionContext($assertion = new Assertion());
     $assertionValidatorMock->expects($this->once())->method('validateAssertion')->with($assertion);
     $action->execute($context);
 }
 public function test_sets_outbounding_message_version_to_value_from_constructor()
 {
     $action = new MessageVersionAction(TestHelper::getLoggerMock($this), $value = SamlConstants::VERSION_20);
     $context = TestHelper::getProfileContext();
     $context->getOutboundContext()->setMessage($message = new AuthnRequest());
     $action->execute($context);
     $this->assertEquals($value, $message->getVersion());
 }
 public function test_sets_id_of_outbounding_message()
 {
     $action = new MessageIdAction(TestHelper::getLoggerMock($this));
     $context = TestHelper::getProfileContext();
     $context->getOutboundContext()->setMessage($message = new AuthnRequest());
     $action->execute($context);
     $this->assertNotNull($message->getID());
 }
 public function test_debug_tree()
 {
     $innerAction = new AssertionAction(TestHelper::getLoggerMock($this), new FooAction());
     $outerAction = new AssertionAction(TestHelper::getLoggerMock($this), $innerAction);
     $actualTree = $outerAction->debugPrintTree();
     $expectedTree = [AssertionAction::class => [AssertionAction::class => [FooAction::class => []]]];
     $this->assertEquals($expectedTree, $actualTree);
 }
 public function test_calls_validator()
 {
     $action = new TimeValidatorAction($loggerMock = TestHelper::getLoggerMock($this), $validatorMock = TestHelper::getAssertionTimeValidatorMock($this), $timeProviderMock = TestHelper::getTimeProviderMock($this), $allowedSkew = 120);
     $context = TestHelper::getAssertionContext($assertion = new Assertion());
     $timeProviderMock->expects($this->once())->method('getTimestamp')->willReturn($timestamp = 123123123);
     $validatorMock->expects($this->once())->method('validateTimeRestrictions')->with($assertion, $timestamp, $allowedSkew);
     $action->execute($context);
 }
 public function test_logs_known_issuer()
 {
     $action = new KnownAssertionIssuerAction($loggerMock = TestHelper::getLoggerMock($this), $entityDescriptorStoreMock = TestHelper::getEntityDescriptorStoreMock($this));
     $context = TestHelper::getAssertionContext($assertion = new Assertion());
     $assertion->setIssuer(new Issuer($issuer = 'http://issuer.com'));
     $entityDescriptorStoreMock->expects($this->once())->method('has')->with($issuer)->willReturn(true);
     $loggerMock->expects($this->once())->method('debug')->with('Known assertion issuer: "http://issuer.com"');
     $action->execute($context);
 }
 public function test_sets_outbounding_message_issue_instant_to_value_from_time_provider()
 {
     $action = new MessageIssueInstantAction(TestHelper::getLoggerMock($this), $timeProviderMock = TestHelper::getTimeProviderMock($this));
     $timeProviderMock->expects($this->any())->method('getTimestamp')->willReturn(1412399250);
     $context = TestHelper::getProfileContext();
     $context->getOutboundContext()->setMessage($message = new AuthnRequest());
     $action->execute($context);
     $this->assertEquals('2014-10-04T05:07:30Z', $message->getIssueInstantString());
 }
 /**
  * @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);
 }
 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());
 }
 /**
  * @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);
 }
 /**
  * @expectedException \LightSaml\Error\LightSamlContextException
  * @expectedExceptionMessage Invalid inbound message destination "http://localhost/foo"
  */
 public function test_throws_exception_when_destination_does_not_match()
 {
     $loggerMock = TestHelper::getLoggerMock($this);
     $endpointResolverMock = $this->getEndpointResolverMock();
     /** @var AbstractDestinationValidatorAction $action */
     $action = $this->getMockForAbstractClass(AbstractDestinationValidatorAction::class, [$loggerMock, $endpointResolverMock]);
     $context = $this->buildContext(ProfileContext::ROLE_IDP, $expectedDestination = 'http://localhost/foo');
     $endpointResolverMock->expects($this->once())->method('resolve')->willReturn(false);
     $action->execute($context);
 }
 /**
  * @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());
 }
 /**
  * @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);
 }
 public function test_calls_binding_factory_with_endpoint_type_and_calls_binding_and_sets_response_to_context()
 {
     $action = new SendMessageAction($loggerMock = TestHelper::getLoggerMock($this), $bindingFactoryMock = TestHelper::getBindingFactoryMock($this));
     $context = TestHelper::getProfileContext();
     $context->getEndpointContext()->setEndpoint(new SingleSignOnService($location = 'http://example/com', $bindingType = SamlConstants::BINDING_SAML2_HTTP_POST));
     $bindingFactoryMock->expects($this->once())->method('create')->with($bindingType)->willReturn($bindingMock = TestHelper::getBindingMock($this));
     $bindingMock->expects($this->once())->method('send')->with($this->isInstanceOf(MessageContext::class))->willReturn($response = new Response());
     $loggerMock->expects($this->once())->method('info')->with('Sending message', $this->isType('array'));
     $action->execute($context);
     $this->assertSame($response, $context->getHttpResponseContext()->getResponse());
 }
 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());
 }
 /**
  * @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);
 }
 public function test_creates_request_state_with_outbound_message_id()
 {
     $action = new SaveRequestStateAction(TestHelper::getLoggerMock($this), $requestStateStoreMock = TestHelper::getRequestStateStoreMock($this));
     $context = TestHelper::getProfileContext();
     $context->getOutboundContext()->setMessage($message = new AuthnRequest());
     $message->setID($id = '123123123');
     $requestStateStoreMock->expects($this->once())->method('set')->with($this->isInstanceOf(RequestState::class))->willReturnCallback(function (RequestState $requestState) use($id) {
         $this->assertEquals($id, $requestState->getId());
     });
     $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_creates_default_trust_options_if_none_resolved()
 {
     $action = new ResolvePartyEntityIdAction($logger = TestHelper::getLoggerMock($this), $spEntityStore = $this->getEntityDescriptorStoreMock(), $idpEntityStore = $this->getEntityDescriptorStoreMock(), $trustOptionsStore = $this->getTrustOptionsStore());
     $context = new ProfileContext(Profiles::SSO_SP_SEND_AUTHN_REQUEST, ProfileContext::ROLE_IDP);
     $context->getPartyEntityContext()->setEntityDescriptor($entityDescriptor = (new EntityDescriptor())->setEntityID($entityId = 'http://localhost/id'));
     $spEntityStore->expects($this->never())->method('get');
     $idpEntityStore->expects($this->never())->method('get');
     $trustOptionsStore->expects($this->once())->method('get')->with($entityId)->willReturn(null);
     $action->execute($context);
     $this->assertNotNull($context->getPartyEntityContext()->getTrustOptions());
     $this->assertNotNull($context->getPartyEntityContext()->getEntityDescriptor());
 }
 public function test_warning_logged_if_no_verification()
 {
     $action = new MessageSignatureValidatorAction($logger = TestHelper::getLoggerMock($this), $signatureValidator = $this->getSignatureValidatorMock());
     $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP);
     $context->getInboundContext()->setMessage($message = new AuthnRequest());
     $message->setSignature($signature = new SignatureStringReader());
     $message->setIssuer(new Issuer($issuerValue = 'http://localhost/issuer'));
     $signatureValidator->expects($this->once())->method('validate')->willReturn(null);
     $logger->expects($this->never())->method('debug');
     $logger->expects($this->once())->method('warning')->with('Signature verification was not performed', $this->isType('array'));
     $action->execute($context);
 }
 public function test_receives_message()
 {
     $action = new ReceiveMessageAction($logger = TestHelper::getLoggerMock($this), $bindingFactory = $this->getBindingFactoryMock());
     $context = new ProfileContext(Profiles::SSO_SP_SEND_AUTHN_REQUEST, ProfileContext::ROLE_SP);
     $context->getHttpRequestContext()->setRequest($request = new Request());
     $binding = $this->getBindingMock();
     $bindingFactory->expects($this->once())->method('detectBindingType')->with($request)->willReturn($bindingType = SamlConstants::BINDING_SAML2_HTTP_POST);
     $logger->expects($this->once())->method('debug')->with('Detected binding type: urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', $this->isType('array'));
     $bindingFactory->expects($this->once())->method('create')->with($bindingType)->willReturn($binding);
     $binding->expects($this->once())->method('receive')->with($request, $context->getInboundContext());
     $action->execute($context);
     $this->assertEquals($bindingType, $context->getInboundContext()->getBindingType());
 }
 public function test_calls_session_processor()
 {
     $action = new SpSsoStateAction(TestHelper::getLoggerMock($this), $sessionProcessorMock = $this->getSessionProcessorMock());
     $context = new ProfileContext(Profiles::SSO_IDP_RECEIVE_AUTHN_REQUEST, ProfileContext::ROLE_IDP);
     $context->getInboundContext()->setMessage($response = new Response());
     $response->addAssertion($assertion1 = new Assertion());
     $response->addAssertion($assertion2 = new Assertion());
     $context->getOwnEntityContext()->setEntityDescriptor(new EntityDescriptor($ownEntityId = 'http://own.entity.id'));
     $context->getPartyEntityContext()->setEntityDescriptor(new EntityDescriptor($partyEntityId = 'http://party.id'));
     $sessionProcessorMock->expects($this->once())->method('processAssertions')->with($this->isType('array'), $ownEntityId, $partyEntityId)->willReturnCallback(function (array $assertions, $ownId, $partyId) use($assertion1, $assertion2) {
         $this->assertSame($assertion1, $assertions[0]);
         $this->assertSame($assertion2, $assertions[1]);
     });
     $action->execute($context);
 }
 public function test_adds_known_in_response_to_request_state_to_context()
 {
     $action = new InResponseToValidatorAction(TestHelper::getLoggerMock($this), $requestStateMock = TestHelper::getRequestStateStoreMock($this));
     $context = TestHelper::getAssertionContext($assertion = new Assertion());
     $assertion->setSubject($subject = new Subject());
     $subject->addSubjectConfirmation($subjectConfirmation = new SubjectConfirmation());
     $subjectConfirmation->setSubjectConfirmationData(new SubjectConfirmationData());
     $subjectConfirmation->getSubjectConfirmationData()->setInResponseTo($inResponseTo = '123123123');
     $requestStateMock->expects($this->once())->method('get')->with($inResponseTo)->willReturn(new RequestState($inResponseTo));
     $action->execute($context);
     /** @var RequestStateContext $requestStateContext */
     $requestStateContext = $context->getSubContext(ProfileContexts::REQUEST_STATE);
     $this->assertInstanceOf(RequestStateContext::class, $requestStateContext);
     $this->assertEquals($inResponseTo, $requestStateContext->getRequestState()->getId());
 }
 public function test_signs_message_when_signing_enabled()
 {
     $action = new SignMessageAction($loggerMock = TestHelper::getLoggerMock($this), $signatureResolverMock = TestHelper::getSignatureResolverMock($this));
     $context = TestHelper::getProfileContext();
     $context->getPartyEntityContext()->setTrustOptions(new TrustOptions());
     $context->getTrustOptions()->setSignAuthnRequest(true);
     $context->getOutboundContext()->setMessage($message = new AuthnRequest());
     $signature = new SignatureWriter($certificateMock = TestHelper::getX509CertificateMock($this));
     $certificateMock->expects($this->any())->method('getInfo')->willReturn($expectedInfo = ['a' => 1]);
     $certificateMock->expects($this->any())->method('getFingerprint')->willReturn($expectedFingerprint = '123123123');
     $signatureResolverMock->expects($this->once())->method('getSignature')->with($context)->willReturn($signature);
     $loggerMock->expects($this->once())->method('debug')->with('Message signed with fingerprint "123123123"', $this->isType('array'));
     $action->execute($context);
     $this->assertSame($signature, $message->getSignature());
 }
 public function test_creates_sso_service_type_criteria()
 {
     $endpointResolverMock = $this->getEndpointResolverMock();
     $action = new DestinationValidatorAuthnRequestAction(TestHelper::getLoggerMock($this), $endpointResolverMock);
     $context = $this->buildContext(ProfileContext::ROLE_IDP, 'http://localhost');
     $endpointResolverMock->expects($this->once())->method('resolve')->willReturnCallback(function (CriteriaSet $criteriaSet, array $endpoints) {
         $this->assertTrue($criteriaSet->has(ServiceTypeCriteria::class));
         $arr = $criteriaSet->get(ServiceTypeCriteria::class);
         $this->assertCount(1, $arr);
         /** @var ServiceTypeCriteria $criteria */
         $criteria = $arr[0];
         $this->assertEquals(SingleSignOnService::class, $criteria->getServiceType());
         return true;
     });
     $action->execute($context);
 }