public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
PHP
49%
JavaScript
35%
HTML
9%
CSS
4%
Shell
2%
Python
1%
Lua
0%
Perl
0%
Ruby
0%
SCSS
0%
Create file
Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git
Commit
[Web] Add identity_provider option to disable auto-creation of users on login
1b2f424e
data/web/inc/functions.auth.inc.php | 33 ++++++++++++++++------
data/web/inc/functions.inc.php | 24 +++++++++++++---
data/web/lang/lang.de-de.json | 1 +
data/web/lang/lang.en-gb.json | 1 +
.../admin/tab-config-identity-provider.twig | 32 ++++++++++++++++++++-
5 files changed, 78 insertions(+), 13 deletions(-)
Diff
diff --git a/data/web/inc/functions.auth.inc.php b/data/web/inc/functions.auth.inc.php
index 57dec808..ebc432a1 100644
--- a/data/web/inc/functions.auth.inc.php
+++ b/data/web/inc/functions.auth.inc.php
@@ -262,10 +262,6 @@ function user_login($user, $pass, $extra = null){
return false;
}
- if (intval($row['attributes']['force_pw_update']) == 1) {
- $_SESSION['pending_pw_update'] = true;
- }
-
// check for tfa authenticators
$authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
@@ -318,10 +314,6 @@ function user_login($user, $pass, $extra = null){
return false;
}
- if (intval($row['attributes']['force_pw_update']) == 1) {
- $_SESSION['pending_pw_update'] = true;
- }
-
// check for tfa authenticators
$authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
@@ -485,6 +477,9 @@ function keycloak_mbox_login_rest($user, $pass, $extra = null){
}
return false;
}
+ if (!$iam_provider) {
+ return false;
+ }
// get access_token for service account of mailcow client
$admin_token = identity_provider("get-keycloak-admin-token");
@@ -554,6 +549,17 @@ function keycloak_mbox_login_rest($user, $pass, $extra = null){
return 'user';
}
+ // check if login provisioning is enabled before creating user
+ if (!$iam_settings['login_provisioning']){
+ if (!$is_internal){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, "Auto-create users on login is deactivated"),
+ 'msg' => 'login_failed'
+ );
+ }
+ return false;
+ }
// check if matching attribute exist
if (empty($iam_settings['mappers']) || !$user_template || $mapper_key === false) {
if (!empty($iam_settings['default_template'])) {
@@ -667,6 +673,17 @@ function ldap_mbox_login($user, $pass, $extra = null){
return 'user';
}
+ // check if login provisioning is enabled before creating user
+ if (!$iam_settings['login_provisioning']){
+ if (!$is_internal){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, "Auto-create users on login is deactivated"),
+ 'msg' => 'login_failed'
+ );
+ }
+ return false;
+ }
// check if matching attribute exist
if (empty($iam_settings['mappers']) || !$user_template || $mapper_key === false) {
if (!empty($iam_settings['default_tempalte'])) {
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index aab57928..edf428d5 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -2294,6 +2294,7 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
break;
case "use_ssl":
case "use_tls":
+ case "login_provisioning":
case "ignore_ssl_errors":
$settings[$row["key"]] = boolval($row["value"]);
break;
@@ -2302,6 +2303,10 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
break;
}
}
+ // set login_provisioning if not exists
+ if (!array_key_exists('login_provisioning', $settings)) {
+ $settings['login_provisioning'] = 1;
+ }
// return default client_scopes for generic-oidc if none is set
if ($settings["authsource"] == "generic-oidc" && empty($settings["client_scopes"])){
$settings["client_scopes"] = "openid profile email mailcow_template";
@@ -2366,7 +2371,8 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
return false;
}
- $_data['ignore_ssl_error'] = isset($_data['ignore_ssl_error']) ? boolval($_data['ignore_ssl_error']) : false;
+ $_data['ignore_ssl_error'] = isset($_data['ignore_ssl_error']) ? boolval($_data['ignore_ssl_error']) : false;
+ $_data['login_provisioning'] = isset($_data['login_provisioning']) ? boolval($_data['login_provisioning']) : false;
switch ($_data['authsource']) {
case "keycloak":
$_data['server_url'] = (!empty($_data['server_url'])) ? rtrim($_data['server_url'], '/') : null;
@@ -2375,14 +2381,14 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
$_data['import_users'] = isset($_data['import_users']) ? intval($_data['import_users']) : 0;
$_data['sync_interval'] = (!empty($_data['sync_interval'])) ? intval($_data['sync_interval']) : 15;
$_data['sync_interval'] = $_data['sync_interval'] < 1 ? 1 : $_data['sync_interval'];
- $required_settings = array('authsource', 'server_url', 'realm', 'client_id', 'client_secret', 'redirect_url', 'version', 'mailpassword_flow', 'periodic_sync', 'import_users', 'sync_interval', 'ignore_ssl_error');
+ $required_settings = array('authsource', 'server_url', 'realm', 'client_id', 'client_secret', 'redirect_url', 'version', 'mailpassword_flow', 'periodic_sync', 'import_users', 'sync_interval', 'ignore_ssl_error', 'login_provisioning');
break;
case "generic-oidc":
$_data['authorize_url'] = (!empty($_data['authorize_url'])) ? $_data['authorize_url'] : null;
$_data['token_url'] = (!empty($_data['token_url'])) ? $_data['token_url'] : null;
$_data['userinfo_url'] = (!empty($_data['userinfo_url'])) ? $_data['userinfo_url'] : null;
$_data['client_scopes'] = (!empty($_data['client_scopes'])) ? $_data['client_scopes'] : "openid profile email mailcow_template";
- $required_settings = array('authsource', 'authorize_url', 'token_url', 'client_id', 'client_secret', 'redirect_url', 'userinfo_url', 'client_scopes', 'ignore_ssl_error');
+ $required_settings = array('authsource', 'authorize_url', 'token_url', 'client_id', 'client_secret', 'redirect_url', 'userinfo_url', 'client_scopes', 'ignore_ssl_error', 'login_provisioning');
break;
case "ldap":
$_data['host'] = (!empty($_data['host'])) ? str_replace(" ", "", $_data['host']) : "";
@@ -2396,7 +2402,7 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
$_data['use_tls'] = isset($_data['use_tls']) && !$_data['use_ssl'] ? boolval($_data['use_tls']) : false;
$_data['sync_interval'] = (!empty($_data['sync_interval'])) ? intval($_data['sync_interval']) : 15;
$_data['sync_interval'] = $_data['sync_interval'] < 1 ? 1 : $_data['sync_interval'];
- $required_settings = array('authsource', 'host', 'port', 'basedn', 'username_field', 'filter', 'attribute_field', 'binddn', 'bindpass', 'periodic_sync', 'import_users', 'sync_interval', 'use_ssl', 'use_tls', 'ignore_ssl_error');
+ $required_settings = array('authsource', 'host', 'port', 'basedn', 'username_field', 'filter', 'attribute_field', 'binddn', 'bindpass', 'periodic_sync', 'import_users', 'sync_interval', 'use_ssl', 'use_tls', 'ignore_ssl_error', 'login_provisioning');
break;
}
@@ -2766,6 +2772,16 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
return true;
}
+ // user doesn't exist, check if login provisioning is enabled
+ if (!$iam_settings['login_provisioning']){
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, "Auto-create users on login is deactivated"),
+ 'msg' => 'login_failed'
+ );
+ return false;
+ }
+
if (empty($iam_settings['mappers']) || empty($user_template) || $mapper_key === false){
if (!empty($iam_settings['default_template'])) {
$mbox_template = $iam_settings['default_template'];
diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json
index 06d43b56..6e1b4d4c 100644
--- a/data/web/lang/lang.de-de.json
+++ b/data/web/lang/lang.de-de.json
@@ -227,6 +227,7 @@
"iam_host": "Host",
"iam_host_info": "Gib einen oder mehrere LDAP-Hosts ein, getrennt durch Kommas.",
"iam_import_users": "Importiere Benutzer",
+ "iam_login_provisioning": "Benutzer beim Login erstellen",
"iam_mapping": "Attribut Mapping",
"iam_bindpass": "Bind Passwort",
"iam_periodic_full_sync": "Vollsynchronisation",
diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json
index 707e2a60..fb8fbb6e 100644
--- a/data/web/lang/lang.en-gb.json
+++ b/data/web/lang/lang.en-gb.json
@@ -234,6 +234,7 @@
"iam_host": "Host",
"iam_host_info": "Enter one or more LDAP hosts, separated by commas.",
"iam_import_users": "Import Users",
+ "iam_login_provisioning": "Auto-create users on login",
"iam_mapping": "Attribute Mapping",
"iam_bindpass": "Bind Password",
"iam_periodic_full_sync": "Periodic Full Sync",
diff --git a/data/web/templates/admin/tab-config-identity-provider.twig b/data/web/templates/admin/tab-config-identity-provider.twig
index a9300225..4572d7fb 100644
--- a/data/web/templates/admin/tab-config-identity-provider.twig
+++ b/data/web/templates/admin/tab-config-identity-provider.twig
@@ -219,6 +219,16 @@
</div>
</div>
</div>
+ <div class="row mb-2">
+ <div class="col-md-3 d-flex align-items-center justify-content-md-end">
+ <label class="control-label">{{ lang.admin.iam_login_provisioning }}</label>
+ </div>
+ <div class="col-12 col-md-9">
+ <div class="form-check form-switch">
+ <input class="form-check-input" type="checkbox" role="switch" name="login_provisioning" value="1" {% if iam_settings.login_provisioning == 1 %}checked{% endif %}>
+ </div>
+ </div>
+ </div>
<div class="row mb-2">
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
<label class="control-label">{{ lang.admin.iam_periodic_full_sync }}</label>
@@ -430,7 +440,7 @@
</div>
</div>
</div>
- <div class="row mb-4">
+ <div class="row mb-2">
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
<label class="control-label">{{ lang.admin.ignore_ssl_error }}</label>
</div>
@@ -440,6 +450,16 @@
</div>
</div>
</div>
+ <div class="row mb-4">
+ <div class="col-md-3 d-flex align-items-center justify-content-md-end">
+ <label class="control-label">{{ lang.admin.iam_login_provisioning }}</label>
+ </div>
+ <div class="col-12 col-md-9">
+ <div class="form-check form-switch">
+ <input class="form-check-input" type="checkbox" role="switch" name="login_provisioning" value="1" {% if iam_settings.login_provisioning == 1 %}checked{% endif %}>
+ </div>
+ </div>
+ </div>
<div class="row mt-4 mb-2">
<div class="offset-md-3 col-12 col-md-9 d-flex flex-wrap">
<div class="btn-group mb-2">
@@ -646,6 +666,16 @@
</div>
</div>
</div>
+ <div class="row mb-2">
+ <div class="col-md-3 d-flex align-items-center justify-content-md-end">
+ <label class="control-label">{{ lang.admin.iam_login_provisioning }}</label>
+ </div>
+ <div class="col-12 col-md-9">
+ <div class="form-check form-switch">
+ <input class="form-check-input" type="checkbox" role="switch" name="login_provisioning" value="1" {% if iam_settings.login_provisioning == 1 %}checked{% endif %}>
+ </div>
+ </div>
+ </div>
<div class="row mb-2">
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
<label class="control-label">{{ lang.admin.iam_periodic_full_sync }}</label>