forked from extern/egroupware
Adding GMail to supported OAuth providers, thought the app is not (yet) approved by Google
This commit is contained in:
parent
21f8a936a0
commit
f85aa4dcbb
@ -145,7 +145,7 @@ class admin_mail
|
||||
/**
|
||||
* List of domains know to not support Sieve
|
||||
*
|
||||
* Used to switch Sieve off by default, thought users can allways try switching it on.
|
||||
* Used to switch Sieve off by default, thought users can always try switching it on.
|
||||
* Testing not existing Sieve with google takes a long time, as ports are open,
|
||||
* but not answering ...
|
||||
*
|
||||
@ -153,6 +153,23 @@ class admin_mail
|
||||
*/
|
||||
public static $no_sieve_blacklist = array('gmail.com', 'googlemail.com', 'outlook.office365.com');
|
||||
|
||||
const ADD_CLIENT_TO_WELL_KNOWN = 'add-client-to-well-known';
|
||||
|
||||
/**
|
||||
* Regular expressions to match domain in username to imap/smtp servers and oauth provider
|
||||
*
|
||||
* @var array[] email-regexp => [imap-host, smtp-host, oauth-provider, client-id, client-secret, scopes] pairs
|
||||
*/
|
||||
public static $oauth_domain_regexps = [
|
||||
'/@([^.]\.onmicrosoft\.com)$/i' => ['outlook.office365.com', 'smtp.office365.com', 'login.microsoftonline.com/$1',
|
||||
'e09fe57b-ffc5-496e-9ef8-3e6c7d628c09', 'Hd18Q~t-8_-ImvPFXlh8DSFjWKYyvpUTqURRJc7i',
|
||||
'https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/POP.AccessAsUser.All https://outlook.office.com/SMTP.Send offline_access',
|
||||
[self::ADD_CLIENT_TO_WELL_KNOWN => 'appid']],
|
||||
'/@g(oogle)?mail\.com$/i' => ['imap.gmail.com', 'smtp.gmail.com', 'accounts.google.com',
|
||||
'581021931838-unqjf9tivr9brnmo34rbsoj179ojp79p.apps.googleusercontent.com', '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',
|
||||
'https://mail.google.com/ https://www.googleapis.com/auth/userinfo.email'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Is current use a mail administrator / has run rights for EMailAdmin
|
||||
*
|
||||
@ -206,10 +223,30 @@ class admin_mail
|
||||
), $readonlys, $content, 2);
|
||||
}
|
||||
|
||||
const OFFICE365_CLIENT_ID = 'e09fe57b-ffc5-496e-9ef8-3e6c7d628c09';
|
||||
const OFFICE365_CLIENT_SECRET = 'Hd18Q~t-8_-ImvPFXlh8DSFjWKYyvpUTqURRJc7i';
|
||||
const OFFICE365_IMAP_HOST = 'outlook.office365.com';
|
||||
const OFFICE365_SMTP_HOST = 'smtp.office365.com';
|
||||
/**
|
||||
* Find server config by email-domain incl. oauth data
|
||||
*
|
||||
* @param $email
|
||||
* @return array|null
|
||||
*/
|
||||
public static function oauthDomainMatch($email)
|
||||
{
|
||||
foreach(self::$oauth_domain_regexps as $regexp => [$imap, $smtp, $provider, $client, $secret, $scopes, $extra])
|
||||
{
|
||||
if (preg_match($regexp, $email, $matches))
|
||||
{
|
||||
return [
|
||||
'imap' => $imap,
|
||||
'smtp' => $smtp,
|
||||
'provider' => $provider ? 'https://'.strtr($provider, ['$1' => $matches[1] ?? null, '$2' => $matches[2] ?? null]): null,
|
||||
'client' => $client,
|
||||
'secret' => $secret,
|
||||
'scopes' => array_merge(['openid'], explode(' ', $scopes)),
|
||||
]+($extra ?? []);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to autoconfig an account
|
||||
@ -245,18 +282,18 @@ class admin_mail
|
||||
);
|
||||
}
|
||||
}
|
||||
// Office 365 Mail
|
||||
elseif (preg_match('/@[^.]+\.onmicrosoft\.com$/i', $content['acc_imap_username']))
|
||||
// supported oauth providers
|
||||
elseif (($oauth = self::oauthDomainMatch($content['acc_imap_username'])))
|
||||
{
|
||||
$content['output'] = lang('Using Office365 mail servers')."\n";
|
||||
list(, $domain) = explode('@', $content['acc_imap_username']);
|
||||
$hosts[self::OFFICE365_IMAP_HOST] = array(
|
||||
self::SSL_TLS => 993,
|
||||
);
|
||||
$content['acc_smpt_host'] = self::OFFICE365_SMTP_HOST;
|
||||
$content['output'] = lang('Using IMAP:%1, SMTP:%2, OAUTH:%3:', $oauth['imap'], $oauth['smtp'], $oauth['provider'])."\n";
|
||||
$hosts[$oauth['imap']] = true;
|
||||
$content['acc_smpt_host'] = $oauth['smtp'];
|
||||
$content['acc_sieve_enabled'] = false;
|
||||
$content['acc_oauth_provider_url'] = "https://login.microsoftonline.com/$domain";
|
||||
$content['acc_oauth_client_id'] = self::OFFICE365_CLIENT_ID;
|
||||
$content['acc_oauth_provider_url'] = $oauth['provider'];
|
||||
$content['acc_oauth_client_id'] = $oauth['client'];
|
||||
$content['acc_oauth_client_secret'] = $oauth['secret'];
|
||||
$content['acc_oauth_scopes'] = $oauth['scopes'];
|
||||
$content[self::ADD_CLIENT_TO_WELL_KNOWN] = $oauth[self::ADD_CLIENT_TO_WELL_KNOWN] ?? null;
|
||||
}
|
||||
elseif (($ispdb = self::mozilla_ispdb($content['ident_email'])) && count($ispdb['imap']))
|
||||
{
|
||||
@ -286,6 +323,13 @@ class admin_mail
|
||||
$hosts = $this->guess_hosts($content['ident_email'], 'imap');
|
||||
}
|
||||
|
||||
// check if support OAuth for that domain or we have a password
|
||||
if (empty($oauth) && empty($content['acc_imap_password']))
|
||||
{
|
||||
Etemplate::set_validation_error('acc_imap_password', lang('Field must not be empty!'));
|
||||
$connected = false;
|
||||
}
|
||||
|
||||
// iterate over all hosts and try to connect
|
||||
foreach(!isset($connected) ? $hosts : [] as $host => $data)
|
||||
{
|
||||
@ -1471,31 +1515,21 @@ class admin_mail
|
||||
{
|
||||
if (empty($content['acc_oauth_client_secret']))
|
||||
{
|
||||
switch($content['acc_oauth_client_id'])
|
||||
{
|
||||
case self::OFFICE365_CLIENT_ID:
|
||||
$content['acc_oauth_client_secret'] = self::OFFICE365_CLIENT_SECRET;
|
||||
break;
|
||||
default:
|
||||
throw new Exception(lang("No OAuth client secret for provider '%1'!", $content['acc_oauth_provider_url']));
|
||||
}
|
||||
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 ($content['acc_oauth_client_id'] = self::OFFICE365_CLIENT_ID)
|
||||
if (!empty($content[self::ADD_CLIENT_TO_WELL_KNOWN]))
|
||||
{
|
||||
$oidc->setWellKnownConfigParameters(['appid' => $content['acc_oauth_client_id']]);
|
||||
$oidc->setWellKnownConfigParameters([$content[self::ADD_CLIENT_TO_WELL_KNOWN] => $content['acc_oauth_client_id']]);
|
||||
}
|
||||
|
||||
// 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->addAuthParam(['response_mode' => 'query']); // to keep cookie, not 'form_post'
|
||||
|
||||
// ToDo: the last 3 are Office365 specific scopes
|
||||
$oidc->addScope(['openid', 'email', 'profile', 'https://outlook.office.com/IMAP.AccessAsUser.All', 'https://outlook.office.com/SMTP.Send', 'https://outlook.office.com/User.Read']);
|
||||
//$oidc->setAllowImplicitFlow(true);
|
||||
$oidc->addScope($content['acc_oauth_scopes']);
|
||||
|
||||
if (!empty($content['acc_oauth_access_token']) || !empty($content['acc_oauth_refresh_token']))
|
||||
{
|
||||
|
@ -23,7 +23,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<description value="Password" for="acc_imap_password"/>
|
||||
<passwd id="acc_imap_password" needed="1" size="32" maxlength="128" autocomplete="off"/>
|
||||
<passwd id="acc_imap_password" size="32" maxlength="128" autocomplete="off" blur="Can be left empty, if OAuth is supported" class="et2_required"/>
|
||||
</row>
|
||||
<row class="@manual_class">
|
||||
<description value="IMAP server" for="acc_imap_host"/>
|
||||
|
Loading…
Reference in New Issue
Block a user