mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 15:33:23 +01:00
* API: support OpenID Connect for authentication against another OIC IdP
also migrating old fallback auth classes to new auth_fallback parameter and reordering providers a bit / give OIC a prominent position
This commit is contained in:
parent
9f46ee5e62
commit
1b9c543547
@ -169,9 +169,12 @@ class Auth
|
||||
}
|
||||
|
||||
// now we need a (not yet authenticated) session so SAML / auth source selected "survives" eg. the SAML redirects
|
||||
if (!empty($type) && !Session::get_sessionid())
|
||||
if (!Session::get_sessionid() || session_status() === PHP_SESSION_NONE)
|
||||
{
|
||||
session_start();
|
||||
if (session_status() === PHP_SESSION_NONE)
|
||||
{
|
||||
session_start();
|
||||
}
|
||||
Session::egw_setcookie(Session::EGW_SESSION_NAME, session_id());
|
||||
}
|
||||
|
||||
|
129
api/src/Auth/Openidconnect.php
Normal file
129
api/src/Auth/Openidconnect.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware Api: OpenIDConnect authentication (EGroupware against another OIC IdP)
|
||||
*
|
||||
* @link https://www.egroupware.org
|
||||
* @package api
|
||||
* @subpackage mail
|
||||
* @author Ralf Becker <rb@egroupware.org>
|
||||
* @copyright (c) 2023 by Ralf Becker <rb@egroupware.org>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Auth;
|
||||
|
||||
use EGroupware\Api;
|
||||
use Jumbojett\OpenIDConnectClient;
|
||||
use Jumbojett\OpenIDConnectClientException;
|
||||
|
||||
class Openidconnect implements BackendSSO
|
||||
{
|
||||
protected OpenIDConnectClient $client;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->client = new OpenIDConnectClient($GLOBALS['egw_info']['server']['oic_provider'],
|
||||
$GLOBALS['egw_info']['server']['oic_client_id'],
|
||||
$GLOBALS['egw_info']['server']['oic_client_secret']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt SSO login
|
||||
*
|
||||
* @return string sessionid on successful login, null otherwise
|
||||
*/
|
||||
function login()
|
||||
{
|
||||
try {
|
||||
//error_log(__METHOD__."() session_status()=".session_status().", _SESSION=".json_encode($_SESSION));
|
||||
$this->client->authenticate();
|
||||
|
||||
$account_lid = $this->client->getVerifiedClaims('sub');
|
||||
$accounts = Api\Accounts::getInstance();
|
||||
if (!$accounts->name2id($account_lid, 'account_lid', 'u'))
|
||||
{
|
||||
// fail if auto-creation of authenticated users is NOT configured
|
||||
if (empty($GLOBALS['egw_info']['server']['auto_create_acct']))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$user_info = $this->client->requestUserInfo();
|
||||
$GLOBALS['auto_create_acct'] = [
|
||||
'firstname' => $user_info['given_name'],
|
||||
'lastname' => $user_info['family_name'],
|
||||
'email' => $user_info['email'],
|
||||
// not (yet) used supported keys
|
||||
//'primary_group' => '',
|
||||
//'add_group' => '',
|
||||
//'account_id' => 0,
|
||||
];
|
||||
}
|
||||
catch (OpenIDConnectClientException $e) {
|
||||
// do NOT fail, if IdP does not support user-info
|
||||
_egw_log_exception($e);
|
||||
}
|
||||
}
|
||||
// return user session
|
||||
return $GLOBALS['egw']->session->create($account_lid, null, null, false, false);
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
_egw_log_exception($e);
|
||||
$GLOBALS['egw']->session->cd_reason = 'OpenIDConnect Error: '.$e->getMessage();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout SSO system
|
||||
*/
|
||||
function logout()
|
||||
{
|
||||
$this->client->signOut($this->client->getIdToken(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return (which) parts of session needed by current auth backend
|
||||
*
|
||||
* If this returns any key(s), the session is NOT destroyed by Api\Session::destroy,
|
||||
* just everything but the keys is removed.
|
||||
*
|
||||
* @return array of needed keys in session
|
||||
*/
|
||||
function needSession()
|
||||
{
|
||||
return ['openid_connect_state', 'openid_connect_nonce', 'openid_connect_code_verifier',
|
||||
Api\Session::EGW_APPSESSION_VAR]; // Auth stores backend via Cache::setSession()
|
||||
}
|
||||
|
||||
/**
|
||||
* password authentication against password stored in sql datababse
|
||||
*
|
||||
* @param string $username username of account to authenticate
|
||||
* @param string $passwd corresponding password
|
||||
* @param string $passwd_type ='text' 'text' for cleartext passwords (default)
|
||||
* @return boolean true if successful authenticated, false otherwise
|
||||
* @ToDo: add config about which claim to use and use this with Client Credentials claim, would allow to use OID like LDAP/AD with password
|
||||
*/
|
||||
function authenticate($username, $passwd, $passwd_type='text')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* changes password in sql datababse
|
||||
*
|
||||
* @param string $old_passwd must be cleartext
|
||||
* @param string $new_passwd must be cleartext
|
||||
* @param int $account_id account id of user whose passwd should be changed
|
||||
* @throws Exception to give a verbose error, why changing password failed
|
||||
* @return boolean true if password successful changed, false otherwise
|
||||
*/
|
||||
function change_password($old_passwd, $new_passwd, $account_id=0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -116,6 +116,23 @@ else
|
||||
{
|
||||
$current_config[$row['config_name']] = $row['config_value'];
|
||||
}
|
||||
// migrate old fallback types to auth_fallback="True"
|
||||
switch ($current_config['auth_type'])
|
||||
{
|
||||
case 'fallback':
|
||||
$current_config['auth_type'] = 'ldap';
|
||||
$current_config['auth_fallback'] = 'True';
|
||||
break;
|
||||
case 'fallbackmail2sql':
|
||||
$current_config['auth_type'] = 'mail';
|
||||
$current_config['auth_fallback'] = 'True';
|
||||
break;
|
||||
case 'fallbackads2sql':
|
||||
case 'fallbackad2sql':
|
||||
$current_config['auth_type'] = 'ads';
|
||||
$current_config['auth_fallback'] = 'True';
|
||||
break;
|
||||
}
|
||||
}
|
||||
$setup_tpl->pparse('out','T_config_pre_script');
|
||||
|
||||
|
@ -440,11 +440,13 @@ class setup_cmd_config extends setup_cmd
|
||||
static $auth_types = array(
|
||||
'sql' => 'SQL',
|
||||
'ldap' => 'LDAP',
|
||||
'mail' => 'Mail',
|
||||
'ads' => 'Active Directory',
|
||||
'openidconnect' => 'OpenID Connect',
|
||||
'saml' => 'SAML',
|
||||
'mail' => 'Mail',
|
||||
'http' => 'HTTP',
|
||||
'fallback' => 'Fallback LDAP --> SQL',
|
||||
'fallbackmail2sql' => 'Fallback Mail --> SQL',
|
||||
'fallback' => false, // do NOT show, they get migrated to fallback-auth automatic
|
||||
'fallbackmail2sql' => false,
|
||||
'sqlssl' => 'SQL / SSL',
|
||||
);
|
||||
static $scan_done = null;
|
||||
@ -457,11 +459,15 @@ class setup_cmd_config extends setup_cmd
|
||||
if (preg_match('/^([a-z0-9]+)\.php$/i', $file, $matches) &&
|
||||
!isset($auth_types[strtolower($matches[1])]) &&
|
||||
!interface_exists($class='EGroupware\\Api\\Auth\\'.$matches[1]) &&
|
||||
is_subclass_of($class, Api\Auth\Backend::class))
|
||||
is_subclass_of($class, Api\Auth\Backend::class) &&
|
||||
$auth_types[$matches[1]] !== false)
|
||||
{
|
||||
$auth_types[strtolower($matches[1])] = $matches[1];
|
||||
}
|
||||
}
|
||||
// remove (obsolete) auth-types marked with false
|
||||
$auth_types = array_filter($auth_types);
|
||||
|
||||
foreach(self::$options['--account-auth'] as &$param)
|
||||
{
|
||||
if ($param['name'] == 'auth_type')
|
||||
|
@ -465,6 +465,29 @@
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
|
||||
<tr class="th">
|
||||
<td colspan="2">
|
||||
<b>{lang_If_using_OpenIDConnect_(authentication as client agains an other OID IdP)}:</b><br/>
|
||||
{lang_The_OIC_IdP_must_support_autoconfiguration_under_the_above_given_URL (.well-known/openid-configuration).}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row_off">
|
||||
<td>{lang_URL_of_the_IdP_(without_path)}:</td>
|
||||
<td><input name="newsettings[oic_provider]" value="{value_oic_provider}" size="80" /></td>
|
||||
</tr>
|
||||
<tr class="row_on">
|
||||
<td>{lang_Client_ID}:</td>
|
||||
<td><input name="newsettings[oic_client_id]" value="{value_oic_client_id}" size="40" /></td>
|
||||
</tr>
|
||||
<tr class="row_off">
|
||||
<td>{lang_Client_secret}:</td>
|
||||
<td><input type="password" name="newsettings[oic_client_secret]" value="{value_oic_client_secret}" size="40" /></td>
|
||||
</tr>
|
||||
|
||||
<tr class="row_off">
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
|
||||
<tr class="th">
|
||||
<td colspan="2"><b>{lang_Periodic_import_from_ADS_or_LDAP_into_EGroupware_database}:</b></td>
|
||||
</tr>
|
||||
|
Loading…
Reference in New Issue
Block a user