From e1b3c35b9680a5c6851d806c8926b0cd68a3f461 Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Tue, 17 Jan 2023 14:44:34 -0500
Subject: [PATCH 01/10] Issue #3327237 by colan: Cloned the Okta client plugin
 for use by Auth0.

---
 .../OpenIDConnectAuth0Client.php              | 85 +++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php

diff --git a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
new file mode 100644
index 0000000..68ad0bb
--- /dev/null
+++ b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Drupal\openid_connect\Plugin\OpenIDConnectClient;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\openid_connect\Plugin\OpenIDConnectClientBase;
+
+/**
+ * Okta OpenID Connect client.
+ *
+ * Implements OpenID Connect Client plugin for Okta.
+ *
+ * @OpenIDConnectClient(
+ *   id = "okta",
+ *   label = @Translation("Okta")
+ * )
+ */
+class OpenIDConnectOktaClient extends OpenIDConnectClientBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration(): array {
+    return [
+      'okta_domain' => '',
+      'scopes' => ['openid', 'email'],
+    ] + parent::defaultConfiguration();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
+    $form['okta_domain'] = [
+      '#title' => $this->t('Okta domain'),
+      '#type' => 'textfield',
+      '#default_value' => $this->configuration['okta_domain'],
+    ];
+
+    $form['scopes'] = [
+      '#title' => $this->t('Scopes'),
+      '#type' => 'textfield',
+      '#description' => $this->t('Custom scopes, separated by spaces, for example: openid email'),
+      '#default_value' => implode(' ', $this->configuration['scopes']),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getEndpoints(): array {
+    // From https://developer.okta.com/docs/reference/api/oidc and
+    // https://${yourOktaDomain}/.well-known/openid-configuration
+    return [
+      'authorization' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/authorize',
+      'token' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/token',
+      'userinfo' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/userinfo',
+      'end_session' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/logout',
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+    $configuration = $form_state->getValues();
+    if (!empty($configuration['scopes'])) {
+      $this->setConfiguration(['scopes' => explode(' ', $configuration['scopes'])]);
+    }
+
+    parent::submitConfigurationForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getClientScopes(): ?array {
+    return $this->configuration['scopes'];
+  }
+
+}
-- 
GitLab


From f3e086b7d16d4c16e317a83737197fab11a467ea Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Tue, 17 Jan 2023 14:53:05 -0500
Subject: [PATCH 02/10] Issue #3327237 by colan: Replaced Okta references with
 Auth0.

---
 .../OpenIDConnectAuth0Client.php              | 30 +++++++++----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
index 68ad0bb..cac58db 100644
--- a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
+++ b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
@@ -6,23 +6,23 @@ use Drupal\Core\Form\FormStateInterface;
 use Drupal\openid_connect\Plugin\OpenIDConnectClientBase;
 
 /**
- * Okta OpenID Connect client.
+ * Auth0 OpenID Connect client.
  *
- * Implements OpenID Connect Client plugin for Okta.
+ * Implements OpenID Connect Client plugin for Auth0.
  *
  * @OpenIDConnectClient(
- *   id = "okta",
- *   label = @Translation("Okta")
+ *   id = "auth0",
+ *   label = @Translation("Auth0")
  * )
  */
-class OpenIDConnectOktaClient extends OpenIDConnectClientBase {
+class OpenIDConnectAuth0Client extends OpenIDConnectClientBase {
 
   /**
    * {@inheritdoc}
    */
   public function defaultConfiguration(): array {
     return [
-      'okta_domain' => '',
+      'auth0_domain' => '',
       'scopes' => ['openid', 'email'],
     ] + parent::defaultConfiguration();
   }
@@ -33,10 +33,10 @@ class OpenIDConnectOktaClient extends OpenIDConnectClientBase {
   public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
     $form = parent::buildConfigurationForm($form, $form_state);
 
-    $form['okta_domain'] = [
-      '#title' => $this->t('Okta domain'),
+    $form['auth0_domain'] = [
+      '#title' => $this->t('Auth0 domain'),
       '#type' => 'textfield',
-      '#default_value' => $this->configuration['okta_domain'],
+      '#default_value' => $this->configuration['auth0_domain'],
     ];
 
     $form['scopes'] = [
@@ -53,13 +53,13 @@ class OpenIDConnectOktaClient extends OpenIDConnectClientBase {
    * {@inheritdoc}
    */
   public function getEndpoints(): array {
-    // From https://developer.okta.com/docs/reference/api/oidc and
-    // https://${yourOktaDomain}/.well-known/openid-configuration
+    // From https://developer.auth0.com/docs/reference/api/oidc and
+    // https://${yourAuth0Domain}/.well-known/openid-configuration
     return [
-      'authorization' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/authorize',
-      'token' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/token',
-      'userinfo' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/userinfo',
-      'end_session' => 'https://' . $this->configuration['okta_domain'] . '/oauth2/v1/logout',
+      'authorization' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/authorize',
+      'token' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/token',
+      'userinfo' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/userinfo',
+      'end_session' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/logout',
     ];
   }
 
-- 
GitLab


From 71da7b73b2ab997a2898e7f1664d8a986a4ac8e3 Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Wed, 18 Jan 2023 11:10:10 -0500
Subject: [PATCH 03/10] Issue #3327237 by colan: Updated endpoint URLs.

---
 .../OpenIDConnectAuth0Client.php                 | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
index cac58db..866e3ec 100644
--- a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
+++ b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
@@ -51,15 +51,19 @@ class OpenIDConnectAuth0Client extends OpenIDConnectClientBase {
 
   /**
    * {@inheritdoc}
+   *
+   * @see https://${yourAuth0Domain}/.well-known/openid-configuration
    */
   public function getEndpoints(): array {
-    // From https://developer.auth0.com/docs/reference/api/oidc and
-    // https://${yourAuth0Domain}/.well-known/openid-configuration
     return [
-      'authorization' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/authorize',
-      'token' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/token',
-      'userinfo' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/userinfo',
-      'end_session' => 'https://' . $this->configuration['auth0_domain'] . '/oauth2/v1/logout',
+      # https://auth0.com/docs/api/authentication#authorize-application
+      'authorization' => 'https://' . $this->configuration['auth0_domain'] . '/authorize',
+      # https://auth0.com/docs/api/authentication#get-code-or-link
+      'token' => 'https://' . $this->configuration['auth0_domain'] . '/oauth/token',
+      # https://auth0.com/docs/api/authentication#get-user-info
+      'userinfo' => 'https://' . $this->configuration['auth0_domain'] . '/userinfo',
+      # https://auth0.com/docs/api/authentication#logout
+      'end_session' => 'https://' . $this->configuration['auth0_domain'] . '/v2/logout',
     ];
   }
 
-- 
GitLab


From e6ad49bf703f82f0c1a1c22def6e9612633ee1ab Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Wed, 25 Jan 2023 13:12:49 -0500
Subject: [PATCH 04/10] Issue #3327237 by colan: Added schema for Auth0 config.

---
 config/schema/openid_connect.schema.yml | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/config/schema/openid_connect.schema.yml b/config/schema/openid_connect.schema.yml
index 4b93e0b..babf079 100644
--- a/config/schema/openid_connect.schema.yml
+++ b/config/schema/openid_connect.schema.yml
@@ -114,3 +114,17 @@ openid_connect.client.plugin.okta:
       label: 'Scopes'
       sequence:
         type: string
+
+openid_connect.client.plugin.auth0:
+  type: mapping
+  label: 'OpenID Connect Auth0 settings'
+  mapping:
+    <<: *base
+    okta_domain:
+      type: string
+      label: 'Okta domain'
+    scopes:
+      type: sequence
+      label: 'Scopes'
+      sequence:
+        type: string
-- 
GitLab


From ecb15fbe616b9eb5b73692f40c98ab034ef7fb08 Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Wed, 25 Jan 2023 13:14:15 -0500
Subject: [PATCH 05/10] Issue #3327237 by colan: Added Auth0 to the list of
 supported backends in in-line help.

---
 openid_connect.module | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/openid_connect.module b/openid_connect.module
index 6ec8f0f..89f47b1 100644
--- a/openid_connect.module
+++ b/openid_connect.module
@@ -30,7 +30,7 @@ function openid_connect_help($route_name, RouteMatchInterface $route_match) : st
       $output .= '<dt>' . t('Login to Drupal using OpenID Connect/OAuth2 providers') . '</dt>';
       $output .= '<dd>' . t('Drupal users can use external OpenID Connect authentication providers to register and login to the Drupal site.') . '</dd>';
       $output .= '<dt>' . t('Default providers') . '</dt>';
-      $output .= '<dd>' . t('The default clients provided by the module for Google, Facebook, Github, LinkedIn and Okta can be used out-of-the box.') . '</dd>';
+      $output .= '<dd>' . t('The default clients provided by the module for Google, Facebook, Github, LinkedIn, Auth0 and Okta can be used out-of-the box.') . '</dd>';
       $output .= '<dt>' . t('Custom OpenID Connect/OAuth2 providers') . '</dt>';
       $output .= '<dd>' . t('Easily add an own provider by using the provided Generic client, or use a custom provider client plugin.') . '</dd>';
       $output .= '<dt>' . t('Synchronize user properties/fields with OpenID Connect claims') . '</dt>';
-- 
GitLab


From f0755156322e3449d458767edffc7bbe16290097 Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Wed, 25 Jan 2023 13:16:08 -0500
Subject: [PATCH 06/10] Issue #3327237 by colan: Added alter method for the
 query.

---
 src/Controller/OpenIDConnectRedirectController.php |  1 +
 src/Plugin/OpenIDConnectClientBase.php             | 12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/src/Controller/OpenIDConnectRedirectController.php b/src/Controller/OpenIDConnectRedirectController.php
index 3f724e4..bbf19a6 100644
--- a/src/Controller/OpenIDConnectRedirectController.php
+++ b/src/Controller/OpenIDConnectRedirectController.php
@@ -445,6 +445,7 @@ class OpenIDConnectRedirectController implements ContainerInjectionInterface, Ac
               if ($redirect_logout_url) {
                 $url_options['query']['post_logout_redirect_uri'] = $redirect_logout_url->setAbsolute()->toString(TRUE)->getGeneratedUrl();
               }
+              $url_options['query'] = $entity->getPlugin()->alterLogoutRedirectionQuery($url_options['query']);
               $redirect = Url::fromUri($endpoints['end_session'], $url_options)->toString(TRUE);
               $response = new TrustedRedirectResponse($redirect->getGeneratedUrl());
               $response->addCacheableDependency($redirect);
diff --git a/src/Plugin/OpenIDConnectClientBase.php b/src/Plugin/OpenIDConnectClientBase.php
index 9ec17e0..64634db 100644
--- a/src/Plugin/OpenIDConnectClientBase.php
+++ b/src/Plugin/OpenIDConnectClientBase.php
@@ -453,4 +453,16 @@ abstract class OpenIDConnectClientBase extends PluginBase implements OpenIDConne
     return Url::fromRoute('openid_connect.redirect_controller_redirect', $route_parameters, $options);
   }
 
+  /**
+   * Allows for alterations to the logout redirection query.
+   *
+   * @param array $query
+   *   The query.
+   * @return array
+   *   The query, possibly with alterations.
+   */
+  public function alterLogoutRedirectionQuery(array $query): array {
+    return $query;
+  }
+
 }
-- 
GitLab


From df90d20ed6903698c3306f51b24c3385acb8305b Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Wed, 25 Jan 2023 13:17:06 -0500
Subject: [PATCH 07/10] Issue #3327237 by colan: Overrode the query alter
 method to do Auth0-specific stuff.

---
 .../OpenIDConnectClient/OpenIDConnectAuth0Client.php  | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
index 866e3ec..691b2aa 100644
--- a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
+++ b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
@@ -86,4 +86,15 @@ class OpenIDConnectAuth0Client extends OpenIDConnectClientBase {
     return $this->configuration['scopes'];
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function alterLogoutRedirectionQuery(array $query): array
+  {
+    $query['client_id'] = $this->configuration['client_id'];
+    $query['returnTo'] = $query['post_logout_redirect_uri'];
+    unset($query['post_logout_redirect_uri'], $query['id_token_hint']);
+    return $query;
+  }
+
 }
-- 
GitLab


From 999bba04df7db964ca649c201e095057a17ab720 Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Fri, 27 Jan 2023 12:36:28 -0500
Subject: [PATCH 08/10] Issue #3327237 by colan: Provide users with the reason
 why they can't log in if available.

---
 src/Controller/OpenIDConnectRedirectController.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Controller/OpenIDConnectRedirectController.php b/src/Controller/OpenIDConnectRedirectController.php
index bbf19a6..dd3b5df 100644
--- a/src/Controller/OpenIDConnectRedirectController.php
+++ b/src/Controller/OpenIDConnectRedirectController.php
@@ -281,11 +281,11 @@ class OpenIDConnectRedirectController implements ContainerInjectionInterface, Ac
         // Any other error should be logged. E.g. invalid scope.
         $variables = [
           '@error' => $request->get('error'),
-          '@details' => $request->get('error_description') ? $request->get('error_description') : $this->t('Unknown error.'),
+          '@details' => $request->get('error_description') ?: $this->t('Unknown error: Could not authenticate with @provider.', $provider_param),
         ];
         $message = 'Authorization failed: @error. Details: @details';
         $this->getLogger('openid_connect_' . $openid_connect_client->getPluginId())->error($message, $variables);
-        $this->messenger()->addError($this->t('Could not authenticate with @provider.', $provider_param));
+        $this->messenger()->addError($variables['@details']);
       }
     }
     else {
-- 
GitLab


From 644ff7b3d371f4432fc7a50f7f493633352d1d78 Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Fri, 27 Jan 2023 12:37:46 -0500
Subject: [PATCH 09/10] Issue #3327237 by colan: Tell admins how to enforce
 e-mail verification at the IDP.

---
 .../OpenIDConnectClient/OpenIDConnectAuth0Client.php | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
index 691b2aa..53a130b 100644
--- a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
+++ b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
@@ -39,6 +39,18 @@ class OpenIDConnectAuth0Client extends OpenIDConnectClientBase {
       '#default_value' => $this->configuration['auth0_domain'],
     ];
 
+    $form['email_verification'] = [
+      '#title' => $this->t('E-mail verification'),
+      '#type' => 'item',
+      '#description' => $this->t(
+        'By default, requiring mandatory e-mail verification for logins as configured at <em>Administration ->
+        Configuration -> People -> Registration and Cancellation</em> is not enforced with this login method.  To enable
+        it in your Auth0 tenant, navigate to Actions -> Flows -> Login, add a custom action with the code block at
+        <a href="https://community.auth0.com/t/user-can-sign-in-before-email-confirmation/62730/3">Auth0 Community: User
+         can sign in before email confirmation</a>, and then place it between <em>Start</em> and <em>Complete</em>.'
+      ),
+    ];
+
     $form['scopes'] = [
       '#title' => $this->t('Scopes'),
       '#type' => 'textfield',
-- 
GitLab


From 9a818668d6447823994d5f0b7fe4135d01e8dfa6 Mon Sep 17 00:00:00 2001
From: Colan Schwartz <colan@58704.no-reply.drupal.org>
Date: Wed, 29 Mar 2023 12:36:30 -0400
Subject: [PATCH 10/10] Issue #3327237 by colan: Use the federated-logout URL
 if requested by admins.

That is, log out of the IDP as well as Drupal.
---
 .../OpenIDConnectAuth0Client.php                | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
index 53a130b..0caf304 100644
--- a/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
+++ b/src/Plugin/OpenIDConnectClient/OpenIDConnectAuth0Client.php
@@ -75,10 +75,25 @@ class OpenIDConnectAuth0Client extends OpenIDConnectClientBase {
       # https://auth0.com/docs/api/authentication#get-user-info
       'userinfo' => 'https://' . $this->configuration['auth0_domain'] . '/userinfo',
       # https://auth0.com/docs/api/authentication#logout
-      'end_session' => 'https://' . $this->configuration['auth0_domain'] . '/v2/logout',
+      'end_session' => 'https://' . $this->configuration['auth0_domain'] . $this->getLogoutPath(),
     ];
   }
 
+  /**
+   * Fetches the logout path at the IDP.
+   *
+   * @return string
+   *
+   * @see https://auth0.com/docs/authenticate/login/logout/log-users-out-of-idps
+   */
+  protected function getLogoutPath(): string {
+    $base_logout_path = '/v2/logout';
+    if (\Drupal::configFactory()->get('openid_connect.settings')->get('end_session_enabled')) {
+      return $base_logout_path . '?federated';
+    }
+    return $base_logout_path;
+  }
+
   /**
    * {@inheritdoc}
    */
-- 
GitLab