';
+ item.scope = "profile";
+ item.grant_types = 'refresh_token password authorization_code';
+ item.chkbox = '';
+ });
} else if (table == 'domainadminstable') {
$.each(data, function (i, item) {
item.selected_domains = escapeHtml(item.selected_domains);
@@ -299,6 +336,7 @@ jQuery(function($){
draw_admins();
draw_fwd_hosts();
draw_relayhosts();
+ draw_oauth2_clients();
draw_transport_maps();
draw_queue();
// Relayhost
diff --git a/data/web/json_api.php b/data/web/json_api.php
index fea4565b..ea4304af 100644
--- a/data/web/json_api.php
+++ b/data/web/json_api.php
@@ -142,6 +142,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
case "mailbox":
process_add_return(mailbox('add', 'mailbox', $attr));
break;
+ case "oauth2-client":
+ process_add_return(oauth2('add', 'client', $attr));
+ break;
case "domain":
process_add_return(mailbox('add', 'domain', $attr));
break;
@@ -1056,6 +1059,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
case "alias":
process_delete_return(mailbox('delete', 'alias', array('id' => $items)));
break;
+ case "oauth2-client":
+ process_delete_return(oauth2('delete', 'client', array('id' => $items)));
+ break;
case "relayhost":
process_delete_return(relayhost('delete', array('id' => $items)));
break;
diff --git a/data/web/lang/lang.cs.php b/data/web/lang/lang.cs.php
index a0910534..ad532eaa 100644
--- a/data/web/lang/lang.cs.php
+++ b/data/web/lang/lang.cs.php
@@ -279,7 +279,7 @@ $lang['mailbox']['tls_policy_maps_info'] = 'Tato mapa přepisuje pravidla odchoz
$lang['mailbox']['tls_enforce_in'] = 'Vynutit TLS pro příchozí';
$lang['mailbox']['tls_enforce_out'] = 'Vynutit TLS pro odchozí';
$lang['mailbox']['tls_map_dest'] = 'Cíl';
-$lang['mailbox']['tls_map_dest_info'] = 'Příklady: example.org, .example.org, mail@example.org, [mail.example.org]:25';
+$lang['mailbox']['tls_map_dest_info'] = 'Příklady: example.org, .example.org, [mail.example.org]:25';
$lang['mailbox']['tls_map_policy'] = 'Pravidlo';
$lang['mailbox']['tls_map_parameters'] = 'Parametry';
$lang['mailbox']['tls_map_parameters_info'] = 'Prázdné nebo parametry, například: protocols=!SSLv2 ciphers=medium exclude=3DES';
diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php
index 22c07caa..dadfb8de 100644
--- a/data/web/lang/lang.de.php
+++ b/data/web/lang/lang.de.php
@@ -272,7 +272,7 @@ $lang['mailbox']['tls_policy_maps_info'] = 'Nachstehende Richtlinien erzwingen T
$lang['mailbox']['tls_enforce_in'] = 'TLS eingehend erzwingen';
$lang['mailbox']['tls_enforce_out'] = 'TLS ausgehend erzwingen';
$lang['mailbox']['tls_map_dest'] = 'Ziel';
-$lang['mailbox']['tls_map_dest_info'] = 'Beispiele: example.org, .example.org, mail@example.org, [mail.example.org]:25';
+$lang['mailbox']['tls_map_dest_info'] = 'Beispiele: example.org, .example.org, [mail.example.org]:25';
$lang['mailbox']['tls_map_policy'] = 'Richtlinie';
$lang['mailbox']['tls_map_parameters'] = 'Parameter';
$lang['mailbox']['tls_map_parameters_info'] = 'Leer oder Parameter, Beispiele: protocols=!SSLv2 ciphers=medium exclude=3DES';
@@ -711,7 +711,39 @@ $lang['admin']['help_text'] = "Hilfstext unter Login-Maske (HTML zulässig)";
$lang['admin']['title_name'] = '"mailcow UI" Webseiten Titel';
$lang['admin']['main_name'] = '"mailcow UI" Name';
$lang['admin']['apps_name'] = '"mailcow Apps" Name';
-$lang['admin']['ui_impress'] = 'Impressum, Footer (HTML zulässig)';
+$lang['admin']['ui_footer'] = 'Footer (HTML zulässig)';
+
+$lang['admin']['oauth2_info'] = 'Die OAuth2 Implementierung untersützt den Grant Type "Authorization Code" mit Refresh Tokens.
+Der Server wird automatisch einen neuen Refresh Token ausstellen, sobald ein vorheriger Token gegen einen Access Token eingetauscht wurde.
+→ Der Standard Scope lautet profile. Nur Mailbox-Benutzer können sich gegen OAuth2 authentifizieren. Wird kein Scope angegeben, verwendet das System per Standard profile.
+→ Der state Parameter wird im Zuge des Autorisierungsprozesses benötigt.
+Die Pfade für die OAuth2 API lauten wie folgt:
+
+
Authorization Endpoint: /oauth/authorize
+
Token Endpoint: /oauth/token
+
Resource Page: /oauth/profile
+
+Die Regenerierung des Client Secrets wird vorhandene Authorization Codes nicht invalidieren, dennoch wird der Renew des Access Tokens durch einen Refresh Token nicht mehr gelingen.
+Das Entfernen aller Client Tokens verursacht die umgehende Terminierung aller aktiven OAuth2 Sessions. Clients müssen sich erneut gegen die OAuth2 Anwendung authentifizieren.';
+
+$lang['admin']['oauth2_client_id'] = "Client ID";
+$lang['admin']['oauth2_client_secret'] = "Client Secret";
+$lang['admin']['oauth2_redirect_uri'] = "Redirect URI";
+$lang['admin']['oauth2_revoke_tokens'] = 'Alle Client Tokens entfernen';
+$lang['admin']['oauth2_renew_secret'] = 'Neues Client Secret generieren';
+$lang['edit']['client_id'] = 'Client ID';
+$lang['edit']['client_secret'] = 'Client Secret';
+$lang['edit']['scope'] = 'Scope';
+$lang['edit']['grant_types'] = 'Grant types';
+$lang['edit']['redirect_uri'] = 'Redirect/Callback URL';
+$lang['oauth2']['scope_ask_permission'] = 'Eine Anwendung hat um die folgenden Berechtigungen gebeten';
+$lang['oauth2']['profile'] = 'Profil';
+$lang['oauth2']['profile_desc'] = 'Persönliche Informationen anzeigen: Benutzername, Name, Erstellzeitpunkt, Änderungszeitpunkt, Status';
+$lang['oauth2']['permit'] = 'Anwendung authorisieren';
+$lang['oauth2']['authorize_app'] = 'Anwendung authorisieren';
+$lang['oauth2']['deny'] = 'Ablehnen';
+$lang['oauth2']['access_denied'] = 'Bitte als Mailbox-Nutzer einloggen, um den Zugriff via OAuth2 zu erlauben.';
+
$lang['admin']['customize'] = "UI Anpassung";
$lang['admin']['change_logo'] = "Logo ändern";
@@ -836,14 +868,6 @@ $lang['mailbox']['add_tls_policy_map'] = "TLS-Richtlinieneintrag hinzufügen";
$lang['danger']['tls_policy_map_parameter_invalid'] = "Parameter ist ungültig";
$lang['danger']['temp_error'] = "Temporärer Fehler";
-$lang['oauth2']['scope_ask_permission'] = 'Eine Anwendung hat um die folgenden Berechtigungen gebeten';
-$lang['oauth2']['profile'] = 'Profil';
-$lang['oauth2']['profile_desc'] = 'Persönliche Informationen anzeigen: Benutzername, Name, Erstellzeitpunkt, Änderungszeitpunkt, Status';
-$lang['oauth2']['permit'] = 'Anwendung authorisieren';
-$lang['oauth2']['authorize_app'] = 'Anwendung authorisieren';
-$lang['oauth2']['deny'] = 'Ablehnen';
-$lang['oauth2']['access_denied'] = 'Bitte als Mailbox-Nutzer einloggen, um den Zugriff via OAuth2 zu erlauben.';
-
$lang['admin']['sys_mails'] = 'System-E-Mails';
$lang['admin']['subject'] = 'Betreff';
$lang['admin']['from'] = 'Absender';
diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php
index 795e531c..efdb80ee 100644
--- a/data/web/lang/lang.en.php
+++ b/data/web/lang/lang.en.php
@@ -276,7 +276,7 @@ $lang['mailbox']['tls_policy_maps_info'] = 'This policy map overrides outgoing T
$lang['mailbox']['tls_enforce_in'] = 'Enforce TLS incoming';
$lang['mailbox']['tls_enforce_out'] = 'Enforce TLS outgoing';
$lang['mailbox']['tls_map_dest'] = 'Destination';
-$lang['mailbox']['tls_map_dest_info'] = 'Examples: example.org, .example.org, mail@example.org, [mail.example.org]:25';
+$lang['mailbox']['tls_map_dest_info'] = 'Examples: example.org, .example.org, [mail.example.org]:25';
$lang['mailbox']['tls_map_policy'] = 'Policy';
$lang['mailbox']['tls_map_parameters'] = 'Parameters';
$lang['mailbox']['tls_map_parameters_info'] = 'Empty or parameters, for example: protocols=!SSLv2 ciphers=medium exclude=3DES';
@@ -346,11 +346,6 @@ $lang['mailbox']['sogo_visible'] = 'Alias is visible in SOGo';
$lang['mailbox']['sogo_visible_y'] = 'Show alias in SOGo';
$lang['mailbox']['sogo_visible_n'] = 'Hide alias in SOGo';
$lang['edit']['syncjob'] = 'Edit sync job';
-$lang['edit']['client_id'] = 'Client ID';
-$lang['edit']['client_secret'] = 'Client secret';
-$lang['edit']['scope'] = 'Scope';
-$lang['edit']['grant_types'] = 'Grant types';
-$lang['edit']['redirect_uri'] = 'Redirect/Callback URL';
$lang['edit']['hostname'] = 'Hostname';
$lang['edit']['encryption'] = 'Encryption';
$lang['edit']['maxage'] = 'Maximum age of messages in days that will be polled from remote (0 = ignore age)';
@@ -679,6 +674,38 @@ $lang['admin']['credentials_transport_warning'] = 'Warning: Adding a new
$lang['admin']['destination'] = 'Destination';
$lang['admin']['nexthop'] = 'Next hop';
+$lang['admin']['oauth2_info'] = 'The OAuth2 implementation supports the grant type "Authorization Code" and issues refresh tokens.
+The server also automatically issues new refresh tokens, after a refresh token has been used.
+→ The default scope is profile. Only mailbox users can be authenticated against OAuth2. If the scope parameter is omitted, it falls back to profile.
+→ The state parameter is required to be sent by the client as part of the authorize request.
+Pathes for requests to the OAuth2 API:
+
+
Authorization endpoint: /oauth/authorize
+
Token endpoint: /oauth/token
+
Resource page: /oauth/profile
+
+Regenerating the client secret will not expire existing authorization codes, but they will fail to renew their token.
+Revoking client tokens will cause immediate termination of all active sessions. All clients need to re-authenticate.';
+
+$lang['admin']['oauth2_client_id'] = "Client ID";
+$lang['admin']['oauth2_client_secret'] = "Client secret";
+$lang['admin']['oauth2_redirect_uri'] = "Redirect URI";
+$lang['admin']['oauth2_revoke_tokens'] = 'Revoke all client tokens';
+$lang['admin']['oauth2_renew_secret'] = 'Generate new client secret';
+$lang['edit']['client_id'] = 'Client ID';
+$lang['edit']['client_secret'] = 'Client secret';
+$lang['edit']['scope'] = 'Scope';
+$lang['edit']['grant_types'] = 'Grant types';
+$lang['edit']['redirect_uri'] = 'Redirect/Callback URL';
+$lang['oauth2']['scope_ask_permission'] = 'An application asked for the following permissions';
+$lang['oauth2']['profile'] = 'Profile';
+$lang['oauth2']['profile_desc'] = 'View personal information: username, full name, created, modified, active';
+$lang['oauth2']['permit'] = 'Authorize application';
+$lang['oauth2']['authorize_app'] = 'Authorize application';
+$lang['oauth2']['deny'] = 'Deny';
+$lang['oauth2']['access_denied'] = 'Please login as mailbox owner to grant access via OAuth2.';
+
+
$lang['success']['forwarding_host_removed'] = "Forwarding host %s has been removed";
$lang['success']['forwarding_host_added'] = "Forwarding host %s has been added";
$lang['success']['relayhost_removed'] = "Map entry %s has been removed";
@@ -727,7 +754,7 @@ $lang['admin']['help_text'] = "Override help text below login mask (HTML allowed
$lang['admin']['title_name'] = '"mailcow UI" website title';
$lang['admin']['main_name'] = '"mailcow UI" name';
$lang['admin']['apps_name'] = '"mailcow Apps" name';
-$lang['admin']['ui_impress'] = 'Impress, Footer note (HTML allowed)';
+$lang['admin']['ui_footer'] = 'Footer (HTML allowed)';
$lang['admin']['customize'] = "Customize";
$lang['admin']['change_logo'] = "Change logo";
@@ -864,14 +891,6 @@ $lang['mailbox']['add_recipient_map_entry'] = 'Add recipient map';
$lang['danger']['tls_policy_map_parameter_invalid'] = "Policy parameter is invalid";
$lang['danger']['temp_error'] = "Temporary error";
-$lang['oauth2']['scope_ask_permission'] = 'An application asked for the following permissions';
-$lang['oauth2']['profile'] = 'Profile';
-$lang['oauth2']['profile_desc'] = 'View personal information: username, full name, created, modified, active';
-$lang['oauth2']['permit'] = 'Authorize application';
-$lang['oauth2']['authorize_app'] = 'Authorize application';
-$lang['oauth2']['deny'] = 'Deny';
-$lang['oauth2']['access_denied'] = 'Please login as mailbox owner to grant access via OAuth2.';
-
$lang['admin']['sys_mails'] = 'System mails';
$lang['admin']['subject'] = 'Subject';
$lang['admin']['from'] = 'From';
diff --git a/data/web/lang/lang.es.php b/data/web/lang/lang.es.php
index 4e3aafa9..d93c185f 100644
--- a/data/web/lang/lang.es.php
+++ b/data/web/lang/lang.es.php
@@ -119,7 +119,7 @@ $lang['user']['tls_enforce_out'] = 'Aplicar TLS saliente';
$lang['mailbox']['tls_enforce_in'] = 'Aplicar TLS entrante';
$lang['mailbox']['tls_enforce_out'] = 'Aplicar TLS saliente';
$lang['mailbox']['tls_map_dest'] = 'Destino';
-$lang['mailbox']['tls_map_dest_info'] = 'Ejemplos: example.org, .example.org, mail@example.org, [mail.example.org]:25';
+$lang['mailbox']['tls_map_dest_info'] = 'Ejemplos: example.org, .example.org, [mail.example.org]:25';
$lang['mailbox']['tls_map_policy'] = 'Póliza';
$lang['mailbox']['tls_map_parameters'] = 'Parametros';
$lang['mailbox']['tls_map_parameters_info'] = 'Vacío o parametros, por ejemplo: protocols=!SSLv2 ciphers=medium exclude=3DES';
diff --git a/data/web/lang/lang.nl.php b/data/web/lang/lang.nl.php
index 85812380..b0c36107 100644
--- a/data/web/lang/lang.nl.php
+++ b/data/web/lang/lang.nl.php
@@ -272,7 +272,7 @@ $lang['mailbox']['tls_policy_maps_info'] = 'Deze opties worden boven het versleu
$lang['mailbox']['tls_enforce_in'] = 'Forceer inkomende versleuteling';
$lang['mailbox']['tls_enforce_out'] = 'Forceer uitgaande versleuteling';
$lang['mailbox']['tls_map_dest'] = 'Bestemming';
-$lang['mailbox']['tls_map_dest_info'] = 'Voorbeeld: example.org, .example.org, mail@example.org, [mail.example.org]:25';
+$lang['mailbox']['tls_map_dest_info'] = 'Voorbeeld: example.org, .example.org, [mail.example.org]:25';
$lang['mailbox']['tls_map_policy'] = 'Beleid';
$lang['mailbox']['tls_map_parameters'] = 'Parameters';
$lang['mailbox']['tls_map_parameters_info'] = 'Voorbeeld: protocols=!SSLv2 ciphers=medium exclude=3DES';
@@ -710,7 +710,7 @@ $lang['admin']['help_text'] = "Hulpteksten onder inlogvenster (HTML toegestaan)"
$lang['admin']['title_name'] = '"Mailcow" (website-titel)';
$lang['admin']['main_name'] = '"Mailcow"';
$lang['admin']['apps_name'] = '"Mailcow-apps"';
-$lang['admin']['ui_impress'] = 'Footer-vermelding (HTML toegestaan)';
+$lang['admin']['ui_footer'] = 'Footer-vermelding (HTML toegestaan)';
$lang['admin']['customize'] = "Uiterlijk";
$lang['admin']['change_logo'] = "Logo";
diff --git a/data/web/modals/admin.php b/data/web/modals/admin.php
index 2303519e..ae23d63a 100644
--- a/data/web/modals/admin.php
+++ b/data/web/modals/admin.php
@@ -105,6 +105,32 @@ if (!isset($_SESSION['mailcow_cc_role'])) {