automatic login from, via 3rd party or deep link?

Created on 8 May 2024, about 1 year ago
Updated 19 August 2024, 11 months ago

Scenario:
- users logged in on IDP application
- openid connect installed properly in Drupal
- "login with X" button works fine

Current experience:
- When clicking link from IDP, have to click "login with X" manually in order to perform OpenID authentication.

Desired Experience:
- Automatically perform OpenID authentication when clicking a link from IDP application to Drupal.
ie auto-login with OpenID and proceed to the Drupal URL

Is this possible and if so how?

πŸ’¬ Support request
Status

Active

Version

1.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States AaronBauman Philadelphia

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @AaronBauman
  • πŸ‡ΊπŸ‡ΈUnited States AaronBauman Philadelphia

    Here's what I managed to put together.
    It's a controller for an "automated login" route - any auth requests directed to this URL will be redirected to ?destination, or a default page if ?destination is not given.
    Any anon requests directed to this URL will be redirected to Open ID login via the ::authorize method of the Open ID provider - in this case "generic"

    
    <?php
    
    namespace Drupal\example_module\Controller;
    
    use Drupal\Core\Controller\ControllerBase;
    use Drupal\Core\Routing\TrustedRedirectResponse;
    use Drupal\openid_connect\OpenIDConnectClaims;
    use Drupal\openid_connect\Plugin\OpenIDConnectClientManager;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Symfony\Component\HttpFoundation\RequestStack;
    
    /**
     * Returns responses for auto-login route.
     */
    final class AutoLoginController extends ControllerBase {
    
      /**
       * The controller constructor.
       */
      public function __construct(
        private readonly RequestStack $requestStack,
        private readonly OpenIDConnectClaims $claims,
        private readonly OpenIDConnectClientManager $pluginManager
      ) {}
    
      /**
       * {@inheritdoc}
       */
      public static function create(ContainerInterface $container): self {
        return new self(
          $container->get('request_stack'),
          $container->get('openid_connect.claims'),
          $container->get('plugin.manager.openid_connect_client')
        );
      }
    
      /**
       * Builds the response.
       */
      public function __invoke() {
        if ($this->currentUser()->isAuthenticated()) {
          $redirect = $this->requestStack->getCurrentRequest()->query->get('destination') ?? $this->getDefaultPage();
          return (new TrustedRedirectResponse($redirect))->addCacheableDependency($this->currentUser);
        }
        $this->saveDestination();
    
    /*** CHANGE openid_connect.settings.generic TO AS APPROPRIATE FOR YOUR OPEN ID PLUGIN ****/
        $configuration = $this->config('openid_connect.settings.generic')
          ->get('settings');
    /*****************************************************************************************/
    
        /** @var \Drupal\openid_connect\Plugin\OpenIDConnectClientInterface $client */
        $client = $this->pluginManager->createInstance(
          'generic',
          $configuration
        );
        $scopes = $this->claims->getScopes($client);
        $_SESSION['openid_connect_op'] = 'login';
        return $client->authorize($scopes);
      }
    
      /**
       * Helper.
       */
      protected function saveDestination() {
        // The destination could contain query parameters. Ensure that they are
        // preserved.
        $_SESSION['openid_connect_destination'] = [
          $this->requestStack->getCurrentRequest()->query->get('destination') ?? $this->getDefaultPage()
        ];
      }
    
      /**
       * Helper.
       */
      protected function getDefaultPage() {
        return '/example';
      }
    
    }
    
  • πŸ‡©πŸ‡°Denmark msno

    Hope you have a second to answer this.

    How do you get the openid_connect module to work with your controller? Besides the controller, what does one need to have in the example_module?

  • πŸ‡ΊπŸ‡ΈUnited States AaronBauman Philadelphia

    you need to hook this controller up to a route, e.g. via your example_module.routing.yml file

    for my use case, i used the path 'login' like so:

    example_module.auto_login:
      path: 'login'
      defaults:
        _title: 'Login'
        _controller: '\Drupal\example_module\Controller\AutoLoginController'
      requirements:
        _access: 'TRUE'
    

    Then, for a "deep link", just prefix any path with login?destination=

Production build 0.71.5 2024