/**
  * @param Request $httpRequest
  * @param string  $provider
  * @return array|Response
  */
 public function consumeAssertionAction(Request $httpRequest, $provider)
 {
     $provider = $this->getProvider($provider);
     $this->get('logger')->notice(sprintf('Received GSSP "%s" SAMLResponse through Gateway, attempting to process', $provider->getName()));
     try {
         /** @var \Surfnet\SamlBundle\Http\PostBinding $postBinding */
         $postBinding = $this->get('surfnet_saml.http.post_binding');
         $assertion = $postBinding->processResponse($httpRequest, $provider->getRemoteIdentityProvider(), $provider->getServiceProvider());
     } catch (Exception $exception) {
         $provider->getStateHandler()->clear();
         $this->getLogger()->error(sprintf('Could not process received Response, error: "%s"', $exception->getMessage()));
         return $this->renderInitiateForm($provider->getName(), ['authenticationFailed' => true]);
     }
     $expectedResponseTo = $provider->getStateHandler()->getRequestId();
     $provider->getStateHandler()->clear();
     if (!InResponseTo::assertEquals($assertion, $expectedResponseTo)) {
         $this->getLogger()->critical(sprintf('Received Response with unexpected InResponseTo, %s', $expectedResponseTo ? 'expected "' . $expectedResponseTo . '"' : ' no response expected'));
         return $this->renderInitiateForm($provider->getName(), ['authenticationFailed' => true]);
     }
     $this->get('logger')->notice(sprintf('Processed GSSP "%s" SAMLResponse received through Gateway successfully', $provider->getName()));
     /** @var \Surfnet\StepupSelfService\SelfServiceBundle\Service\GssfService $service */
     $service = $this->get('surfnet_stepup_self_service_self_service.service.gssf');
     /** @var \Surfnet\SamlBundle\SAML2\Attribute\AttributeDictionary $attributeDictionary */
     $attributeDictionary = $this->get('surfnet_saml.saml.attribute_dictionary');
     $gssfId = $attributeDictionary->translate($assertion)->getNameID();
     $secondFactorId = $service->provePossession($this->getIdentity()->id, $provider->getName(), $gssfId);
     if ($secondFactorId) {
         $this->getLogger()->notice('GSSF possession has been proven successfully');
         return $this->redirectToRoute('ss_registration_email_verification_email_sent', ['secondFactorId' => $secondFactorId]);
     }
     $this->getLogger()->error('Unable to prove GSSF possession');
     return $this->renderInitiateForm($provider->getName(), ['proofOfPossessionFailed' => true]);
 }
 /**
  * @test
  * @group saml2-response
  * @group saml2
  */
 public function in_reponse_to_equality_is_strictly_checked()
 {
     $assertion = new SAML2_Assertion();
     $subjectConfirmationWithData = new SAML2_XML_saml_SubjectConfirmation();
     $subjectConfirmationData = new SAML2_XML_saml_SubjectConfirmationData();
     $subjectConfirmationData->InResponseTo = '1';
     $subjectConfirmationWithData->SubjectConfirmationData = $subjectConfirmationData;
     $assertion->setSubjectConfirmation([$subjectConfirmationWithData]);
     $this->assertTrue(InResponseTo::assertEquals($assertion, '1'));
     $this->assertFalse(InResponseTo::assertEquals($assertion, 1));
 }
 private function handleEvent(GetResponseEvent $event)
 {
     /** @var SessionHandler $sessionHandler */
     $sessionHandler = $this->container->get('ra.security.authentication.session_handler');
     // reinstate the token from the session. Could be expanded with logout check if needed
     if ($this->getTokenStorage()->getToken()) {
         return;
     }
     /** @var SamlInteractionProvider $samlInteractionProvider */
     $samlInteractionProvider = $this->container->get('ra.security.authentication.saml');
     if (!$samlInteractionProvider->isSamlAuthenticationInitiated()) {
         $sessionHandler->setCurrentRequestUri($event->getRequest()->getUri());
         $event->setResponse($samlInteractionProvider->initiateSamlRequest());
         /** @var SamlAuthenticationLogger $logger */
         $logger = $this->container->get('surfnet_saml.logger')->forAuthentication($sessionHandler->getRequestId());
         $logger->notice('Sending AuthnRequest');
         return;
     }
     /** @var SamlAuthenticationLogger $logger */
     $logger = $this->container->get('surfnet_saml.logger')->forAuthentication($sessionHandler->getRequestId());
     $expectedInResponseTo = $sessionHandler->getRequestId();
     try {
         $assertion = $samlInteractionProvider->processSamlResponse($event->getRequest());
     } catch (PreconditionNotMetException $e) {
         $logger->notice(sprintf('SAML response precondition not met: "%s"', $e->getMessage()));
         $event->setResponse($this->renderPreconditionExceptionResponse($e));
         return;
     } catch (Exception $e) {
         $logger->error(sprintf('Failed SAMLResponse Parsing: "%s"', $e->getMessage()));
         throw new AuthenticationException('Failed SAMLResponse parsing', 0, $e);
     }
     if (!InResponseTo::assertEquals($assertion, $expectedInResponseTo)) {
         $logger->error('Unknown or unexpected InResponseTo in SAMLResponse');
         throw new AuthenticationException('Unknown or unexpected InResponseTo in SAMLResponse');
     }
     $logger->notice('Successfully processed SAMLResponse, attempting to authenticate');
     $loaResolutionService = $this->container->get('surfnet_stepup.service.loa_resolution');
     $loa = $loaResolutionService->getLoa($assertion->getAuthnContextClassRef());
     $token = new SamlToken($loa);
     $token->assertion = $assertion;
     /** @var AuthenticationProviderManager $authenticationManager */
     $authenticationManager = $this->container->get('security.authentication.manager');
     try {
         $authToken = $authenticationManager->authenticate($token);
     } catch (BadCredentialsException $exception) {
         $logger->error(sprintf('Bad credentials, reason: "%s"', $exception->getMessage()), ['exception' => $exception]);
         $event->setResponse($this->renderBadCredentialsResponse($exception));
         return;
     } catch (AuthenticationException $failed) {
         $logger->error(sprintf('Authentication Failed, reason: "%s"', $failed->getMessage()), ['exception' => $failed]);
         $event->setResponse($this->renderAuthenticationExceptionResponse($failed));
         return;
     }
     // for the current request
     $this->getTokenStorage()->setToken($authToken);
     // migrate the session to prevent session hijacking
     $sessionHandler->migrate();
     $event->setResponse(new RedirectResponse($sessionHandler->getCurrentRequestUri()));
     $logger->notice('Authentication succeeded, redirecting to original location');
 }
 /**
  * @param Request $httpRequest
  * @param string  $provider
  * @return array|Response
  */
 public function verifyAction(Request $httpRequest, $provider)
 {
     $provider = $this->getProvider($provider);
     $this->get('logger')->notice(sprintf('Received GSSP "%s" SAMLResponse through Gateway, attempting to process', $provider->getName()));
     try {
         /** @var \Surfnet\SamlBundle\Http\PostBinding $postBinding */
         $postBinding = $this->get('surfnet_saml.http.post_binding');
         $assertion = $postBinding->processResponse($httpRequest, $provider->getRemoteIdentityProvider(), $provider->getServiceProvider());
     } catch (Exception $exception) {
         $provider->getStateHandler()->clear();
         $this->getLogger()->error(sprintf('Could not process received Response, error: "%s"', $exception->getMessage()));
         throw new BadRequestHttpException('Could not process received SAML response, cannot return to vetting procedure');
     }
     $expectedResponseTo = $provider->getStateHandler()->getRequestId();
     $provider->getStateHandler()->clear();
     if (!InResponseTo::assertEquals($assertion, $expectedResponseTo)) {
         $this->getLogger()->critical(sprintf('Received Response with unexpected InResponseTo: %s', $expectedResponseTo ? 'expected "' . $expectedResponseTo . '"' : ' no response expected'));
         throw new BadRequestHttpException('Received unexpected SAML response, cannot return to vetting procedure');
     }
     $this->get('logger')->notice(sprintf('Processed GSSP "%s" SAMLResponse received through Gateway successfully', $provider->getName()));
     /** @var \Surfnet\SamlBundle\SAML2\Attribute\AttributeDictionary $attributeDictionary */
     $attributeDictionary = $this->get('surfnet_saml.saml.attribute_dictionary');
     $gssfId = $attributeDictionary->translate($assertion)->getNameID();
     /** @var \Surfnet\StepupRa\RaBundle\Service\VettingService $vettingService */
     $vettingService = $this->get('ra.service.vetting');
     $result = $vettingService->verifyGssfId($gssfId);
     if ($result->isSuccess()) {
         $this->getLogger()->notice('GSSP possession proven successfully');
         return $this->redirectToRoute('ra_vetting_verify_identity', ['procedureId' => $result->getProcedureId()]);
     }
     if (!$result->getProcedureId()) {
         // Should be unreachable statement, because the request ID is compared to the response ID a few lines before
         // this.
         throw new RuntimeException('Procedure ID for GSSF verification procedure could not be recovered.');
     }
     $this->getLogger()->notice('Unable to prove possession of correct GSSF: ' . 'GSSF ID registered in Self-Service does not match current GSSF ID');
     return $this->render('SurfnetStepupRaRaBundle:Vetting/Gssf:initiate.html.twig', ['provider' => $provider->getName(), 'procedureId' => $result->getProcedureId(), 'gssfIdMismatch' => true]);
 }
 /**
  * @param GetResponseEvent $event
  */
 private function handleEvent(GetResponseEvent $event)
 {
     if ($this->tokenStorage->getToken()) {
         return;
     }
     if (!$this->samlInteractionProvider->isSamlAuthenticationInitiated()) {
         $this->sendAuthnRequest($event);
         return;
     }
     $expectedInResponseTo = $this->stateHandler->getRequestId();
     $logger = $this->logger;
     try {
         $assertion = $this->samlInteractionProvider->processSamlResponse($event->getRequest());
     } catch (PreconditionNotMetException $e) {
         $logger->notice(sprintf('SAML response precondition not met: "%s"', $e->getMessage()));
         $this->setPreconditionExceptionResponse($e, $event);
         return;
     } catch (Exception $e) {
         $logger->error(sprintf('Failed SAMLResponse Parsing: "%s"', $e->getMessage()));
         throw new AuthenticationException('Failed SAMLResponse parsing', 0, $e);
     }
     if (!InResponseTo::assertEquals($assertion, $expectedInResponseTo)) {
         $logger->error('Unknown or unexpected InResponseTo in SAMLResponse');
         throw new AuthenticationException('Unknown or unexpected InResponseTo in SAMLResponse');
     }
     $logger->notice('Successfully processed SAMLResponse, attempting to authenticate');
     $token = new SamlToken();
     $token->assertion = $assertion;
     try {
         $authToken = $this->authenticationManager->authenticate($token);
     } catch (AuthenticationException $failed) {
         $logger->error(sprintf('Authentication Failed, reason: "%s"', $failed->getMessage()));
         $this->setAuthenticationFailedResponse($event);
         return;
     }
     $this->tokenStorage->setToken($authToken);
     // migrate the session to prevent session hijacking
     $this->session->migrate();
     $event->setResponse(new RedirectResponse($this->stateHandler->getCurrentRequestUri()));
     $logger->notice('Authentication succeeded, redirecting to original location');
 }