mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
WIP oauth mail-authentication updates refresh-token and redirects to IdP, if refresh-token is expired
This commit is contained in:
parent
fa71d9d450
commit
1c40074331
@ -1263,7 +1263,7 @@ class admin_mail
|
||||
else
|
||||
{
|
||||
try {
|
||||
if (empty($content['acc_imap_username']) && ($oauth = OpenIDConnectClient::providerByDomain(
|
||||
if (($oauth = OpenIDConnectClient::providerByDomain(
|
||||
$content['acc_oauth_username'] ?? $content['acc_imap_username'] ?? $content['ident_email'], $content['acc_imap_host'])))
|
||||
{
|
||||
$content += self::oauth2content($oauth);
|
||||
@ -1541,17 +1541,21 @@ class admin_mail
|
||||
$oidc->addScope($content['acc_oauth_scopes']);
|
||||
}
|
||||
|
||||
if (!empty($content['acc_oauth_access_token']) || !empty($content['acc_oauth_refresh_token']))
|
||||
if (!empty($content['acc_oauth_access_token']) ||
|
||||
!empty($content['acc_oauth_refresh_token']) && $content['acc_oauth_refresh_token'] !== Mail\Credentials::UNAVAILABLE)
|
||||
{
|
||||
if (empty($content['acc_oauth_access_token']))
|
||||
{
|
||||
$content['acc_oauth_access_token'] = $oidc->refreshToken($content['acc_oauth_refresh_token']);
|
||||
$content['acc_oauth_access_token'] = $oidc->refreshToken($content['acc_oauth_refresh_token'])->access_token;
|
||||
}
|
||||
if ($smtp)
|
||||
if (!empty($content['acc_oauth_access_token']))
|
||||
{
|
||||
return new Horde_Smtp_Password_Xoauth2($content['acc_oauth_username'] ?? $content['acc_smtp_username'], $content['acc_oauth_access_token']);
|
||||
if ($smtp)
|
||||
{
|
||||
return new Horde_Smtp_Password_Xoauth2($content['acc_oauth_username'] ?? $content['acc_smtp_username'], $content['acc_oauth_access_token']);
|
||||
}
|
||||
return new Horde_Imap_Client_Password_Xoauth2($content['acc_oauth_username'] ?? $content['acc_imap_username'], $content['acc_oauth_access_token']);
|
||||
}
|
||||
return new Horde_Imap_Client_Password_Xoauth2($content['acc_oauth_username'] ?? $content['acc_imap_username'], $content['acc_oauth_access_token']);
|
||||
}
|
||||
// Run OAuth authentication, will NOT return, but call success or failure callbacks below
|
||||
$oidc->authenticateThen(__CLASS__.'::oauthAuthenticated', [$content], __CLASS__.'::oauthFailure', [$content]);
|
||||
|
@ -244,7 +244,7 @@ class Credentials
|
||||
{
|
||||
unset($results[$prefix.'password']);
|
||||
$results[$prefix.'refresh_token'] = self::UNAVAILABLE; // no need to make it available
|
||||
$results[$prefix.'access_token'] = self::getAccessToken($row['cred_username'], $password, $mailserver);
|
||||
$results[$prefix.'access_token'] = self::getAccessToken($row['cred_username'], $password, $mailserver, $acc_id, $row['account_id']);
|
||||
// if no extra imap&smtp username set, set the oauth one
|
||||
foreach(['acc_imap_', 'acc_smtp_'] as $pre)
|
||||
{
|
||||
@ -267,11 +267,13 @@ class Credentials
|
||||
* @param string $username
|
||||
* @param string $refresh_token
|
||||
* @param string|null $mailserver mailserver to detect oauth hosts
|
||||
* @param ?int $acc_id to store updated refresh-token
|
||||
* @param ?int $account_id ----------- " ------------
|
||||
* @return string|null
|
||||
*/
|
||||
static protected function getAccessToken($username, $refresh_token, $mailserver=null)
|
||||
static protected function getAccessToken(string $username, string $refresh_token, string $mailserver=null, int $acc_id=null, int $account_id=null)
|
||||
{
|
||||
return Api\Cache::getInstance(__CLASS__, 'access-token-'.$username.'-'.md5($refresh_token), static function() use ($username, $refresh_token, $mailserver)
|
||||
return Api\Cache::getInstance(__CLASS__, 'access-token-'.$username.'-'.md5($refresh_token), static function() use ($acc_id, $account_id, $username, $refresh_token, $mailserver)
|
||||
{
|
||||
if (!($oidc = Api\Auth\OpenIDConnectClient::byDomain($username, $mailserver)))
|
||||
{
|
||||
@ -280,13 +282,24 @@ class Credentials
|
||||
try
|
||||
{
|
||||
$token = $oidc->refreshToken($refresh_token);
|
||||
return $token->access_token;
|
||||
// if we got a new refresh-token, store it
|
||||
if (isset($token->refresh_token) && $refresh_token !== $token->refresh_token && $acc_id > 0 && $account_id > 0)
|
||||
{
|
||||
self::write($acc_id, $username, $token->refresh_token, self::OAUTH_REFRESH_TOKEN, $account_id);
|
||||
//error_log("Mail\\Credentials::getAccessToken($acc_id, $account_id, '$username', ..., ".json_encode($mailserver).") stored new refresh-token: ".json_encode($token));
|
||||
}
|
||||
if (isset($token->access_token))
|
||||
{
|
||||
return $token->access_token;
|
||||
}
|
||||
// we did NOT get an access-token
|
||||
error_log("Mail\\Credentials::getAccessToken($acc_id, $account_id, '$username', '$refresh_token', ".json_encode($mailserver).") got NO access-token: ".json_encode($token));
|
||||
}
|
||||
catch (OpenIDConnectClientException $e) {
|
||||
_egw_log_exception($e);
|
||||
}
|
||||
return null;
|
||||
}, [], 3500); // access-token have a livetime of 3600s, give it some margin
|
||||
}, [], 3500); // access-token have a lifetime of 3600s, give it some margin
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -599,7 +599,7 @@ class mail_ui
|
||||
catch (Exception $e)
|
||||
{
|
||||
// do not exit here. mail-tree should be build. if we exit here, we never get there.
|
||||
error_log(__METHOD__.__LINE__.$e->getMessage().($e->details?', '.$e->details:'').' Menuaction:'.$_GET['menuaction'].'.'.function_backtrace());
|
||||
_egw_log_exception($e);
|
||||
if (isset($this->mail_bo))
|
||||
{
|
||||
if (empty($etpl))
|
||||
|
Loading…
Reference in New Issue
Block a user