custom/static-plugins/WabsAuth/src/Controller/OAuthController.php line 219

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace WabsAuth\Controller;
  3. use Exception;
  4. use Shopware\Core\Checkout\Customer\Event\CustomerLoginEvent;
  5. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLogoutRoute;
  6. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  7. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  8. use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
  9. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextRestorer;
  10. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  11. use Shopware\Core\System\SystemConfig\SystemConfigService;
  12. use Shopware\Storefront\Controller\StorefrontController;
  13. use Shopware\Storefront\Framework\Captcha\Annotation\Captcha;
  14. use Symfony\Component\HttpFoundation\RedirectResponse;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\HttpFoundation\Session\Session;
  18. use Symfony\Component\Routing\Annotation\Route;
  19. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  20. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  21. use WabsAuth\Helper\AuthHelper;
  22. use WabsAuth\Helper\DebugHelper;
  23. /**
  24.  * @RouteScope(scopes={"storefront"})
  25.  */
  26. class OAuthController extends StorefrontController
  27. {
  28.     /**
  29.      * @var Session
  30.      */
  31.     private $session;
  32.     /**
  33.      * @var EventDispatcherInterface
  34.      */
  35.     private $eventDispatcher;
  36.     /**
  37.      * @var AuthHelper
  38.      */
  39.     private $authHelper;
  40.     /**
  41.      * @var SalesChannelContextRestorer
  42.      */
  43.     private $contextRestorer;
  44.     /**
  45.      * @var DebugHelper
  46.      */
  47.     private $logger;
  48.     /**
  49.      * @var SystemConfigService
  50.      */
  51.     private $systemConfig;
  52.     /**
  53.      * @var AbstractLogoutRoute
  54.      */
  55.     private $logoutRoute;
  56.     /**
  57.      * OAuthController constructor.
  58.      * @param Session $session
  59.      * @param SalesChannelContextRestorer $contextRestorer
  60.      * @param EventDispatcherInterface $eventDispatcher
  61.      * @param AuthHelper $authHelper
  62.      * @param SystemConfigService $systemConfig
  63.      * @param AbstractLogoutRoute $logoutRoute
  64.      * @param DebugHelper $logger
  65.      */
  66.     public function __construct(
  67.         Session $session,
  68.         SalesChannelContextRestorer $contextRestorer,
  69.         EventDispatcherInterface $eventDispatcher,
  70.         AuthHelper $authHelper,
  71.         SystemConfigService $systemConfig,
  72.         AbstractLogoutRoute $logoutRoute,
  73.         DebugHelper $logger
  74.     ) {
  75.         $this->session $session;
  76.         $this->eventDispatcher $eventDispatcher;
  77.         $this->authHelper $authHelper;
  78.         $this->contextRestorer $contextRestorer;
  79.         $this->logger $logger;
  80.         $this->systemConfig $systemConfig;
  81.         $this->logoutRoute $logoutRoute;
  82.     }
  83.     /**
  84.      * @Route("/account/oauth/callback", name="frontend.account.oauth.callback", options={"seo"="false"}, methods={"GET"})
  85.      */
  86.     public function callback(Request $requestSalesChannelContext $context): Response
  87.     {
  88.         $receivedValidationCode $request->query->get('code');
  89.         $receivedState $request->query->get('state');
  90.         $redirectRoute $this->session->get('oauth_redirect_to');
  91.         $responseType $this->session->get('oauth_reponse_type');
  92.         $currentState $this->session->get('oauthState');
  93.         $this->session->remove('oauthState');
  94.         $this->session->remove('oauth_redirect_to');
  95.         $this->session->remove('oauth_reponse_type');
  96.         $this->logger->debug('OAuthController | Callback Function Begin.');
  97.         if (!isset($currentState)) {
  98.             $this->logger->debug('OAuthController | No currentState was set.');
  99.             if( $redirectRoute ) {
  100.                 return $this->redirect($redirectRoute . (preg_match("/\?/"$redirectRoute) ? '&' '?') . http_build_query(['error' => 'No state']) );
  101.             } else {
  102.                 return $this->redirectToRoute('frontend.account.login.page');
  103.             }
  104.         }
  105.         if (!isset($receivedState) || $currentState != $receivedState) {
  106.             $this->logger->debug('OAuthController | The current state and the received state do not match.');
  107.             if( $redirectRoute ) {
  108.                 return $this->redirect($redirectRoute . (preg_match("/\?/"$redirectRoute) ? '&' '?') . http_build_query(['error' => 'State does not match']) );
  109.             } else {
  110.                 $this->addFlash('danger''Ihr Authentifizierungsstatus stimmt nicht mit dem gelieferten Status überein!');
  111.                 return $this->redirectToRoute('frontend.home.page');
  112.             }
  113.         }
  114.         $provider $this->authHelper->getProvider();
  115.         try {
  116.             // Make the token request
  117.             $this->logger->debug('OAuthController | Try to get Token.');
  118.             $accessToken $provider->getAccessToken('authorization_code', [
  119.                 'code' => $receivedValidationCode
  120.             ]);
  121.             $this->logger->debug('OAuthController | Token success: ' json_encode($accessToken));
  122.             $this->logger->debug('OAuthController | Try to get owner data.');
  123.             $owner $provider->getResourceOwner($accessToken);
  124.             $ownerData $owner->toArray();
  125.             $this->logger->debug('OAuthController | OwnerData: ' json_encode($ownerData));
  126.             // Make user register if not already registered
  127.             // Save users API ID to check for existence
  128.             $customer $this->authHelper->getCustomer($ownerData$accessToken->getToken(), $context);
  129.             if (!$customer) {
  130.                 $this->logger->debug('OAuthController | No customer returned.');
  131.                 if( $redirectRoute ) {
  132.                     return $this->redirect($redirectRoute . (preg_match("/\?/"$redirectRoute) ? '&' '?') . http_build_query(['error' => 'No customer']) );
  133.                 } else {
  134.                     $this->addFlash('danger',
  135.                         'Wir konnten Sie leider nicht einloggen. Bitte versuchen Sie es zu einem späteren Zeitpunkt erneut.');
  136.                     return $this->redirectToRoute('frontend.home.page');
  137.                 }
  138.             }
  139.             $this->session->set('oauth_access_token'$accessToken);
  140.             $this->session->set('oauth_data'$ownerData);
  141.             $context $this->contextRestorer->restore($customer->getId(), $context);
  142.             $newToken $context->getToken();
  143.             // Customer is now logged in and has the default channel group!
  144.             $event = new CustomerLoginEvent($context$customer$newToken);
  145.             $this->eventDispatcher->dispatch($event);
  146.             $this->logger->debug('OAuthController | Callback Function End.');
  147.             if ($redirectRoute) {
  148.                 return $this->redirect($redirectRoute . ( $responseType === 'code' ? (preg_match("/\?/"$redirectRoute) ? '&' '?') . http_build_query(['code' => $newToken]) : '' ) );
  149.             }
  150.             if (!($customer->getGroup()->getName() != 'GC')) {
  151.                 $this->addFlash('success''Login erfolgreich!');
  152.             }
  153.             return new RedirectResponse(
  154.                 $this->generateUrl('frontend.home.page', ( $responseType === 'code' ? ['code' => $newToken] : [] )),
  155.                 302,
  156.                 ['Cache-Control' => 'no-cache']);
  157.         } catch (Exception $e) {
  158.             $this->logger->error('[OAuth] Login: ' $e->getMessage());
  159.             $this->logger->error('[OAuth] Login: ' $e->getTraceAsString());
  160.             $request->getSession()->invalidate();
  161.             $this->logger->debug('OAuthController | Callback Function End Exception.');
  162.             if( $redirectRoute ) {
  163.                 return $this->redirect($redirectRoute . (preg_match("/\?/"$redirectRoute) ? '&' '?') . http_build_query(['error' => $e->getMessage()]) );
  164.             } else {
  165.                 $this->addFlash(
  166.                     'danger',
  167.                     'Wir konnten Sie leider nicht einloggen. Bitte versuchen Sie es zu einem späteren Zeitpunkt erneut. Bitte prüfen Sie auch die Vollständigkeit Ihrer Daten Ihres IGM-Accounts.'
  168.                 );
  169.                 return $this->redirectToRoute('frontend.home.page');
  170.             }
  171.         }
  172.     }
  173.     /**
  174.      * @Route("/account/oauth/redirect", name="frontend.account.oauth.redirect", options={"seo"="false"}, methods={"GET"})
  175.      */
  176.     public function oAuthRedirect(Request $requestSalesChannelContext $context)
  177.     {
  178.         $provider $this->authHelper->getProvider();
  179.         // First get URL to generate the state and then save the state to the session
  180.         $url $provider->getAuthorizationUrl();
  181.         $this->session->set('oauthState'$provider->getState());
  182.         if( $request->query->get('response_type')) {
  183.             $this->session->set('oauth_reponse_type'$request->query->get('response_type') );
  184.         }
  185.         if( $request->query->get('redirect_to')) {
  186.             $this->session->set('oauth_redirect_to'$request->query->get('redirect_to') );
  187.         }
  188.         if( $request->query->get('auto_group') ) {
  189.             $this->session->set('oauth_auto_group'$request->query->get('auto_group') );
  190.         }
  191.         if( $request->query->get('force_auto_group') ) {
  192.             $this->session->set('oauth_force_auto_group', (bool)$request->query->get('force_auto_group')  );
  193.         }
  194.         return $this->redirect($url);
  195.     }
  196.     /**
  197.      * @Route("/account/register", name="frontend.account.register.save", methods={"POST"})
  198.      * @Captcha
  199.      */
  200.     public function register(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  201.     {
  202.         // we don't let ppl register normally! so we don't need this route
  203.         return $this->redirectToRoute('frontend.home.page');
  204.     }
  205.     /**
  206.      * @Route("/account/profile", name="frontend.account.profile.save", methods={"POST"})
  207.      */
  208.     public function saveProfile(RequestDataBag $dataSalesChannelContext $context): Response
  209.     {
  210.         // buttons already removed. there should be no possible way to change profile information from controller
  211.         return $this->redirectToRoute('frontend.home.page');
  212.     }
  213.     /**
  214.      * Route to change
  215.      *
  216.      * @Route("/account/group/change", name="frontend.account.group.change", methods={"GET"})
  217.      */
  218.     public function changeGroup(Request $requestSalesChannelContext $context): Response
  219.     {
  220.         try {
  221.             $this->logger->debug('OAuthController | ChangeGroup Function Begin.');
  222.             $redirectRoute $this->session->get('oauth_redirect_to');
  223.             // Get selected group and load customer group (not yet loaded by default)
  224.             $selectedGroup $request->query->get('group-selection');
  225.             $customer $this->authHelper->loadCustomerGroupToCustomer($context->getCustomer(), $context);
  226.             // Check if user is allowed to change group and to use the transmitted group
  227.             if ($this->authHelper->checkAllowedGroups($selectedGroup$customer)) {
  228.                 $customFields $customer->getCustomFields();
  229.                 // Check if we have all needed Data in customer->customFields
  230.                 if (!array_key_exists('igm_session_token'$customFields) ||
  231.                     !array_key_exists('igm_groups'$customFields) ||
  232.                     !array_key_exists('access_token'$customFields) ||
  233.                     !array_key_exists('igm_account_data'$customFields)) {
  234.                     $this->logger->debug('OAuthController | ChangeGroup | Array keys missing from customFields: ' $customFields);
  235.                     throw new Exception('Not enough data saved to the customer.');
  236.                 }
  237.                 // Replicate the needed data array for the update process
  238.                 $data = [
  239.                     'igm_session_token' => $customFields['igm_session_token'],
  240.                     'igm_account_data' => $customFields['igm_account_data']
  241.                 ];
  242.                 $igmGroups $customFields['igm_groups'];
  243.                 $accessToken $customFields['access_token'];
  244.                 // Check User group
  245.                 $customerGroupId $this->authHelper->loadCustomerGroupId($selectedGroup$context);
  246.                 if (empty($customerGroupId)) {
  247.                     $this->logger->debug('AuthHelper | No Valid Group for customer with number: ' $customer->getCustomerNumber());
  248.                     throw new Exception('No valid Group for customer.');
  249.                 }
  250.                 // User is allowed, so try to set the group
  251.                 $this->authHelper->updateCustomer($customer$data$customerGroupId$igmGroups$accessToken,
  252.                     $context);
  253.                 if ($this->authHelper->organizationAddressFlag) {
  254.                     return $this->redirectToRoute('frontend.account.logout.page', ['organizationAddressFlag' => true]);
  255.                 }
  256.                 $this->logger->debug('OAuthController | ChangeGroup Function End.');
  257.                 if ($redirectRoute) {
  258.                     return $this->redirect($redirectRoute);
  259.                 }
  260.                 return $this->redirectToRoute('frontend.home.page');
  261.             }
  262.         } catch (Exception $e) {
  263.             $this->logger->error('[OAuth] Login: ' $e->getMessage());
  264.             $this->logger->error('[OAuth] Login: ' $e->getTraceAsString());
  265.             $request->getSession()->invalidate();
  266.             $this->addFlash(
  267.                 'danger',
  268.                 'Wir konnten Sie leider nicht einloggen. Bitte versuchen Sie es zu einem späteren Zeitpunkt erneut. Bitte prüfen Sie auch die Vollständigkeit Ihrer Daten Ihres IGM-Accounts.'
  269.             );
  270.             $this->logger->debug('OAuthController | ChangeGroup Function Exception.');
  271.             return $this->redirectToRoute('frontend.home.page');
  272.         }
  273.         // User tried to login to a group that he has no permission for
  274.         // Might be wise to add logging for this kind of user, because they try to hack us...
  275.         $this->addFlash('error''Sie haben keine Berechtigung für diese Gruppe.');
  276.         $redirectRoute $this->session->get('oauth_redirect_to');
  277.         $this->logger->debug('OAuthController | ChangeGroup Function Error.');
  278.         return $this->redirectToRoute($redirectRoute ?? 'frontend.home.page');
  279.     }
  280.     /**
  281.      * @Route("/account/logout", name="frontend.account.logout.page", methods={"GET"})
  282.      */
  283.     public function logout(Request $requestSalesChannelContext $context): Response
  284.     {
  285.         $parameters = [];
  286.         $redirectTo $request->query->get('redirect_to') ? $request->query->get('redirect_to') : null;
  287.         if ($context->getCustomer() !== null) {
  288.             try {
  289.                 $this->logoutRoute->logout($context, new RequestDataBag());
  290.                 $salesChannelId $context->getSalesChannel()->getId();
  291.                 if ($request->hasSession() && $this->systemConfig->get(
  292.                         'core.loginRegistration.invalidateSessionOnLogOut',
  293.                         $salesChannelId)) {
  294.                     $request->getSession()->invalidate();
  295.                 }
  296.                 if (!$redirectTo) {
  297.                     if ($request->get('organizationAddressFlag')) {
  298.                         $this->addFlash('danger'$this->systemConfig->get('WabsAuth.config.invalidOrganizationAddressErrorMessage'));
  299.                     }
  300.                     $this->addFlash('success'$this->trans('account.logoutSucceeded'));
  301.                 }
  302.             } catch (ConstraintViolationException $formViolations) {
  303.                 $parameters = ['formViolations' => $formViolations];
  304.             }
  305.         }
  306.         if( $redirectTo $redirectTo .= (preg_match("/\?/"$redirectTo) ? '&' '?') . http_build_query($parameters);
  307.         /** Edit: Changed Redirect URL to KeyCloak Service if set*/
  308.         $logoutUrl $this->systemConfig->get('WabsAuth.config.urlLogout');
  309.         if (!$logoutUrl) {
  310.             if( $redirectTo ) {
  311.                 return $this->redirect($redirectTo);
  312.             } else {
  313.                 return $this->redirectToRoute('frontend.home.page'$parameters);
  314.             }
  315.         }
  316.         return $this->redirect($logoutUrl '?redirect_uri=' . ( $redirectTo $redirectTo $this->generateUrl('frontend.home.page',
  317.                 $parametersUrlGeneratorInterface::ABSOLUTE_URL)));
  318.         /** END EDIT */
  319.     }
  320. }