diff --git a/config.inc.php.dist b/config.inc.php.dist index 19e91a0..4cb6234 100644 --- a/config.inc.php.dist +++ b/config.inc.php.dist @@ -44,3 +44,5 @@ $config['oidc_field_server'] = 'imap_server'; // Any errors will be reported as $ERROR $config['oidc_login_page'] = ''; +// Automatically redirect on login page +$config['oidc_auto_redirect'] = false; \ No newline at end of file diff --git a/roundcube_oidc.php b/roundcube_oidc.php index 9f415fa..54e2e09 100644 --- a/roundcube_oidc.php +++ b/roundcube_oidc.php @@ -23,6 +23,7 @@ function init() { $this->load_config('config.inc.php.dist'); $this->load_config('config.inc.php'); $this->add_hook('template_object_loginform', array($this, 'loginform')); + $this->add_hook('logout_after', array($this, 'logout_after')); } function altReturn($ERROR) { @@ -39,14 +40,42 @@ function altReturn($ERROR) { } } + function logout_after() { + $RCMAIL = rcmail::get_instance(); + + // OIDC login was not used + if (!$_COOKIE['roundcube_oidc_login_hint']) + return; + + $oidc = new OpenIDConnectClient( + $RCMAIL->config->get('oidc_url'), + $RCMAIL->config->get('oidc_client'), + $RCMAIL->config->get('oidc_secret') + ); + + rcube_utils::setcookie('roundcube_oidc_login_hint', ''); + + // TODO: We could save idToken during login and use it here + $oidc->signOut(null, null); + } + public function loginform($content) { - // Add the login link - $content['content'] .= "

Login with OIDC

"; + // Get mail object + $RCMAIL = rcmail::get_instance(); + $auto_redirect = $RCMAIL->config->get('oidc_auto_redirect'); - // Check if we are starting or resuming oidc auth - if (!isset($_GET['code']) && !isset($_GET['oidc'])) { - $this->altReturn(null); - return $content; + if ($auto_redirect === true) { + $content['content'] = ''; + } + else { + // Add the login link + $content['content'] .= "

Login with OIDC

"; + + // Check if we are starting or resuming oidc auth + if (!isset($_GET['code']) && !isset($_GET['oidc'])) { + $this->altReturn(null); + return $content; + } } // Define error for alt login @@ -65,12 +94,19 @@ public function loginform($content) { $RCMAIL->config->get('oidc_client'), $RCMAIL->config->get('oidc_secret') ); - $oidc->addScope($RCMAIL->config->get('oidc_scope')); + $oidc->setRedirectURL($oidc->getRedirectURL() . '/'); + $oidc->addScope(explode(' ', $RCMAIL->config->get('oidc_scope'))); + + // Try to decrypt login_hint cookie + $login_hint = $RCMAIL->decrypt($_COOKIE['roundcube_oidc_login_hint']); + if ($login_hint) { + $oidc->addAuthParam(['login_hint' => $login_hint]); + } // Get user information try { $oidc->authenticate(); - $user = json_decode(json_encode($oidc->requestUserInfo()), true); + $user = json_decode(json_encode($oidc->getVerifiedClaims()), true); } catch (\Exception $e) { $ERROR = 'OIDC Authentication Failed
' . $e->getMessage(); $content['content'] .= "

$ERROR

"; @@ -80,9 +116,16 @@ public function loginform($content) { // Parse fields $uid = $user[$RCMAIL->config->get('oidc_field_uid')]; + $mail = $uid; $password = get($user[$RCMAIL->config->get('oidc_field_password')], $password); $imap_server = get($user[$RCMAIL->config->get('oidc_field_server')], $imap_server); + if (!$uid) { + $content['content'] .= "

User ID (mail) not provided.

"; + $this->altReturn($ERROR); + return $content; + } + // Check if master user is present $master = $RCMAIL->config->get('oidc_config_master_user'); if ($master != '') { @@ -99,6 +142,22 @@ public function loginform($content) { // Login to IMAP if ($RCMAIL->login($auth['user'], $password, $imap_server, $auth['cookiecheck'])) { + rcube_utils::setcookie('roundcube_oidc_login_hint', $RCMAIL->encrypt($mail)); + + // Update user profile + $user_identity = $RCMAIL->user->get_identity(); + $iid = $user_identity['identity_id']; + if (isset($iid) && (!$user_identity['name'] || $user_identity['email'] == $uid)) { + $data = array('email' => $mail); + + $claim_name = $user['name']; + if (isset($claim_name)) { + $data['name'] = $claim_name; + } + + $RCMAIL->user->update_identity($iid, $data); + } + $RCMAIL->session->remove('temp'); $RCMAIL->session->regenerate_id(false); $RCMAIL->session->set_auth_cookie(); @@ -111,13 +170,6 @@ public function loginform($content) { $redir = $RCMAIL->plugins->exec_hook('login_after', $query + array('_task' => 'mail')); $RCMAIL->session->set_auth_cookie(); - // Update user profile - $iid = $RCMAIL->user->get_identity()['identity_id']; - $claim_name = $user['name']; - if (isset($iid) && isset($claim_name)) { - $RCMAIL->user->update_identity($iid, array('name' => $claim_name)); - } - $OUTPUT->redirect($redir, 0, true); } else { $ERROR = 'IMAP authentication failed!';