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