mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 07:53:39 +01:00
* Mail: OAuth authentication for Microsoft (Office365, outlook.com, ...) and GMail
This commit is contained in:
parent
8a43d88ffe
commit
c49f7849bb
@ -1243,7 +1243,7 @@ class admin_mail
|
||||
$sel_options['acc_smtp_ssl'] = self::$ssl_types;
|
||||
|
||||
// admin access to account with no credentials available
|
||||
if ($this->is_admin && (empty($content['acc_imap_username']) || empty($content['acc_imap_host']) || $content['called_for']))
|
||||
if ($this->is_admin && (!empty($content['called_for']) || empty($content['acc_imap_host']) || $content['called_for']))
|
||||
{
|
||||
// can't connection to imap --> allow free entries in taglists
|
||||
foreach(array('acc_folder_sent', 'acc_folder_trash', 'acc_folder_draft', 'acc_folder_template', 'acc_folder_junk') as $folder)
|
||||
@ -1254,6 +1254,11 @@ class admin_mail
|
||||
else
|
||||
{
|
||||
try {
|
||||
if (empty($content['acc_imap_username']) && ($oauth = OpenIDConnectClient::providerByDomain(
|
||||
$content['acc_oauth_username'] ?? $content['acc_imap_username'] ?? $content['ident_email'], $content['acc_imap_host'])))
|
||||
{
|
||||
$content += self::oauth2content($oauth);
|
||||
}
|
||||
$sel_options['acc_folder_sent'] = $sel_options['acc_folder_trash'] =
|
||||
$sel_options['acc_folder_draft'] = $sel_options['acc_folder_template'] =
|
||||
$sel_options['acc_folder_junk'] = $sel_options['acc_folder_archive'] =
|
||||
@ -1482,9 +1487,10 @@ class admin_mail
|
||||
'timeout' => $timeout > 0 ? $timeout : Mail\Imap::getTimeOut(),
|
||||
'debug' => self::DEBUG_LOG,
|
||||
];
|
||||
if (!empty($content['acc_oauth_provider_url']))
|
||||
if (!empty($content['acc_oauth_provider_url']) || !empty($content['acc_oauth_access_token']))
|
||||
{
|
||||
$config['xoauth2_token'] = self::oauthToken($content);
|
||||
$config['username'] = $content['acc_oauth_username'] ?? $content['acc_imap_username'];
|
||||
if (empty($config['password'])) $config['password'] = '**oauth**'; // some password is required, even if not used
|
||||
}
|
||||
return new Horde_Imap_Client_Socket($config);
|
||||
@ -1495,28 +1501,36 @@ class admin_mail
|
||||
*/
|
||||
protected static function oauthToken(array &$content, bool $smtp=false)
|
||||
{
|
||||
if (empty($content['acc_oauth_client_secret']))
|
||||
if (empty($content['acc_oauth_access_token']))
|
||||
{
|
||||
throw new Exception(lang("No OAuth client secret for provider '%1'!", $content['acc_oauth_provider_url']));
|
||||
}
|
||||
$oidc = new OpenIDConnectClient($content['acc_oauth_provider_url'],
|
||||
$content['acc_oauth_client_id'], $content['acc_oauth_client_secret']);
|
||||
if (empty($content['acc_oauth_client_secret']) &&
|
||||
($oauth = OpenIDConnectClient::providerByDomain($content['acc_oauth_username'] ?? $content['acc_imap_username'] ?? $content['ident_email'], $content['acc_imap_host'])))
|
||||
{
|
||||
$content += self::oauth2content($oauth);
|
||||
}
|
||||
if (empty($content['acc_oauth_client_secret']))
|
||||
{
|
||||
throw new Exception(lang("No OAuth client secret for provider '%1'!", $content['acc_oauth_provider_url']));
|
||||
}
|
||||
$oidc = new OpenIDConnectClient($content['acc_oauth_provider_url'],
|
||||
$content['acc_oauth_client_id'], $content['acc_oauth_client_secret']);
|
||||
|
||||
// Office365 requires client-ID as appid GET parameter (https://github.com/jumbojett/OpenID-Connect-PHP/issues/190)
|
||||
if (!empty($content[OpenIDConnectClient::ADD_CLIENT_TO_WELL_KNOWN]))
|
||||
{
|
||||
$oidc->setWellKnownConfigParameters([$content[OpenIDConnectClient::ADD_CLIENT_TO_WELL_KNOWN] => $content['acc_oauth_client_id']]);
|
||||
}
|
||||
// Google requires access_type=offline&prompt=consent to return a refresh-token
|
||||
if (!empty($content[OpenIDConnectClient::ADD_AUTH_PARAM]))
|
||||
{
|
||||
$oidc->addAuthParam(str_replace('$username', $content['acc_oauth_username'] ?? $content['acc_imap_username'], $content[OpenIDConnectClient::ADD_AUTH_PARAM]));
|
||||
}
|
||||
// Office365 requires client-ID as appid GET parameter (https://github.com/jumbojett/OpenID-Connect-PHP/issues/190)
|
||||
if (!empty($content[OpenIDConnectClient::ADD_CLIENT_TO_WELL_KNOWN]))
|
||||
{
|
||||
$oidc->setWellKnownConfigParameters([$content[OpenIDConnectClient::ADD_CLIENT_TO_WELL_KNOWN] => $content['acc_oauth_client_id']]);
|
||||
}
|
||||
// Google requires access_type=offline&prompt=consent to return a refresh-token
|
||||
if (!empty($content[OpenIDConnectClient::ADD_AUTH_PARAM]))
|
||||
{
|
||||
$oidc->addAuthParam(str_replace('$username', $content['acc_oauth_username'] ?? $content['acc_imap_username'], $content[OpenIDConnectClient::ADD_AUTH_PARAM]));
|
||||
}
|
||||
|
||||
// we need to use response_code=query / GET request to keep our session token!
|
||||
$oidc->setResponseTypes(['code']); // to be able to use query, not 'id_token'
|
||||
//$oidc->setAllowImplicitFlow(true);
|
||||
$oidc->addScope($content['acc_oauth_scopes']);
|
||||
// we need to use response_code=query / GET request to keep our session token!
|
||||
$oidc->setResponseTypes(['code']); // to be able to use query, not 'id_token'
|
||||
//$oidc->setAllowImplicitFlow(true);
|
||||
$oidc->addScope($content['acc_oauth_scopes']);
|
||||
}
|
||||
|
||||
if (!empty($content['acc_oauth_access_token']) || !empty($content['acc_oauth_refresh_token']))
|
||||
{
|
||||
@ -1545,7 +1559,7 @@ class admin_mail
|
||||
{
|
||||
if (empty($content['acc_oauth_username']))
|
||||
{
|
||||
$content['acc_oauth_username'] = $content['acc_imap_username'];
|
||||
$content['acc_oauth_username'] = $content['acc_imap_username'] ?? $oidc->getVerifiedClaims('email') ?? $content['ident_email'];
|
||||
}
|
||||
if (empty($content['acc_oauth_refresh_token'] = $oidc->getRefreshToken()))
|
||||
{
|
||||
@ -1557,7 +1571,14 @@ class admin_mail
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = 'admin';
|
||||
|
||||
$obj = new self;
|
||||
$obj->autoconfig($content);
|
||||
if (!empty($content['acc_id']))
|
||||
{
|
||||
$obj->edit($content, lang('Use save or apply to store the received OAuth token!'), 'info');
|
||||
}
|
||||
else
|
||||
{
|
||||
$obj->autoconfig($content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1568,12 +1589,20 @@ class admin_mail
|
||||
*/
|
||||
public static function oauthFailure(Throwable $exception=null, array $content)
|
||||
{
|
||||
$content['output'] .= lang('OAuth Authentiction').': '.($exception ? $exception->getMessage() : lang('failed'));
|
||||
$content['connected'] = false;
|
||||
|
||||
$GLOBALS['egw_info']['flags']['currentapp'] = 'admin';
|
||||
|
||||
$obj = new self;
|
||||
if (!empty($content['acc_id']))
|
||||
{
|
||||
$obj->edit($content, lang('OAuth Authentiction').': '.($exception ? $exception->getMessage() : lang('failed')), 'error');
|
||||
}
|
||||
else
|
||||
{
|
||||
$content['output'] .= lang('OAuth Authentiction').': '.($exception ? $exception->getMessage() : lang('failed'));
|
||||
$content['connected'] = false;
|
||||
|
||||
$obj->autoconfig($content);
|
||||
}
|
||||
$obj->autoconfig($content);
|
||||
}
|
||||
|
||||
|
@ -949,6 +949,7 @@ use default admin de Vorgabe verwenden
|
||||
use ldap defaults admin de LDAP Standardeinstellungen benutzen
|
||||
use predefined username and password defined below admin de Verwende den unten vordefinierten Benutzernamen und Passwort
|
||||
use pure html compliant code (not fully working yet) admin de Vollständig HTML kompatiblen Code verwenden (nicht vollständig implementiert)
|
||||
use save or apply to store the received oauth token! admin de Benutze Speicher oder Übernehmen um das erhaltene OAuth Token zu speichern!
|
||||
use secure cookies (transmitted only via https) admin de Benutze sichere Cookies (werden nur per https übertragen)
|
||||
use smtp auth admin de SMTP Authentifizierung benutzen
|
||||
use theme admin de Benutztes Farbschema
|
||||
|
@ -952,6 +952,7 @@ use default admin en use default
|
||||
use ldap defaults admin en Use LDAP defaults
|
||||
use predefined username and password defined below admin en Use predefined username and password defined below
|
||||
use pure html compliant code (not fully working yet) admin en Use pure HTML compliant code
|
||||
use save or apply to store the received oauth token! admin en Use save or apply to store the received OAuth token!
|
||||
use secure cookies (transmitted only via https) admin en Use secure cookies (transmitted only via https)
|
||||
use smtp auth admin en Use SMTP authentication
|
||||
use theme admin en Use theme
|
||||
|
@ -122,11 +122,12 @@ class OpenIDConnectClient extends \Jumbojett\OpenIDConnectClient
|
||||
* Get OIDC client object for the given domain/email
|
||||
*
|
||||
* @param string $domain domain or email address
|
||||
* @param string|null $mailserver
|
||||
* @return self|null
|
||||
*/
|
||||
public static function byDomain($domain)
|
||||
public static function byDomain($domain, $mailserver=null)
|
||||
{
|
||||
if (!($provider = self::providerByDomain($domain)))
|
||||
if (!($provider = self::providerByDomain($domain, $mailserver)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ abstract class Extra
|
||||
// if we have real push available and a regular single-entry refresh of a push supporting app, no need to refresh
|
||||
if (!Json\Push::onlyFallback() &&
|
||||
!empty($type) && !empty($id) && // $type === null --> full reload
|
||||
Link::get_registry($app, 'push_data') !== null)
|
||||
Link::get_registry($app, 'push_data'))
|
||||
{
|
||||
$app = 'msg-only-push-refresh';
|
||||
}
|
||||
|
@ -469,10 +469,17 @@ class Account implements \ArrayAccess
|
||||
*/
|
||||
public function is_imap($try_connect=true)
|
||||
{
|
||||
if (empty($this->acc_imap_host) || ( empty($this->acc_imap_username) && empty($this->acc_imap_password) ) )
|
||||
if (empty($this->acc_imap_host) ||
|
||||
empty($this->acc_imap_username) && empty($this->acc_imap_password) &&
|
||||
!($oauth = Api\Auth\OpenIDConnectClient::providerByDomain($this->acc_imap_username ?: $this->ident_email, $this->acc_imap_host)))
|
||||
{
|
||||
return false; // no imap host or credentials
|
||||
}
|
||||
if (isset($oauth))
|
||||
{
|
||||
$this->params['acc_imap_username'] = $this->acc_imap_username ?: $this->ident_email;
|
||||
$this->params['acc_imap_password'] = '**oauth**';
|
||||
}
|
||||
// if we are not managing the mail-server, we do NOT need to check deliveryMode and accountStatus
|
||||
if ($this->acc_smtp_type == __NAMESPACE__.'\\Smtp')
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user