diff --git a/includes/OpenIDConnectClientBase.class.php b/includes/OpenIDConnectClientBase.class.php index 8c54144..e050d1f 100644 --- a/includes/OpenIDConnectClientBase.class.php +++ b/includes/OpenIDConnectClientBase.class.php @@ -167,9 +167,12 @@ abstract class OpenIDConnectClientBase implements OpenIDConnectClientInterface { * expiracy of the id_token, re use the refresh_token value at any time with endSession, etc.. * still need to decide what is the best approach to store values, session var / system variables ? * using system variables - * @see openid_connect_admin_form_submit - * @see openid_connect_extras_user_logout - * @param $retrievedTokens array result from retrieveTokens + * + * @see openid_connect_admin_form_submit() + * @see openid_connect_extras_user_logout() + * + * @param $retrievedTokens + * Array result from retrieveTokens. */ private function processTokens($retrievedTokens) { $_SESSION['openid_connect_tokens'] = $retrievedTokens; diff --git a/openid_connect.api.php b/openid_connect.api.php index 5957c64..e64819c 100644 --- a/openid_connect.api.php +++ b/openid_connect.api.php @@ -10,6 +10,32 @@ * @{ */ +/** + * Perform an action before user is logged into Drupal. + * + * @param array $tokens + * ID token and access token that we received as a result of the OpenID + * Connect flow. + * @param object $account + * The user account if it exists, false if not. + * @param array $userinfo + * The user claims returned by the OpenID Connect provider. + * @param string $client_name + * The machine name of the OpenID Connect client plugin. + * + * @return bool + * TRUE if user should be logged into Drupal. FALSE if not. + */ +function hook_openid_connect_pre_login($tokens, $account, $userinfo, $client_name) { + $allowed_users = array('user1@example.com', 'user2@example.com'); + // Allow only specific users to log in. + if (in_array($userinfo['email'], $allowed_users)) { + return TRUE; + } + + // Block all others. + return FALSE; +} /** * Perform an action after a successful authorization. * diff --git a/openid_connect.module b/openid_connect.module index b434505..8cc4e4c 100644 --- a/openid_connect.module +++ b/openid_connect.module @@ -805,6 +805,14 @@ function openid_connect_complete_authorization($client, $tokens, &$destination) } $account = openid_connect_user_load_by_sub($sub, $client->getName()); + $results = module_invoke_all('openid_connect_pre_login', $tokens, $account, $userinfo, $client->getName()); + + // Deny access if any module returns FALSE. + if (in_array(FALSE, $results, TRUE)) { + watchdog('openid_connect', 'Login denied for @email via pre-login hook.', array('@email' => $userinfo['email']), WATCHDOG_ERROR); + return FALSE; + } + if ($account) { // An existing account was found. Save user claims. if (variable_get('openid_connect_always_save_userinfo', TRUE)) { @@ -877,6 +885,14 @@ function openid_connect_connect_current_user($client, $tokens) { } $account = openid_connect_user_load_by_sub($sub, $client->getName()); + $results = module_invoke_all('openid_connect_pre_login', $tokens, $account, $userinfo, $client->getName()); + + // Deny access if any module returns FALSE. + if (in_array(FALSE, $results, TRUE)) { + watchdog('openid_connect', 'Login denied for @email via pre-login hook.', array('@email' => $userinfo['email']), WATCHDOG_ERROR); + return FALSE; + } + if ($account && $account->uid !== $user->uid) { drupal_set_message(t('Another user is already connected to this @provider account.', $provider_param), 'error'); @@ -905,6 +921,11 @@ function openid_connect_connect_current_user($client, $tokens) { function openid_connect_user_logout($account) { global $user; + // Check if we're masquerading, if so don't do this. + if (isset($_SESSION['masquerade_user_logout']) || isset($_SESSION['masquerading'])) { + return; + } + // Check if user is external. $mapped_user = openid_connect_get_connected_accounts($account); @@ -922,9 +943,15 @@ function openid_connect_user_logout($account) { // Destroy Idp session if provider supports it. if (method_exists($client, 'endSession')) { // Keep tokens for later use. - $tokens = $_SESSION['openid_connect_tokens']; + $tokens = array(); + if (isset($_SESSION['openid_connect_tokens'])) { + $tokens = $_SESSION['openid_connect_tokens']; + } + session_destroy(); - $client->endSession($tokens['id_token'], url('', array('absolute' => TRUE))); + + $id_token = isset($tokens['id_token']) ? $tokens['id_token'] : NULL; + $client->endSession($id_token, url('', array('absolute' => TRUE))); } else { watchdog('openid_connect', '@provider plugin does not support log out. You are logged out of the site but not out of the OpenID Connect provider.', array('@provider' => $client->getLabel()), WATCHDOG_ERROR); diff --git a/plugins/openid_connect_client/generic/OpenIDConnectClientGeneric.class.php b/plugins/openid_connect_client/generic/OpenIDConnectClientGeneric.class.php index 6476928..3a0ff00 100644 --- a/plugins/openid_connect_client/generic/OpenIDConnectClientGeneric.class.php +++ b/plugins/openid_connect_client/generic/OpenIDConnectClientGeneric.class.php @@ -22,16 +22,19 @@ class OpenIDConnectClientGeneric extends OpenIDConnectClientBase { '#type' => 'textfield', '#default_value' => $this->getSetting('authorization_endpoint', $default_site . '/authorize'), ); + $form['token_endpoint'] = array( '#title' => t('Token endpoint'), '#type' => 'textfield', '#default_value' => $this->getSetting('token_endpoint', $default_site . '/token'), ); + $form['userinfo_endpoint'] = array( '#title' => t('UserInfo endpoint'), '#type' => 'textfield', '#default_value' => $this->getSetting('userinfo_endpoint', $default_site . '/UserInfo'), ); + $form['end_session_endpoint'] = array( '#title' => t('EndSession endpoint'), '#type' => 'textfield', @@ -54,15 +57,15 @@ class OpenIDConnectClientGeneric extends OpenIDConnectClientBase { } /** - * End User Session in IdP. - * - * @param string $id_token - * A NON expired id_token (RECOMMENDED). - * @param string $post_logout_redirect_url - * Logout url registered on the IdP. + * End User Session in IdP * * @see http://openid.net/specs/openid-connect-session-1_0-15.html * @see http://openid.net/specs/openid-connect-session-1_0-15.html#RPLogout + * + * @param $id_token + * A NON-expired id_token (RECOMMENDED) + * @param $post_logout_redirect_url + * Logout url registered on the IdP. */ public function endSession($id_token, $post_logout_redirect_url = '') { $endpoints = $this->getEndpoints();