2626use OpenConext \EngineBlock \Metadata \MfaEntity ;
2727use OpenConext \EngineBlock \Metadata \Service ;
2828use OpenConext \EngineBlock \Metadata \TransparentMfaEntity ;
29+ use OpenConext \EngineBlock \Metadata \X509 \KeyPairFactory ;
2930use OpenConext \EngineBlockBundle \Authentication \AuthenticationState ;
3031use OpenConext \EngineBlockBundle \Exception \UnknownKeyIdException ;
32+ use OpenConext \EngineBlock \Service \ProcessingStateHelperInterface ;
3133use OpenConext \Value \Saml \Entity ;
3234use OpenConext \Value \Saml \EntityId ;
3335use OpenConext \Value \Saml \EntityType ;
@@ -126,6 +128,8 @@ class EngineBlock_Corto_ProxyServer
126128 protected $ _templateSource ;
127129 protected $ _processingMode = false ;
128130
131+ protected $ _diContainer = null ;
132+
129133 /**
130134 * @var EngineBlock_Saml2_AuthnRequestAnnotationDecorator
131135 */
@@ -144,6 +148,7 @@ class EngineBlock_Corto_ProxyServer
144148 public function __construct (Twig_Environment $ twig )
145149 {
146150 $ this ->_server = $ this ;
151+ $ this ->_diContainer = EngineBlock_ApplicationSingleton::getInstance ()->getDiContainer ();
147152 $ this ->twig = $ twig ;
148153 }
149154
@@ -353,6 +358,20 @@ public function getRepository()
353358 return $ this ->_repository ;
354359 }
355360
361+ /**
362+ * @return ServiceProvider
363+ */
364+ public function getEngineSpRole ()
365+ {
366+ $ keyId = $ this ->getKeyId ();
367+ if (!$ keyId ) {
368+ $ keyId = KeyPairFactory::DEFAULT_KEY_PAIR_IDENTIFIER ;
369+ }
370+
371+ $ serviceProvider = $ this ->_diContainer ->getServiceProviderFactory ()->createEngineBlockEntityFrom ($ keyId );
372+ return ServiceProvider::fromServiceProviderEntity ($ serviceProvider );
373+ }
374+
356375//////// MAIN /////////
357376
358377 public function serve ($ serviceName , $ remoteIdpMd5 = "" )
@@ -402,6 +421,131 @@ public function setRemoteIdpMd5($remoteIdPMd5)
402421 return $ this ;
403422 }
404423
424+
425+ //////// CALLOUT HANDLERS ////////
426+
427+ function handleSRAMInterruptCallout (
428+ $ receivedResponse ,
429+ $ receivedRequest
430+ ) {
431+ $ logger = $ this ->getLogger ();
432+ $ logger ->info ('Handle SRAM interrupt callout ' );
433+
434+ if ("" != $ receivedResponse ->getSRAMInterruptNonce ()) {
435+
436+ // Add the SRAM step
437+ $ this ->_diContainer ->getProcessingStateHelper ()->addStep (
438+ $ receivedRequest ->getId (),
439+ ProcessingStateHelperInterface::STEP_SRAM ,
440+ $ this ->getEngineSpRole (),
441+ $ receivedResponse
442+ );
443+
444+ // Redirect to SRAM
445+ $ this ->sendSRAMInterruptRequest ($ receivedResponse , $ receivedRequest );
446+
447+ return true ;
448+ }
449+
450+ return false ;
451+ }
452+
453+ function handleStepupAuthenticationCallout (
454+ $ receivedResponse ,
455+ $ receivedRequest
456+ ) {
457+ $ logger = $ this ->getLogger ();
458+ $ logger ->info ('Handle Stepup authentication callout ' );
459+
460+ // Add Stepup authentication step
461+ $ currentProcessStep = $ this ->_diContainer ->getProcessingStateHelper ()->addStep (
462+ $ receivedRequest ->getId (),
463+ ProcessingStateHelperInterface::STEP_STEPUP ,
464+ $ this ->_diContainer ->getStepupIdentityProvider ($ this ),
465+ $ receivedResponse
466+ );
467+
468+ if ($ receivedRequest ->isDebugRequest ()) {
469+ $ sp = $ this ->getEngineSpRole ();
470+ } else {
471+ $ issuer = $ receivedRequest ->getIssuer () ? $ receivedRequest ->getIssuer ()->getValue () : '' ;
472+ $ sp = $ this ->getRepository ()->fetchServiceProviderByEntityId ($ issuer );
473+ }
474+
475+ $ issuer = $ receivedResponse ->getIssuer () ? $ receivedResponse ->getIssuer ()->getValue () : '' ;
476+ $ idp = $ this ->getRepository ()->fetchIdentityProviderByEntityId ($ issuer );
477+
478+ // When dealing with an SP that acts as a trusted proxy, we should use the proxying SP and not the proxy itself.
479+ if ($ sp ->getCoins ()->isTrustedProxy ()) {
480+ // Overwrite the trusted proxy SP instance with that of the SP that uses the trusted proxy.
481+ $ sp = $ this ->findOriginalServiceProvider ($ receivedRequest , $ logger );
482+ }
483+
484+ $ pdpLoas = $ receivedResponse ->getPdpRequestedLoas ();
485+ $ loaRepository = $ this ->_diContainer ->getLoaRepository ();
486+ $ authnRequestLoas = $ receivedRequest ->getStepupObligations ($ loaRepository ->getStepUpLoas ());
487+
488+ // Get mapped AuthnClassRef and get NameId
489+ $ nameId = clone $ receivedResponse ->getNameId ();
490+ $ authnClassRef = $ this ->_diContainer ->getStepupGatewayCallOutHelper ()->getStepupLoa ($ idp , $ sp , $ authnRequestLoas , $ pdpLoas );
491+
492+ $ this ->sendStepupAuthenticationRequest (
493+ $ receivedRequest ,
494+ $ currentProcessStep ->getRole (),
495+ $ authnClassRef ,
496+ $ nameId ,
497+ $ sp ->getCoins ()->isStepupForceAuthn ()
498+ );
499+ }
500+
501+ function handleConsentAuthenticationCallout (
502+ $ receivedResponse ,
503+ $ receivedRequest
504+ // $currentProcessStep
505+ ) {
506+ $ logger = $ this ->getLogger ();
507+ $ logger ->info ('Handle Consent authentication callout ' );
508+
509+ // Add the consent step
510+ $ currentProcessStep = $ this ->_diContainer ->getProcessingStateHelper ()->addStep (
511+ $ receivedRequest ->getId (),
512+ ProcessingStateHelperInterface::STEP_CONSENT ,
513+ $ this ->getEngineSpRole (),
514+ $ receivedResponse
515+ );
516+
517+ $ issuer = $ receivedResponse ->getIssuer () ? $ receivedResponse ->getIssuer ()->getValue () : '' ;
518+ $ idp = $ this ->getRepository ()->fetchIdentityProviderByEntityId ($ issuer );
519+
520+ if ($ receivedRequest ->isDebugRequest ()) {
521+ $ sp = $ this ->getEngineSpRole ();
522+ } else {
523+ $ issuer = $ receivedRequest ->getIssuer () ? $ receivedRequest ->getIssuer ()->getValue () : '' ;
524+ $ sp = $ this ->getRepository ()->fetchServiceProviderByEntityId ($ issuer );
525+ }
526+
527+ // When dealing with an SP that acts as a trusted proxy, we should use the proxying SP and not the proxy itself.
528+ if ($ sp ->getCoins ()->isTrustedProxy ()) {
529+ // Overwrite the trusted proxy SP instance with that of the SP that uses the trusted proxy.
530+ $ sp = $ this ->_server ->findOriginalServiceProvider ($ receivedRequest , $ this ->getLogger ());
531+ }
532+
533+ $ pdpLoas = $ receivedResponse ->getPdpRequestedLoas ();
534+ $ loaRepository = $ this ->_diContainer ->getLoaRepository ();
535+ $ authnRequestLoas = $ receivedRequest ->getStepupObligations ($ loaRepository ->getStepUpLoas ());
536+
537+ $ shouldUseStepup = $ this ->_diContainer ->getStepupGatewayCallOutHelper ()->shouldUseStepup ($ idp , $ sp , $ authnRequestLoas , $ pdpLoas );
538+
539+ // Goto consent if no Stepup authentication is needed
540+ if (!$ shouldUseStepup ) {
541+ $ this ->sendConsentAuthenticationRequest ($ receivedResponse , $ receivedRequest , $ currentProcessStep ->getRole (), $ this ->_diContainer ->getAuthenticationStateHelper ()->getAuthenticationState ());
542+ return true ;
543+ }
544+
545+ return false ;
546+ }
547+
548+
405549//////// REQUEST HANDLING /////////
406550
407551 public function sendAuthenticationRequest (
@@ -467,7 +611,15 @@ public function sendAuthenticationRequest(
467611 $ this ->getBindingsModule ()->send ($ ebRequest , $ identityProvider );
468612 }
469613
470- public function sendStepupAuthenticationRequest (
614+ function sendSRAMInterruptRequest ($ response , $ request ) {
615+ $ nonce = $ response ->getSRAMInterruptNonce ();
616+
617+ $ sbsClient = EngineBlock_ApplicationSingleton::getInstance ()->getDiContainer ()->getSbsClient ();
618+ $ redirect_url = $ sbsClient ->getInterruptLocationLink ($ nonce );
619+ $ this ->redirect ($ redirect_url , '' );
620+ }
621+
622+ function sendStepupAuthenticationRequest (
471623 EngineBlock_Saml2_AuthnRequestAnnotationDecorator $ spRequest ,
472624 IdentityProvider $ identityProvider ,
473625 Loa $ authnContextClassRef ,
@@ -558,14 +710,6 @@ function sendConsentAuthenticationRequest(
558710 $ this ->_server ->getBindingsModule ()->send ($ newResponse , $ serviceProvider );
559711 }
560712
561- function sendSRAMInterruptRequest ($ response , $ request ) {
562- $ nonce = $ response ->getSRAMInterruptNonce ();
563-
564- $ sbsClient = EngineBlock_ApplicationSingleton::getInstance ()->getDiContainer ()->getSbsClient ();
565- $ redirect_url = $ sbsClient ->getInterruptLocationLink ($ nonce );
566- $ this ->redirect ($ redirect_url , '' );
567- }
568-
569713//////// RESPONSE HANDLING ////////
570714
571715 public function createProxyCountExceededResponse (EngineBlock_Saml2_AuthnRequestAnnotationDecorator $ request )
0 commit comments