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
|
* 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,
|
* Testing not existing Sieve with google takes a long time, as ports are open,
|
||||||
* but not answering ...
|
* but not answering ...
|
||||||
*
|
*
|
||||||
@ -153,6 +153,23 @@ class admin_mail
|
|||||||
*/
|
*/
|
||||||
public static $no_sieve_blacklist = array('gmail.com', 'googlemail.com', 'outlook.office365.com');
|
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
|
* Is current use a mail administrator / has run rights for EMailAdmin
|
||||||
*
|
*
|
||||||
@ -206,10 +223,30 @@ class admin_mail
|
|||||||
), $readonlys, $content, 2);
|
), $readonlys, $content, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const OFFICE365_CLIENT_ID = 'e09fe57b-ffc5-496e-9ef8-3e6c7d628c09';
|
/**
|
||||||
const OFFICE365_CLIENT_SECRET = 'Hd18Q~t-8_-ImvPFXlh8DSFjWKYyvpUTqURRJc7i';
|
* Find server config by email-domain incl. oauth data
|
||||||
const OFFICE365_IMAP_HOST = 'outlook.office365.com';
|
*
|
||||||
const OFFICE365_SMTP_HOST = 'smtp.office365.com';
|
* @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
|
* Try to autoconfig an account
|
||||||
@ -245,18 +282,18 @@ class admin_mail
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Office 365 Mail
|
// supported oauth providers
|
||||||
elseif (preg_match('/@[^.]+\.onmicrosoft\.com$/i', $content['acc_imap_username']))
|
elseif (($oauth = self::oauthDomainMatch($content['acc_imap_username'])))
|
||||||
{
|
{
|
||||||
$content['output'] = lang('Using Office365 mail servers')."\n";
|
$content['output'] = lang('Using IMAP:%1, SMTP:%2, OAUTH:%3:', $oauth['imap'], $oauth['smtp'], $oauth['provider'])."\n";
|
||||||
list(, $domain) = explode('@', $content['acc_imap_username']);
|
$hosts[$oauth['imap']] = true;
|
||||||
$hosts[self::OFFICE365_IMAP_HOST] = array(
|
$content['acc_smpt_host'] = $oauth['smtp'];
|
||||||
self::SSL_TLS => 993,
|
|
||||||
);
|
|
||||||
$content['acc_smpt_host'] = self::OFFICE365_SMTP_HOST;
|
|
||||||
$content['acc_sieve_enabled'] = false;
|
$content['acc_sieve_enabled'] = false;
|
||||||
$content['acc_oauth_provider_url'] = "https://login.microsoftonline.com/$domain";
|
$content['acc_oauth_provider_url'] = $oauth['provider'];
|
||||||
$content['acc_oauth_client_id'] = self::OFFICE365_CLIENT_ID;
|
$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']))
|
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');
|
$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
|
// iterate over all hosts and try to connect
|
||||||
foreach(!isset($connected) ? $hosts : [] as $host => $data)
|
foreach(!isset($connected) ? $hosts : [] as $host => $data)
|
||||||
{
|
{
|
||||||
@ -1471,31 +1515,21 @@ class admin_mail
|
|||||||
{
|
{
|
||||||
if (empty($content['acc_oauth_client_secret']))
|
if (empty($content['acc_oauth_client_secret']))
|
||||||
{
|
{
|
||||||
switch($content['acc_oauth_client_id'])
|
throw new Exception(lang("No OAuth client secret for provider '%1'!", $content['acc_oauth_provider_url']));
|
||||||
{
|
|
||||||
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']));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$oidc = new OpenIDConnectClient($content['acc_oauth_provider_url'],
|
$oidc = new OpenIDConnectClient($content['acc_oauth_provider_url'],
|
||||||
$content['acc_oauth_client_id'], $content['acc_oauth_client_secret']);
|
$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)
|
// 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!
|
// 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->setResponseTypes(['code']); // to be able to use query, not 'id_token'
|
||||||
$oidc->setAllowImplicitFlow(true);
|
//$oidc->setAllowImplicitFlow(true);
|
||||||
$oidc->addAuthParam(['response_mode' => 'query']); // to keep cookie, not 'form_post'
|
$oidc->addScope($content['acc_oauth_scopes']);
|
||||||
|
|
||||||
// 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']);
|
|
||||||
|
|
||||||
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']))
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<description value="Password" for="acc_imap_password"/>
|
<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>
|
||||||
<row class="@manual_class">
|
<row class="@manual_class">
|
||||||
<description value="IMAP server" for="acc_imap_host"/>
|
<description value="IMAP server" for="acc_imap_host"/>
|
||||||
@ -56,4 +56,4 @@
|
|||||||
</rows>
|
</rows>
|
||||||
</grid>
|
</grid>
|
||||||
</template>
|
</template>
|
||||||
</overlay>
|
</overlay>
|
Loading…
Reference in New Issue
Block a user