Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config.inc.php.dist
Original file line number Diff line number Diff line change
Expand Up @@ -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;
82 changes: 67 additions & 15 deletions roundcube_oidc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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'] .= "<p> <a href='?oidc=1'> Login with OIDC </a> </p>";
// 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'] .= "<p> <a href='?oidc=1'> Login with OIDC </a> </p>";

// 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
Expand All @@ -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 <br/>' . $e->getMessage();
$content['content'] .= "<p class='alert-danger'> $ERROR </p>";
Expand All @@ -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'] .= "<p class='alert-danger'> User ID (mail) not provided. </p>";
$this->altReturn($ERROR);
return $content;
}

// Check if master user is present
$master = $RCMAIL->config->get('oidc_config_master_user');
if ($master != '') {
Expand All @@ -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();
Expand All @@ -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!';
Expand Down