|
23 | 23 | use OCA\UserOIDC\Service\DiscoveryService; |
24 | 24 | use OCA\UserOIDC\Service\LdapService; |
25 | 25 | use OCA\UserOIDC\Service\ProviderService; |
| 26 | +use OCA\UserOIDC\Service\ProvisioningDeniedException; |
26 | 27 | use OCA\UserOIDC\Service\ProvisioningService; |
27 | 28 | use OCA\UserOIDC\Service\TokenService; |
28 | 29 | use OCA\UserOIDC\Vendor\Firebase\JWT\JWT; |
@@ -480,26 +481,51 @@ public function code(string $state = '', string $code = '', string $scope = '', |
480 | 481 | } |
481 | 482 |
|
482 | 483 | $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 | + } |
483 | 493 |
|
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); |
488 | 494 | $userFromOtherBackend = $this->userManager->get($userId); |
489 | 495 | if ($userFromOtherBackend !== null && $this->ldapService->isLdapDeletedUser($userFromOtherBackend)) { |
490 | 496 | $userFromOtherBackend = null; |
491 | 497 | } |
492 | 498 |
|
493 | 499 | 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 | + } |
500 | 524 | } |
| 525 | + |
501 | 526 | // 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 |
503 | 529 | } else { |
504 | 530 | // when auto provision is disabled, we assume the user has been created by another user backend (or manually) |
505 | 531 | $user = $userFromOtherBackend; |
@@ -758,7 +784,7 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok |
758 | 784 | * @return JSONResponse |
759 | 785 | */ |
760 | 786 | private function getBackchannelLogoutErrorResponse( |
761 | | - string $error, string $description, array $throttleMetadata = [], |
| 787 | + string $error, string $description, array $throttleMetadata = [], ?bool $throttle = null, |
762 | 788 | ): JSONResponse { |
763 | 789 | $this->logger->debug('Backchannel logout error. ' . $error . ' ; ' . $description); |
764 | 790 | return new JSONResponse( |
|
0 commit comments