mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2024-12-23 02:04:46 +02:00
[Web] add generic-oidc provider
This commit is contained in:
parent
1ab1505c88
commit
3b6a1d50bd
@ -2069,8 +2069,13 @@ function uuid4() {
|
|||||||
}
|
}
|
||||||
function identity_provider($_action, $_data = null) {
|
function identity_provider($_action, $_data = null) {
|
||||||
function identity_provider($_action, $_data = null, $hide_secret = false) {
|
function identity_provider($_action, $_data = null, $hide_secret = false) {
|
||||||
|
function identity_provider($_action, $_data = null, $_extra = null) {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
|
$data_log = $_data;
|
||||||
|
if (isset($data_log['client_secret'])) $data_log['client_secret'] = '*';
|
||||||
|
if (isset($data_log['access_token'])) $data_log['access_token'] = '*';
|
||||||
|
|
||||||
switch ($_action) {
|
switch ($_action) {
|
||||||
case 'get':
|
case 'get':
|
||||||
$settings = array();
|
$settings = array();
|
||||||
@ -2078,16 +2083,15 @@ function identity_provider($_action, $_data = null, $hide_secret = false) {
|
|||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
foreach($rows as $row){
|
foreach($rows as $row){
|
||||||
if ($row["key"] == 'mappers'){
|
if ($row["key"] == 'mappers' || $row["key"] == 'templates'){
|
||||||
$settings['mappers'] = json_decode($row["value"]);
|
$settings[$row["key"]] = json_decode($row["value"]);
|
||||||
} else if ($row["key"] == 'templates'){
|
|
||||||
$settings['templates'] = json_decode($row["value"]);
|
|
||||||
} else {
|
} else {
|
||||||
$settings[$row["key"]] = $row["value"];
|
$settings[$row["key"]] = $row["value"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($hide_secret){
|
if ($_extra['hide_sensitive']){
|
||||||
$settings['client_secret'] = '';
|
$settings['client_secret'] = '';
|
||||||
|
$settings['access_token'] = '';
|
||||||
}
|
}
|
||||||
return $settings;
|
return $settings;
|
||||||
break;
|
break;
|
||||||
@ -2100,54 +2104,60 @@ function identity_provider($_action, $_data = null, $hide_secret = false) {
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$data_log = $_data;
|
if (!isset($_data['authsource'])){
|
||||||
$data_log['client_secret'] = '*';
|
$_SESSION['return'][] = array(
|
||||||
$stmt = $pdo->prepare("INSERT INTO identity_provider (`key`, `value`) VALUES (:key, :value) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);");
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $data_log),
|
||||||
$_data['login_flow'] = (isset($_data['login_flow']) && $_data['login_flow'] == 'ropc') ? 'ropc' : 'rest';
|
'msg' => array('required_data_missing', $setting)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_data['authsource'] = strtolower($_data['authsource']);
|
||||||
|
if ($_data['authsource'] != "keycloak" && $_data['authsource'] != "generic-oidc"){
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $data_log),
|
||||||
|
'msg' => array('invalid_authsource', $setting)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// add connection settings
|
if ($_data['authsource'] == "keycloak") {
|
||||||
$required_settings = array('server_url', 'authsource', 'realm', 'client_id', 'client_secret', 'redirect_url', 'version', 'login_flow');
|
$_data['mailpassword_flow'] = isset($_data['mailpassword_flow']) ? intval($_data['mailpassword_flow']) : 0;
|
||||||
|
$_data['periodic_sync'] = isset($_data['periodic_sync']) ? intval($_data['periodic_sync']) : 0;
|
||||||
|
$_data['import_users'] = isset($_data['import_users']) ? intval($_data['import_users']) : 0;
|
||||||
|
$required_settings = array('authsource', 'server_url', 'realm', 'client_id', 'client_secret', 'redirect_url', 'version', 'mailpassword_flow', 'periodic_sync', 'import_users');
|
||||||
|
} else if ($_data['authsource'] == "generic-oidc") {
|
||||||
|
$required_settings = array('authsource', 'authorize_url', 'token_url', 'client_id', 'client_secret', 'redirect_url', 'userinfo_url');
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO identity_provider (`key`, `value`) VALUES (:key, :value) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);");
|
||||||
|
// add connection settings
|
||||||
foreach($required_settings as $setting){
|
foreach($required_settings as $setting){
|
||||||
if (!$_data[$setting]){
|
if (!isset($_data[$setting])){
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
'log' => array(__FUNCTION__, $_action, $data_log),
|
'log' => array(__FUNCTION__, $_action, $data_log),
|
||||||
'msg' => 'required_data_missing'
|
'msg' => array('required_data_missing', $setting)
|
||||||
);
|
);
|
||||||
|
$pdo->rollback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
foreach($_data as $key => $value){
|
|
||||||
if (!in_array($key, $required_settings) || $key == 'mappers' || $key == 'templates'){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->bindParam(':key', $key);
|
$stmt->bindParam(':key', $setting);
|
||||||
$stmt->bindParam(':value', $value);
|
$stmt->bindParam(':value', $_data[$setting]);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
|
$pdo->commit();
|
||||||
|
|
||||||
// add mappers
|
// add mappers
|
||||||
if ($_data['mappers'] && $_data['templates']){
|
if ($_data['mappers'] && $_data['templates']){
|
||||||
if (!is_array($_data['mappers'])){
|
$_data['mappers'] = (!is_array($_data['mappers'])) ? array($_data['mappers']) : $_data['mappers'];
|
||||||
$_data['mappers'] = array($_data['mappers']);
|
$_data['templates'] = (!is_array($_data['templates'])) ? array($_data['templates']) : $_data['templates'];
|
||||||
}
|
|
||||||
if (!is_array($_data['templates'])){
|
$mappers = array_filter($_data['mappers']);
|
||||||
$_data['templates'] = array($_data['templates']);
|
$templates = array_filter($_data['templates']);
|
||||||
}
|
|
||||||
$mappers = array();
|
|
||||||
$templates = array();
|
|
||||||
foreach($_data['mappers'] as $mapper){
|
|
||||||
if ($mapper){
|
|
||||||
array_push($mappers, $mapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach($_data['templates'] as $template){
|
|
||||||
if ($template){
|
|
||||||
array_push($templates, $template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count($mappers) == count($templates)){
|
if (count($mappers) == count($templates)){
|
||||||
$mappers = json_encode($mappers);
|
$mappers = json_encode($mappers);
|
||||||
$templates = json_encode($templates);
|
$templates = json_encode($templates);
|
||||||
@ -2161,6 +2171,9 @@ function identity_provider($_action, $_data = null, $hide_secret = false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete old access_token
|
||||||
|
$stmt = $pdo->query("INSERT INTO identity_provider (`key`, `value`) VALUES ('access_token', '') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);");
|
||||||
|
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'success',
|
'type' => 'success',
|
||||||
'log' => array(__FUNCTION__, $_action, $data_log),
|
'log' => array(__FUNCTION__, $_action, $data_log),
|
||||||
@ -2178,7 +2191,11 @@ function identity_provider($_action, $_data = null, $hide_secret = false) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = "{$_data['server_url']}/realms/{$_data['realm']}/protocol/openid-connect/token";
|
if ($_data['authsource'] == 'keycloak') {
|
||||||
|
$url = "{$_data['server_url']}/realms/{$_data['realm']}/protocol/openid-connect/token";
|
||||||
|
} else {
|
||||||
|
$url = $_data['token_url'];
|
||||||
|
}
|
||||||
$req = http_build_query(array(
|
$req = http_build_query(array(
|
||||||
'grant_type' => 'client_credentials',
|
'grant_type' => 'client_credentials',
|
||||||
'client_id' => $_data['client_id'],
|
'client_id' => $_data['client_id'],
|
||||||
@ -2215,21 +2232,37 @@ function identity_provider($_action, $_data = null, $hide_secret = false) {
|
|||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case "init":
|
case "init":
|
||||||
$identity_provider_settings = identity_provider('get');
|
$iam_settings = identity_provider('get');
|
||||||
$provider = null;
|
$provider = null;
|
||||||
if ($identity_provider_settings['server_url'] && $identity_provider_settings['realm'] && $identity_provider_settings['client_id'] &&
|
if ($iam_settings['authsource'] == 'keycloak'){
|
||||||
$identity_provider_settings['client_secret'] && $identity_provider_settings['redirect_url'] && $identity_provider_settings['version']){
|
if ($iam_settings['server_url'] && $iam_settings['realm'] && $iam_settings['client_id'] &&
|
||||||
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
$iam_settings['client_secret'] && $iam_settings['redirect_url'] && $iam_settings['version']){
|
||||||
'authServerUrl' => $identity_provider_settings['server_url'],
|
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||||
'realm' => $identity_provider_settings['realm'],
|
'authServerUrl' => $iam_settings['server_url'],
|
||||||
'clientId' => $identity_provider_settings['client_id'],
|
'realm' => $iam_settings['realm'],
|
||||||
'clientSecret' => $identity_provider_settings['client_secret'],
|
'clientId' => $iam_settings['client_id'],
|
||||||
'redirectUri' => $identity_provider_settings['redirect_url'],
|
'clientSecret' => $iam_settings['client_secret'],
|
||||||
'version' => $identity_provider_settings['version'],
|
'redirectUri' => $iam_settings['redirect_url'],
|
||||||
// 'encryptionAlgorithm' => 'RS256', // optional
|
'version' => $iam_settings['version'],
|
||||||
// 'encryptionKeyPath' => '../key.pem' // optional
|
// 'encryptionAlgorithm' => 'RS256', // optional
|
||||||
// 'encryptionKey' => 'contents_of_key_or_certificate' // optional
|
// 'encryptionKeyPath' => '../key.pem' // optional
|
||||||
]);
|
// 'encryptionKey' => 'contents_of_key_or_certificate' // optional
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($iam_settings['authsource'] == 'generic-oidc'){
|
||||||
|
if ($iam_settings['client_id'] && $iam_settings['client_secret'] && $iam_settings['redirect_url'] &&
|
||||||
|
$iam_settings['authorize_url'] && $iam_settings['token_url'] && $iam_settings['userinfo_url']){
|
||||||
|
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
|
||||||
|
'clientId' => $iam_settings['client_id'],
|
||||||
|
'clientSecret' => $iam_settings['client_secret'],
|
||||||
|
'redirectUri' => $iam_settings['redirect_url'],
|
||||||
|
'urlAuthorize' => $iam_settings['authorize_url'],
|
||||||
|
'urlAccessToken' => $iam_settings['token_url'],
|
||||||
|
'urlResourceOwnerDetails' => $iam_settings['userinfo_url'],
|
||||||
|
'scopes' => 'openid profile email'
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $provider;
|
return $provider;
|
||||||
break;
|
break;
|
||||||
|
@ -362,7 +362,7 @@ function init_db_schema() {
|
|||||||
"custom_attributes" => "JSON NOT NULL DEFAULT ('{}')",
|
"custom_attributes" => "JSON NOT NULL DEFAULT ('{}')",
|
||||||
"kind" => "VARCHAR(100) NOT NULL DEFAULT ''",
|
"kind" => "VARCHAR(100) NOT NULL DEFAULT ''",
|
||||||
"multiple_bookings" => "INT NOT NULL DEFAULT -1",
|
"multiple_bookings" => "INT NOT NULL DEFAULT -1",
|
||||||
"authsource" => "ENUM('mailcow', 'keycloak') DEFAULT 'mailcow'",
|
"authsource" => "ENUM('mailcow', 'keycloak', 'generic-oidc') DEFAULT 'mailcow'",
|
||||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||||
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
|
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
|
||||||
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
||||||
|
@ -8,110 +8,228 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-config-identity-provider" class="card-body collapse" data-bs-parent="#admin-content">
|
<div id="collapse-tab-config-identity-provider" class="card-body collapse" data-bs-parent="#admin-content">
|
||||||
<p class="offset-sm-3 mb-4">{{ lang.admin.iam_description }}</p>
|
<p class="offset-sm-3 mb-4">{{ lang.admin.iam_description }}</p>
|
||||||
<form class="form-horizontal" autocapitalize="none" data-id="iam_sso" autocorrect="off" role="form" method="post">
|
<div class="row mb-4">
|
||||||
<input type="hidden" name="authsource" value="keycloak">
|
<label class="control-label col-sm-3 text-sm-end" for="iam_realm">{{ lang.admin.iam }}:</label>
|
||||||
<div class="row mb-2">
|
<div class="col-sm-4">
|
||||||
<label class="control-label col-sm-3 text-sm-end" for="iam_url">{{ lang.admin.iam_server_url }}:</label>
|
<select
|
||||||
<div class="col-sm-4">
|
data-style="btn btn-secondary"
|
||||||
<input type="text" class="form-control" id="iam_server_url" name="server_url" value="{{ identity_provider_settings.server_url }}" required>
|
data-id="iam_provider"
|
||||||
</div>
|
title="{{ lang.admin.iam_provider }}"
|
||||||
|
name="iam_provider" id="iam_provider" class="full-width-select form-control" required>
|
||||||
|
<option value="keycloak" {% if not iam_settings.authsource or iam_settings.authsource == 'keycloak' %}selected{% endif %}>Keycloak</option>
|
||||||
|
<option value="generic-oidc" {% if iam_settings.authsource == 'generic-oidc' %}selected{% endif %}>Generic-OIDC</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-2">
|
</div>
|
||||||
<label class="control-label col-sm-3 text-sm-end" for="iam_realm">{{ lang.admin.iam_realm }}:</label>
|
<div id="keycloak_settings" class="{% if iam_settings.authsource and iam_settings.authsource != 'keycloak' %}d-none{% endif %}">
|
||||||
<div class="col-sm-4">
|
<form class="form-horizontal" autocapitalize="none" data-id="iam_keycloak" autocorrect="off" role="form" method="post">
|
||||||
<input type="text" class="form-control" id="iam_realm" name="realm" value="{{ identity_provider_settings.realm }}" required>
|
<input type="hidden" name="authsource" value="keycloak">
|
||||||
</div>
|
<div class="row mb-2">
|
||||||
</div>
|
<label class="control-label col-sm-3 text-sm-end" for="iam_keycloak_url">{{ lang.admin.iam_server_url }}:</label>
|
||||||
<div class="row mb-2">
|
<div class="col-sm-4">
|
||||||
<label class="control-label col-sm-3 text-sm-end" for="iam_client_id">{{ lang.admin.iam_client_id }}:</label>
|
<input type="text" class="form-control" id="iam_keycloak_url" name="server_url" value="{{ iam_settings.server_url }}" required>
|
||||||
<div class="col-sm-4">
|
|
||||||
<input type="text" class="form-control" id="iam_client_id" name="client_id" value="{{ identity_provider_settings.client_id }}" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-2">
|
|
||||||
<label class="control-label col-sm-3 text-sm-end" for="iam_client_secret">{{ lang.admin.iam_client_secret }}:</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<div class="reveal-password-input input-group">
|
|
||||||
<input type="password" class="password-field form-control" id="iam_client_secret" name="client_secret" value="{{ identity_provider_settings.client_secret }}" required>
|
|
||||||
<button class="toggle-password btn btn-secondary" type="button"><i class="bi bi-eye"></i></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mb-2">
|
||||||
<div class="row mb-2">
|
<label class="control-label col-sm-3 text-sm-end" for="iam_keycloak_realm">{{ lang.admin.iam_realm }}:</label>
|
||||||
<label class="control-label col-sm-3 text-sm-end" for="iam_redirect_url">{{ lang.admin.iam_redirect_url }}:</label>
|
<div class="col-sm-4">
|
||||||
<div class="col-sm-4">
|
<input type="text" class="form-control" id="iam_keycloak_realm" name="realm" value="{{ iam_settings.realm }}" required>
|
||||||
<input type="text" class="form-control" id="iam_redirect_url" name="redirect_url" value="{{ identity_provider_settings.redirect_url }}" required>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mb-2">
|
||||||
<div class="row mb-4">
|
<label class="control-label col-sm-3 text-sm-end" for="iam_keycloak_clientid">{{ lang.admin.iam_client_id }}:</label>
|
||||||
<label class="control-label col-sm-3 text-sm-end" for="iam_version">{{ lang.admin.iam_version }}:</label>
|
<div class="col-sm-4">
|
||||||
<div class="col-sm-4">
|
<input type="text" class="form-control" id="iam_keycloak_clientid" name="client_id" value="{{ iam_settings.client_id }}" required>
|
||||||
<input type="text" class="form-control" id="iam_version" name="version" value="{{ identity_provider_settings.version }}" required>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mb-2">
|
||||||
<div class="row mb-4">
|
<label class="control-label col-sm-3 text-sm-end" for="iam_keycloak_clientsecret">{{ lang.admin.iam_client_secret }}:</label>
|
||||||
<label class="control-label col-sm-3 text-sm-end" for="iam_version">{{ lang.admin.iam_mapping }}:</label>
|
<div class="col-sm-4">
|
||||||
<div class="col-4 d-flex mb-2">
|
<div class="reveal-password-input input-group">
|
||||||
<span class="w-100 me-2">Attribute</span>
|
<input type="password" class="password-field form-control" id="iam_keycloak_clientsecret" name="client_secret" value="{{ iam_settings.client_secret }}" required>
|
||||||
<span class="w-100 ms-2">Template</span>
|
<button class="toggle-password btn btn-secondary" type="button"><i class="bi bi-eye"></i></button>
|
||||||
<button id="iam_rolemap_add" class="btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-plus-lg"></i></button>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% for key, role in identity_provider_settings.mappers %}
|
<div class="row mb-2">
|
||||||
<div class="offset-sm-3 col-4 d-flex mb-2">
|
<label class="control-label col-sm-3 text-sm-end" for="iam_keycloak_redirecturl">{{ lang.admin.iam_redirect_url }}:</label>
|
||||||
<input type="text" class="form-control me-2" name="mappers" value="{{ identity_provider_settings.mappers[key] }}" required>
|
<div class="col-sm-4">
|
||||||
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}" required>
|
<input type="text" class="form-control" id="iam_keycloak_redirecturl" name="redirect_url" value="{{ iam_settings.redirect_url }}" required>
|
||||||
{% for mbox_template in mbox_templates %}
|
</div>
|
||||||
<option{% if mbox_template.template == identity_provider_settings.templates[key] %} selected{% endif %}>
|
</div>
|
||||||
{{ mbox_template.template }}
|
<div class="row mb-4">
|
||||||
</option>
|
<label class="control-label col-sm-3 text-sm-end" for="iam_keycloak_version">{{ lang.admin.iam_version }}:</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input type="text" class="form-control" id="iam_keycloak_version" name="version" value="{{ iam_settings.version }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end">{{ lang.admin.iam_mapping }}:</label>
|
||||||
|
<div class="col-4 d-flex mb-2">
|
||||||
|
<span class="w-100 me-2">Attribute</span>
|
||||||
|
<span class="w-100 ms-2">Template</span>
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-secondary ms-2 iam_rolemap_add"><i class="bi bi-plus-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
{% for key, role in iam_settings.mappers %}
|
||||||
|
<div class="offset-sm-3 col-4 d-flex mb-2">
|
||||||
|
<input type="text" class="form-control me-2" name="mappers" value="{{ iam_settings.mappers[key] }}" required>
|
||||||
|
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}" required>
|
||||||
|
{% for mbox_template in mbox_templates %}
|
||||||
|
<option{% if mbox_template.template == iam_settings.templates[key] %} selected{% endif %}>
|
||||||
|
{{ mbox_template.template }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
{% if not iam_settings.mappers %}
|
||||||
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
<div class="offset-sm-3 col-4 d-flex mb-2">
|
||||||
|
<input type="text" class="form-control me-2" name="mappers" value="" required>
|
||||||
|
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}" required>
|
||||||
|
{% for mbox_template in mbox_templates %}
|
||||||
|
<option>
|
||||||
|
{{ mbox_template.template }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
<div class="row mb-2 mt-4">
|
||||||
{% if not identity_provider_settings.mappers %}
|
<label class="control-label col-sm-3 text-sm-end"></label>
|
||||||
<div class="offset-sm-3 col-4 d-flex mb-2">
|
<div class="col-sm-9">
|
||||||
<input type="text" class="form-control me-2" name="mappers" value="" required>
|
<span>{{ lang.admin.iam_extra_permission|raw }}</span>
|
||||||
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}" required>
|
</div>
|
||||||
{% for mbox_template in mbox_templates %}
|
</div>
|
||||||
<option>
|
<div class="row mb-2">
|
||||||
{{ mbox_template.template }}
|
<label class="control-label col-sm-3 text-sm-end">{{ lang.admin.iam_rest_flow }}</label>
|
||||||
</option>
|
<div class="col-sm-9">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" name="mailpassword_flow" value="1" {% if iam_settings.mailpassword_flow == 1 %}checked{% endif %}>
|
||||||
|
</div>
|
||||||
|
<p class="text-muted">
|
||||||
|
<small>
|
||||||
|
{{ lang.admin.iam_auth_flow_info|raw }}
|
||||||
|
</small>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end">Periodic Full Sync</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" name="periodic_sync" value="1" {% if iam_settings.periodic_sync == 1 %}checked{% endif %}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end">Import Users</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" name="import_users" value="1" {% if iam_settings.import_users == 1 %}checked{% endif %}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-4 mb-2">
|
||||||
|
<div class="offset-sm-3 col-sm-9 d-flex">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-secondary iam_test_connection iam_test_connection" data-id="iam_keycloak"><i class="bi bi-play"></i> {{ lang.admin.iam_test_connection }}</button>
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="identity-provider" data-action="edit_selected" data-id="iam_keycloak" data-api-url='edit/identity-provider' data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-danger ms-auto" data-item="identity-provider" data-action="delete_selected" data-id="iam_keycloak" data-api-url='delete/identity-provider'><i class="bi bi-trash"></i> {{ lang.mailbox.remove }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="generic_oidc_settings" class="{% if not iam_settings.authsource or iam_settings.authsource != 'generic-oidc' %}d-none{% endif %}">
|
||||||
|
<form class="form-horizontal" autocapitalize="none" data-id="iam_generic" autocorrect="off" role="form" method="post">
|
||||||
|
<input type="hidden" name="authsource" value="generic-oidc">
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end" for="iam_authorize_url">{{ lang.admin.iam_authorize_url }}:</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input type="text" class="form-control" id="iam_authorize_url" name="authorize_url" value="{{ iam_settings.authorize_url }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end" for="iam_token_url">{{ lang.admin.iam_token_url }}:</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input type="text" class="form-control" id="iam_token_url" name="token_url" value="{{ iam_settings.token_url }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end" for="iam_userinfo_url">{{ lang.admin.iam_userinfo_url }}:</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input type="text" class="form-control" id="iam_userinfo_url" name="userinfo_url" value="{{ iam_settings.userinfo_url }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end" for="iam_client_id">{{ lang.admin.iam_client_id }}:</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input type="text" class="form-control" id="iam_client_id" name="client_id" value="{{ iam_settings.client_id }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end" for="iam_client_secret">{{ lang.admin.iam_client_secret }}:</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="reveal-password-input input-group">
|
||||||
|
<input type="password" class="password-field form-control" id="iam_client_secret" name="client_secret" value="{{ iam_settings.client_secret }}" required>
|
||||||
|
<button class="toggle-password btn btn-secondary" type="button"><i class="bi bi-eye"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end" for="iam_redirect_url">{{ lang.admin.iam_redirect_url }}:</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input type="text" class="form-control" id="iam_redirect_url" name="redirect_url" value="{{ iam_settings.redirect_url }}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<label class="control-label col-sm-3 text-sm-end">{{ lang.admin.iam_mapping }}:</label>
|
||||||
|
<div class="col-4 d-flex mb-2">
|
||||||
|
<span class="w-100 me-2">Attribute</span>
|
||||||
|
<span class="w-100 ms-2">Template</span>
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-secondary ms-2 iam_rolemap_add"><i class="bi bi-plus-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
{% for key, role in iam_settings.mappers %}
|
||||||
|
<div class="offset-sm-3 col-4 d-flex mb-2">
|
||||||
|
<input type="text" class="form-control me-2" name="mappers" value="{{ iam_settings.mappers[key] }}" required>
|
||||||
|
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}" required>
|
||||||
|
{% for mbox_template in mbox_templates %}
|
||||||
|
<option{% if mbox_template.template == iam_settings.templates[key] %} selected{% endif %}>
|
||||||
|
{{ mbox_template.template }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
{% if not iam_settings.mappers %}
|
||||||
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
<div class="offset-sm-3 col-4 d-flex mb-2">
|
||||||
</div>
|
<input type="text" class="form-control me-2" name="mappers" value="" required>
|
||||||
{% endif %}
|
<select data-live-search="true" name="templates" class="form-control" title="{{ lang.mailbox.template }}" required>
|
||||||
</div>
|
{% for mbox_template in mbox_templates %}
|
||||||
<div class="row mb-2">
|
<option>
|
||||||
<label class="control-label col-sm-3 text-sm-end">{{ lang.admin.iam_auth_flow }}</label>
|
{{ mbox_template.template }}
|
||||||
<div class="col-sm-9">
|
</option>
|
||||||
<div class="btn-group">
|
{% endfor %}
|
||||||
<input type="radio" class="btn-check" name="login_flow" id="iam_login_flow_rest" autocomplete="off" value="rest" {% if identity_provider_settings.login_flow != 'ropc' %}checked{% endif %}>
|
</select>
|
||||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary" for="iam_login_flow_rest">{{ lang.admin.iam_rest_flow }}</label>
|
<button class="iam_rolemap_del btn btn-sm d-block d-sm-inline btn-secondary ms-2"><i class="bi bi-x-lg"></i></button>
|
||||||
|
|
||||||
<input type="radio" class="btn-check" name="login_flow" id="iam_login_flow_ropc" autocomplete="off" value="ropc" {% if identity_provider_settings.login_flow == 'ropc' %}checked{% endif %}>
|
|
||||||
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary" for="iam_login_flow_ropc">{{ lang.admin.iam_ropc_flow }}</label>
|
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted">
|
{% endif %}
|
||||||
<small>
|
|
||||||
{{ lang.admin.iam_auth_flow_info|raw }}<br>
|
|
||||||
{{ lang.admin.iam_auth_flow_rest_info|raw }}<br>
|
|
||||||
{{ lang.admin.iam_auth_flow_ropc_info|raw }}
|
|
||||||
</small>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mt-4 mb-2">
|
||||||
<div class="row mt-4 mb-2">
|
<div class="offset-sm-3 col-sm-9 d-flex">
|
||||||
<div class="offset-sm-3 col-sm-9 d-flex">
|
<div class="btn-group">
|
||||||
<div class="btn-group">
|
<button class="btn btn-sm d-block d-sm-inline btn-secondary iam_test_connection" data-id="iam_generic"><i class="bi bi-play"></i> {{ lang.admin.iam_test_connection }}</button>
|
||||||
<button id="iam_test_connection" class="btn btn-sm d-block d-sm-inline btn-secondary"><i class="bi bi-play"></i> {{ lang.admin.iam_test_connection }}</button>
|
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="identity-provider" data-action="edit_selected" data-id="iam_generic" data-api-url='edit/identity-provider' data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||||
<button class="btn btn-sm d-block d-sm-inline btn-success" data-item="iam_sso" data-action="edit_selected" data-id="iam_sso" data-api-url='edit/identity-provider' data-api-attr='{}'><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
</div>
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-danger ms-auto" data-item="identity-provider" data-action="delete_selected" data-id="iam_generic" data-api-url='delete/identity-provider'><i class="bi bi-trash"></i> {{ lang.mailbox.remove }}</button>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-sm d-block d-sm-inline btn-danger ms-auto" data-item="identity-provider" data-action="delete_selected" data-id="iam_sso" data-api-url='delete/identity-provider'><i class="bi bi-trash"></i> {{ lang.mailbox.remove }}</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user