2323use  OCA \UserOIDC \Service \DiscoveryService ;
2424use  OCA \UserOIDC \Service \LdapService ;
2525use  OCA \UserOIDC \Service \ProviderService ;
26+ use  OCA \UserOIDC \Service \ProvisioningDeniedException ;
2627use  OCA \UserOIDC \Service \ProvisioningService ;
2728use  OCA \UserOIDC \Service \TokenService ;
2829use  OCA \UserOIDC \Vendor \Firebase \JWT \JWT ;
@@ -480,26 +481,51 @@ public function code(string $state = '', string $code = '', string $scope = '',
480481		}
481482
482483		$ autoProvisionAllowed  = (!isset ($ oidcSystemConfig ['auto_provision ' ]) || $ oidcSystemConfig ['auto_provision ' ]);
484+ 		$ softAutoProvisionAllowed  = (!isset ($ oidcSystemConfig ['soft_auto_provision ' ]) || $ oidcSystemConfig ['soft_auto_provision ' ]);
485+ 
486+ 		$ shouldDoUserLookup  = !$ autoProvisionAllowed  || ($ softAutoProvisionAllowed  && !$ this  ->provisioningService ->hasOidcUserProvisitioned ($ userId ));
487+ 		if  ($ shouldDoUserLookup  && $ this  ->ldapService ->isLDAPEnabled ()) {
488+ 			// in case user is provisioned by user_ldap, userManager->search() triggers an ldap search which syncs the results 
489+ 			// so new users will be directly available even if they were not synced before this login attempt 
490+ 			$ this  ->userManager ->search ($ userId , 1 , 0 );
491+ 			$ this  ->ldapService ->syncUser ($ userId );
492+ 		}
483493
484- 		// in case user is provisioned by user_ldap, userManager->search() triggers an ldap search which syncs the results 
485- 		// so new users will be directly available even if they were not synced before this login attempt 
486- 		$ this  ->userManager ->search ($ userId );
487- 		$ this  ->ldapService ->syncUser ($ userId );
488494		$ userFromOtherBackend  = $ this  ->userManager ->get ($ userId );
489495		if  ($ userFromOtherBackend  !== null  && $ this  ->ldapService ->isLdapDeletedUser ($ userFromOtherBackend )) {
490496			$ userFromOtherBackend  = null ;
491497		}
492498
493499		if  ($ autoProvisionAllowed ) {
494- 			$ softAutoProvisionAllowed  = (!isset ($ oidcSystemConfig ['soft_auto_provision ' ]) || $ oidcSystemConfig ['soft_auto_provision ' ]);
495- 			if  (!$ softAutoProvisionAllowed  && $ userFromOtherBackend  !== null ) {
496- 				// if soft auto-provisioning is disabled, 
497- 				// we refuse login for a user that already exists in another backend 
498- 				$ message  = $ this  ->l10n ->t ('User conflict ' );
499- 				return  $ this  ->build403TemplateResponse ($ message , Http::STATUS_BAD_REQUEST , ['reason '  => 'non-soft auto provision, user conflict ' ], false );
500+ 			// $softAutoProvisionAllowed = (!isset($oidcSystemConfig['soft_auto_provision']) || $oidcSystemConfig['soft_auto_provision']); 
501+ 			// if (!$softAutoProvisionAllowed && $userFromOtherBackend !== null) { 
502+ 			// if soft auto-provisioning is disabled, 
503+ 			// we refuse login for a user that already exists in another backend 
504+ 			// $message = $this->l10n->t('User conflict'); 
505+ 			// return $this->build403TemplateResponse($message, Http::STATUS_BAD_REQUEST, ['reason' => 'non-soft auto provision, user conflict'], false); 
506+ 			// } 
507+ 
508+ 			// TODO: (proposal) refactor all provisioning strategies into event handlers 
509+ 			$ user  = null ;
510+ 
511+ 			try  {
512+ 				$ user  = $ this  ->provisioningService ->provisionUser ($ userId , $ providerId , $ idTokenPayload , $ userFromOtherBackend );
513+ 			} catch  (ProvisioningDeniedException   $ denied ) {
514+ 				// TODO MagentaCLOUD should upstream the exception handling 
515+ 				$ redirectUrl  = $ denied ->getRedirectUrl ();
516+ 				if  ($ redirectUrl  === null ) {
517+ 					$ message  = $ this  ->l10n ->t ('Failed to provision user ' );
518+ 					return  $ this  ->build403TemplateResponse ($ message , Http::STATUS_BAD_REQUEST , ['reason '  => $ denied ->getMessage ()]);
519+ 				} else  {
520+ 					// error response is a redirect, e.g. to a booking site 
521+ 					// so that you can immediately get the registration page 
522+ 					return  new  RedirectResponse ($ redirectUrl );
523+ 				}
500524			}
525+ 
501526			// use potential user from other backend, create it in our backend if it does not exist 
502- 			$ user  = $ this  ->provisioningService ->provisionUser ($ userId , $ providerId , $ idTokenPayload , $ userFromOtherBackend );
527+ 			// $user = $this->provisioningService->provisionUser($userId, $providerId, $idTokenPayload, $userFromOtherBackend); 
528+ 			// no default exception handling to pass on unittest assertion failures 
503529		} else  {
504530			// when auto provision is disabled, we assume the user has been created by another user backend (or manually) 
505531			$ user  = $ userFromOtherBackend ;
@@ -526,12 +552,12 @@ public function code(string $state = '', string $code = '', string $scope = '',
526552		$ this  ->session ->remove (self ::NONCE );
527553
528554		// store all token information for potential token exchange requests 
529- 		$ tokenData  = array_merge (
530- 			$ data ,
531- 			['provider_id '  => $ providerId ],
532- 		);
533- 		$ this  ->tokenService ->storeToken ($ tokenData );
534- 		$ this  ->config ->setUserValue ($ user ->getUID (), Application::APP_ID , 'had_token_once ' , '1 ' );
555+ 		//  $tokenData = array_merge(
556+ 			//  $data,
557+ 			//  ['provider_id' => $providerId],
558+ 		//  );
559+ 		//  $this->tokenService->storeToken($tokenData);
560+ 		//  $this->config->setUserValue($user->getUID(), Application::APP_ID, 'had_token_once', '1');
535561
536562		// Set last password confirm to the future as we don't have passwords to confirm against with SSO 
537563		$ this  ->session ->set ('last-password-confirm ' , strtotime ('+4 year ' , time ()));
@@ -758,7 +784,7 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
758784	 * @return JSONResponse 
759785	 */ 
760786	private  function  getBackchannelLogoutErrorResponse (
761- 		string  $ error , string  $ description , array  $ throttleMetadata  = [],
787+ 		string  $ error , string  $ description , array  $ throttleMetadata  = [], ? bool   $ throttle  =  null , 
762788	): JSONResponse   {
763789		$ this  ->logger ->debug ('Backchannel logout error.  '  . $ error  . ' ;  '  . $ description );
764790		return  new  JSONResponse (
0 commit comments