diff --git a/data/web/inc/functions.auth.inc.php b/data/web/inc/functions.auth.inc.php index 8e695c359..e047b83ba 100644 --- a/data/web/inc/functions.auth.inc.php +++ b/data/web/inc/functions.auth.inc.php @@ -216,7 +216,7 @@ function user_login($user, $pass, $extra = null){ unset($_SESSION['ldelay']); $_SESSION['return'][] = array( 'type' => 'success', - 'log' => array(__FUNCTION__, $user, '*'), + 'log' => array(__FUNCTION__, $user, '*', 'Provider: Keycloak'), 'msg' => array('logged_in_as', $user) ); return "pending"; @@ -229,7 +229,7 @@ function user_login($user, $pass, $extra = null){ $stmt->execute(array(':user' => $user)); $_SESSION['return'][] = array( 'type' => 'success', - 'log' => array(__FUNCTION__, $user, '*'), + 'log' => array(__FUNCTION__, $user, '*', 'Provider: Keycloak'), 'msg' => array('logged_in_as', $user) ); } @@ -255,7 +255,7 @@ function user_login($user, $pass, $extra = null){ unset($_SESSION['ldelay']); $_SESSION['return'][] = array( 'type' => 'success', - 'log' => array(__FUNCTION__, $user, '*'), + 'log' => array(__FUNCTION__, $user, '*', 'Provider: LDAP'), 'msg' => array('logged_in_as', $user) ); return "pending"; @@ -268,7 +268,7 @@ function user_login($user, $pass, $extra = null){ $stmt->execute(array(':user' => $user)); $_SESSION['return'][] = array( 'type' => 'success', - 'log' => array(__FUNCTION__, $user, '*'), + 'log' => array(__FUNCTION__, $user, '*', 'Provider: LDAP'), 'msg' => array('logged_in_as', $user) ); } @@ -290,7 +290,7 @@ function user_login($user, $pass, $extra = null){ unset($_SESSION['ldelay']); $_SESSION['return'][] = array( 'type' => 'success', - 'log' => array(__FUNCTION__, $user, '*'), + 'log' => array(__FUNCTION__, $user, '*', 'Provider: mailcow'), 'msg' => array('logged_in_as', $user) ); return "pending"; @@ -303,7 +303,7 @@ function user_login($user, $pass, $extra = null){ $stmt->execute(array(':user' => $user)); $_SESSION['return'][] = array( 'type' => 'success', - 'log' => array(__FUNCTION__, $user, '*'), + 'log' => array(__FUNCTION__, $user, '*', 'Provider: mailcow'), 'msg' => array('logged_in_as', $user) ); } @@ -434,12 +434,27 @@ function keycloak_mbox_login_rest($user, $pass, $extra = null){ $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); if ($code != 200) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*', 'Identity Provider returned HTTP ' . $code), + 'msg' => 'generic_server_error' + ); return false; } if (!isset($user_res['attributes']['mailcow_password']) || !is_array($user_res['attributes']['mailcow_password'])){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*', 'User has no mailcow_password attribute'), + 'msg' => 'generic_server_error' + ); return false; } if (empty($user_res['attributes']['mailcow_password'][0])){ + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*', "User's mailcow_password attribute is empty"), + 'msg' => 'generic_server_error' + ); return false; } @@ -469,8 +484,14 @@ function keycloak_mbox_login_rest($user, $pass, $extra = null){ } // check if matching attribute exist - if (empty($iam_settings['mappers']) || !$user_template) return false; - if ($mapper_key === false) return false; + if (empty($iam_settings['mappers']) || !$user_template || $mapper_key === false) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*', 'No matching attribute mapping was found'), + 'msg' => 'generic_server_error' + ); + return false; + } // create mailbox $_SESSION['access_all_exception'] = '1'; @@ -484,6 +505,11 @@ function keycloak_mbox_login_rest($user, $pass, $extra = null){ $_SESSION['access_all_exception'] = '0'; if (!$create_res){ clear_session(); + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*', 'Could not create mailbox on login'), + 'msg' => 'generic_server_error' + ); return false; } @@ -526,17 +552,12 @@ function ldap_mbox_login($user, $pass, $extra = null){ $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $user, '*', $e->getMessage()), - 'msg' => 'ldap_error' + 'msg' => 'generic_server_error' ); return false; } try { if (!$iam_provider->auth()->attempt($user_res['dn'], $pass)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $user, '*', $user_res), - 'msg' => 'ldap_auth_failed' - ); return false; } } catch (Exception $e) { @@ -545,7 +566,7 @@ function ldap_mbox_login($user, $pass, $extra = null){ $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $user, '*', $e->getMessage()), - 'msg' => 'ldap_error' + 'msg' => 'generic_server_error' ); return false; } @@ -570,8 +591,14 @@ function ldap_mbox_login($user, $pass, $extra = null){ } // check if matching attribute exist - if (empty($iam_settings['mappers']) || !$user_template) return false; - if ($mapper_key === false) return false; + if (empty($iam_settings['mappers']) || !$user_template || $mapper_key === false) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*', 'No matching attribute mapping was found'), + 'msg' => 'generic_server_error' + ); + return false; + } // create mailbox $_SESSION['access_all_exception'] = '1'; @@ -585,6 +612,11 @@ function ldap_mbox_login($user, $pass, $extra = null){ $_SESSION['access_all_exception'] = '0'; if (!$create_res){ clear_session(); + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $user, '*', 'Could not create mailbox on login'), + 'msg' => 'generic_server_error' + ); return false; } diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 2a6968fe2..187036b47 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -2271,7 +2271,7 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { } // 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"; + $settings["client_scopes"] = "openid profile email mailcow_template"; } if ($_extra['hide_sensitive']){ $settings['client_secret'] = ''; @@ -2348,7 +2348,7 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { $_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"; + $_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'); break; case "ldap": @@ -2619,8 +2619,8 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { if ($iam_settings['authsource'] != 'keycloak' && $iam_settings['authsource'] != 'generic-oidc'){ $_SESSION['return'][] = array( 'type' => 'danger', - 'log' => array(__FUNCTION__), - 'msg' => array('login_failed', "no OIDC provider configured") + 'log' => array(__FUNCTION__, "no OIDC provider configured"), + 'msg' => 'login_failed' ); return false; } @@ -2633,13 +2633,20 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { } catch (Throwable $e) { $_SESSION['return'][] = array( 'type' => 'danger', - 'log' => array(__FUNCTION__), - 'msg' => array('login_failed', $e->getMessage()) + 'log' => array(__FUNCTION__, $e->getMessage()), + 'msg' => 'login_failed' ); return false; } // check if email address is given - if (empty($info['email'])) return false; + if (empty($info['email'])) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, 'No email address found for user'), + 'msg' => 'login_failed' + ); + return false; + } // get mapped template $user_template = $info['mailcow_template']; @@ -2678,21 +2685,12 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { return true; } - if (empty($iam_settings['mappers']) || empty($user_template)){ + if (empty($iam_settings['mappers']) || empty($user_template) || $mapper_key === false){ clear_session(); $_SESSION['return'][] = array( 'type' => 'danger', - 'log' => array(__FUNCTION__, $info['email']), - 'msg' => array('login_failed', 'empty attribute mapping or missing template attribute') - ); - return false; - } - if ($mapper_key === false) { - clear_session(); - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $info['email']), - 'msg' => array('login_failed', 'specified template not found') + 'log' => array(__FUNCTION__, $info['email'], 'No matching attribute mapping was found'), + 'msg' => 'login_failed' ); return false; } @@ -2711,8 +2709,8 @@ function identity_provider($_action = null, $_data = null, $_extra = null) { clear_session(); $_SESSION['return'][] = array( 'type' => 'danger', - 'log' => array(__FUNCTION__, $info['email']), - 'msg' => array('login_failed', 'mailbox creation failed') + 'log' => array(__FUNCTION__, $info['email'], 'Could not create mailbox on login'), + 'msg' => 'login_failed' ); return false; } diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 85a713c67..0857bc5f7 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -219,10 +219,10 @@ "iam_extra_permission": "Damit die folgenden Einstellungen funktionieren, benötigt der mailcow Client in Keycloak ein Service-Konto und die Berechtigung view-users.", "iam_host": "Host", "iam_host_info": "Gib einen oder mehrere LDAP-Hosts ein, getrennt durch Kommas.", - "iam_import_users": "Import Users", + "iam_import_users": "Importiere Benutzer", "iam_mapping": "Attribut Mapping", "iam_bindpass": "Bind Passwort", - "iam_periodic_full_sync": "Periodic Full Sync", + "iam_periodic_full_sync": "Vollsynchronisation", "iam_port": "Port", "iam_realm": "Realm", "iam_redirect_url": "Redirect Url", @@ -238,7 +238,7 @@ "iam_use_ssl": "Benutze SSL", "iam_use_tls": "Benutze TLS", "iam_version": "Version", - "ignore_ssl_error": "Ignoriere SSL Errors", + "ignore_ssl_error": "Ignoriere SSL Fehler", "import": "Importieren", "import_private_key": "Private Key importieren", "in_use_by": "Verwendet von", @@ -406,6 +406,7 @@ "aliases_in_use": "Maximale Anzahl an Aliassen muss größer oder gleich %d sein", "app_name_empty": "App-Name darf nicht leer sein", "app_passwd_id_invalid": "App-Passwort ID %s ist ungültig", + "authsource_in_use": "Der Identity Provider kann nicht geändert oder gelöscht werden, da er derzeit von einem oder mehreren Benutzern verwendet wird.", "bcc_empty": "BCC-Ziel darf nicht leer sein", "bcc_exists": "Ein BCC-Map-Eintrag %s existiert bereits als Typ %s", "bcc_must_be_email": "BCC-Ziel %s ist keine gültige E-Mail-Adresse", @@ -430,6 +431,7 @@ "file_open_error": "Datei kann nicht zum Schreiben geöffnet werden", "filter_type": "Falscher Filtertyp", "from_invalid": "Die Absenderadresse muss eine gültige E-Mail-Adresse sein", + "generic_server_error": "Ein unerwarteter Serverfehler ist aufgetreten. Bitte kontaktieren Sie Ihren Administrator.", "global_filter_write_error": "Kann Filterdatei nicht schreiben: %s", "global_map_invalid": "Rspamd-Map %s ist ungültig", "global_map_write_error": "Kann globale Map ID %s nicht schreiben: %s", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 5f8e78a9b..64baade92 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -433,6 +433,7 @@ "file_open_error": "File cannot be opened for writing", "filter_type": "Wrong filter type", "from_invalid": "Sender must not be empty", + "generic_server_error": "An unexpected server error occurred. Please contact your administrator.", "global_filter_write_error": "Could not write filter file: %s", "global_map_invalid": "Global map ID %s invalid", "global_map_write_error": "Could not write global map ID %s: %s", diff --git a/data/web/templates/admin/tab-config-identity-provider.twig b/data/web/templates/admin/tab-config-identity-provider.twig index 3381fe4d6..4a85b42fc 100644 --- a/data/web/templates/admin/tab-config-identity-provider.twig +++ b/data/web/templates/admin/tab-config-identity-provider.twig @@ -265,7 +265,7 @@
- +