mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2025-12-13 09:56:01 +00:00
Merge pull request #6483 from PseudoResonance/oauth2-redirect-extra-domain
Allow additional domains in OAuth2 redirect URLs
This commit is contained in:
@@ -5847,6 +5847,7 @@ paths:
|
|||||||
client_id: "mailcow_client"
|
client_id: "mailcow_client"
|
||||||
client_secret: "*"
|
client_secret: "*"
|
||||||
redirect_url: "https://mail.mailcow.tld"
|
redirect_url: "https://mail.mailcow.tld"
|
||||||
|
redirect_url_extra: ["https://extramail.mailcow.tld"]
|
||||||
version: "26.1.3"
|
version: "26.1.3"
|
||||||
default_template: "Default"
|
default_template: "Default"
|
||||||
mappers:
|
mappers:
|
||||||
@@ -5900,6 +5901,9 @@ paths:
|
|||||||
redirect_url:
|
redirect_url:
|
||||||
description: The redirect URL that OIDC Provider will use after authentication. Required if `authsource` is keycloak or generic-oidc.
|
description: The redirect URL that OIDC Provider will use after authentication. Required if `authsource` is keycloak or generic-oidc.
|
||||||
type: string
|
type: string
|
||||||
|
redirect_url_extra:
|
||||||
|
description: Additional redirect URLs that OIDC Provider can use after authentication if valid.
|
||||||
|
type: array
|
||||||
version:
|
version:
|
||||||
description: Specifies the Keycloak version. Required if `authsource` is keycloak.
|
description: Specifies the Keycloak version. Required if `authsource` is keycloak.
|
||||||
type: string
|
type: string
|
||||||
@@ -5990,6 +5994,7 @@ paths:
|
|||||||
client_id: "mailcow_client"
|
client_id: "mailcow_client"
|
||||||
client_secret: "Xy7GdPqvJ9m3R8sT2LkVZ5W1oNbCaYQf"
|
client_secret: "Xy7GdPqvJ9m3R8sT2LkVZ5W1oNbCaYQf"
|
||||||
redirect_url: "https://mail.mailcow.tld"
|
redirect_url: "https://mail.mailcow.tld"
|
||||||
|
redirect_url_extra: ["https://extramail.mailcow.tld"]
|
||||||
version: "26.1.3"
|
version: "26.1.3"
|
||||||
default_template: "Default"
|
default_template: "Default"
|
||||||
mappers: ["small_mbox", "medium_mbox"]
|
mappers: ["small_mbox", "medium_mbox"]
|
||||||
@@ -6034,6 +6039,7 @@ paths:
|
|||||||
client_id: "mailcow_client"
|
client_id: "mailcow_client"
|
||||||
client_secret: "Xy7GdPqvJ9m3R8sT2LkVZ5W1oNbCaYQf"
|
client_secret: "Xy7GdPqvJ9m3R8sT2LkVZ5W1oNbCaYQf"
|
||||||
redirect_url: "https://mail.mailcow.tld"
|
redirect_url: "https://mail.mailcow.tld"
|
||||||
|
redirect_url_extra: ["https://extramail.mailcow.tld"]
|
||||||
client_scopes: "openid profile email mailcow_template"
|
client_scopes: "openid profile email mailcow_template"
|
||||||
default_template: "Default"
|
default_template: "Default"
|
||||||
mappers: ["small_mbox", "medium_mbox"]
|
mappers: ["small_mbox", "medium_mbox"]
|
||||||
|
|||||||
@@ -2287,6 +2287,7 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
|
|||||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
foreach($rows as $row){
|
foreach($rows as $row){
|
||||||
switch ($row["key"]) {
|
switch ($row["key"]) {
|
||||||
|
case "redirect_url_extra":
|
||||||
case "mappers":
|
case "mappers":
|
||||||
case "templates":
|
case "templates":
|
||||||
$settings[$row["key"]] = json_decode($row["value"]);
|
$settings[$row["key"]] = json_decode($row["value"]);
|
||||||
@@ -2419,6 +2420,18 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
|
|||||||
}
|
}
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
|
|
||||||
|
// add redirect_url_extra
|
||||||
|
if (isset($_data['redirect_url_extra'])){
|
||||||
|
$_data['redirect_url_extra'] = (!is_array($_data['redirect_url_extra'])) ? array($_data['redirect_url_extra']) : $_data['redirect_url_extra'];
|
||||||
|
|
||||||
|
$redirect_url_extra = array_filter($_data['redirect_url_extra']);
|
||||||
|
$redirect_url_extra = json_encode($redirect_url_extra);
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO identity_provider (`key`, `value`) VALUES ('redirect_url_extra', :value) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);");
|
||||||
|
$stmt->bindParam(':value', $redirect_url_extra);
|
||||||
|
$stmt->execute();
|
||||||
|
}
|
||||||
|
|
||||||
// add default template
|
// add default template
|
||||||
if (isset($_data['default_template'])) {
|
if (isset($_data['default_template'])) {
|
||||||
$_data['default_template'] = (empty($_data['default_template'])) ? "" : $_data['default_template'];
|
$_data['default_template'] = (empty($_data['default_template'])) ? "" : $_data['default_template'];
|
||||||
@@ -2852,7 +2865,19 @@ function identity_provider($_action = null, $_data = null, $_extra = null) {
|
|||||||
case "get-redirect":
|
case "get-redirect":
|
||||||
if ($iam_settings['authsource'] != 'keycloak' && $iam_settings['authsource'] != 'generic-oidc')
|
if ($iam_settings['authsource'] != 'keycloak' && $iam_settings['authsource'] != 'generic-oidc')
|
||||||
return false;
|
return false;
|
||||||
$authUrl = $iam_provider->getAuthorizationUrl();
|
$options = [];
|
||||||
|
if (isset($iam_settings['redirect_url_extra'])) {
|
||||||
|
// check if the current domain is used in an extra redirect URL
|
||||||
|
$targetDomain = strtolower($_SERVER['HTTP_HOST']);
|
||||||
|
foreach ($iam_settings['redirect_url_extra'] as $testUrl) {
|
||||||
|
$testUrlParsed = parse_url($testUrl);
|
||||||
|
if (isset($testUrlParsed['host']) && strtolower($testUrlParsed['host']) == $targetDomain) {
|
||||||
|
$options['redirect_uri'] = $testUrl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$authUrl = $iam_provider->getAuthorizationUrl($options);
|
||||||
$_SESSION['oauth2state'] = $iam_provider->getState();
|
$_SESSION['oauth2state'] = $iam_provider->getState();
|
||||||
return $authUrl;
|
return $authUrl;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -789,6 +789,18 @@ jQuery(function($){
|
|||||||
$('.iam_ldap_rolemap_del').click(async function(e){
|
$('.iam_ldap_rolemap_del').click(async function(e){
|
||||||
deleteAttributeMappingRow(this, e);
|
deleteAttributeMappingRow(this, e);
|
||||||
});
|
});
|
||||||
|
$('.iam_redirect_add_keycloak').click(async function(e){
|
||||||
|
addRedirectUrlRow('#iam_keycloak_redirect_list', '.iam_keycloak_redirect_del', e);
|
||||||
|
});
|
||||||
|
$('.iam_redirect_add_generic').click(async function(e){
|
||||||
|
addRedirectUrlRow('#iam_generic_redirect_list', '.iam_generic_redirect_del', e);
|
||||||
|
});
|
||||||
|
$('.iam_keycloak_redirect_del').click(async function(e){
|
||||||
|
deleteRedirectUrlRow(this, e);
|
||||||
|
});
|
||||||
|
$('.iam_generic_redirect_del').click(async function(e){
|
||||||
|
deleteRedirectUrlRow(this, e);
|
||||||
|
});
|
||||||
// selecting identity provider
|
// selecting identity provider
|
||||||
$('#iam_provider').on('change', function(){
|
$('#iam_provider').on('change', function(){
|
||||||
// toggle password fields
|
// toggle password fields
|
||||||
@@ -833,4 +845,22 @@ jQuery(function($){
|
|||||||
if ($(elem).parent().parent().parent().parent().children().length > 1)
|
if ($(elem).parent().parent().parent().parent().children().length > 1)
|
||||||
$(elem).parent().parent().parent().remove();
|
$(elem).parent().parent().parent().remove();
|
||||||
}
|
}
|
||||||
|
function addRedirectUrlRow(list_id, del_class, e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var parent = $(list_id)
|
||||||
|
$(parent).children().last().clone().appendTo(parent);
|
||||||
|
var newChild = $(parent).children().last();
|
||||||
|
$(newChild).find('input').val('');
|
||||||
|
|
||||||
|
$(del_class).off('click');
|
||||||
|
$(del_class).click(async function(e){
|
||||||
|
deleteRedirectUrlRow(this, e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function deleteRedirectUrlRow(elem, e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if ($(elem).parent().parent().parent().parent().children().length > 2)
|
||||||
|
$(elem).parent().parent().parent().remove();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -64,10 +64,42 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
|
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
|
||||||
<label class="control-label" for="iam_keycloak_redirecturl">{{ lang.admin.iam_redirect_url }}:</label>
|
<label class="control-label">{{ lang.admin.iam_redirect_url }}:</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-9 col-lg-4">
|
<div class="col-12 col-md-9 col-lg-4">
|
||||||
<input type="text" class="form-control" id="iam_keycloak_redirecturl" name="redirect_url" value="{{ iam_settings.redirect_url }}" required>
|
<div class="row px-2 align-items-center">
|
||||||
|
<span class="col-10 p-0 pe-2">
|
||||||
|
<input type="text" class="form-control" name="redirect_url" value="{{ iam_settings.redirect_url }}" required>
|
||||||
|
</span>
|
||||||
|
<div class="col-2 p-0 d-flex">
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-secondary ms-auto iam_redirect_add_keycloak"><i class="bi bi-plus-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2" id="iam_keycloak_redirect_list">
|
||||||
|
<input type="hidden" name="redirect_url_extra" value="">
|
||||||
|
{% for key, url in iam_settings.redirect_url_extra %}
|
||||||
|
<div class="offset-md-3 col-12 col-md-9 col-lg-4 mb-2">
|
||||||
|
<div class="row px-2">
|
||||||
|
<div class="col-10 p-0 pe-2">
|
||||||
|
<input type="text" class="form-control me-2" name="redirect_url_extra" value="{{ iam_settings.redirect_url_extra[key] }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-2 p-0 d-flex">
|
||||||
|
<button class="iam_keycloak_redirect_del btn btn-sm d-block d-sm-inline btn-secondary ms-auto"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="offset-md-3 col-12 col-md-9 col-lg-4 mb-2">
|
||||||
|
<div class="row px-2">
|
||||||
|
<div class="col-10 p-0 pe-2">
|
||||||
|
<input type="text" class="form-control me-2" name="redirect_url_extra" value="">
|
||||||
|
</div>
|
||||||
|
<div class="col-2 p-0 d-flex">
|
||||||
|
<button class="iam_keycloak_redirect_del btn btn-sm d-block d-sm-inline btn-secondary ms-auto"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
@@ -274,10 +306,42 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
|
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
|
||||||
<label class="control-label" for="iam_redirect_url">{{ lang.admin.iam_redirect_url }}:</label>
|
<label class="control-label">{{ lang.admin.iam_redirect_url }}:</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-9 col-lg-4">
|
<div class="col-12 col-md-9 col-lg-4">
|
||||||
<input type="text" class="form-control" id="iam_redirect_url" name="redirect_url" value="{{ iam_settings.redirect_url }}" required>
|
<div class="row px-2 align-items-center">
|
||||||
|
<span class="col-10 p-0 pe-2">
|
||||||
|
<input type="text" class="form-control" name="redirect_url" value="{{ iam_settings.redirect_url }}" required>
|
||||||
|
</span>
|
||||||
|
<div class="col-2 p-0 d-flex">
|
||||||
|
<button class="btn btn-sm d-block d-sm-inline btn-secondary ms-auto iam_redirect_add_generic"><i class="bi bi-plus-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2" id="iam_generic_redirect_list">
|
||||||
|
<input type="hidden" name="redirect_url_extra" value="">
|
||||||
|
{% for key, url in iam_settings.redirect_url_extra %}
|
||||||
|
<div class="offset-md-3 col-12 col-md-9 col-lg-4 mb-2">
|
||||||
|
<div class="row px-2">
|
||||||
|
<div class="col-10 p-0 pe-2">
|
||||||
|
<input type="text" class="form-control me-2" name="redirect_url_extra" value="{{ iam_settings.redirect_url_extra[key] }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-2 p-0 d-flex">
|
||||||
|
<button class="iam_generic_redirect_del btn btn-sm d-block d-sm-inline btn-secondary ms-auto"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="offset-md-3 col-12 col-md-9 col-lg-4 mb-2">
|
||||||
|
<div class="row px-2">
|
||||||
|
<div class="col-10 p-0 pe-2">
|
||||||
|
<input type="text" class="form-control me-2" name="redirect_url_extra" value="">
|
||||||
|
</div>
|
||||||
|
<div class="col-2 p-0 d-flex">
|
||||||
|
<button class="iam_generic_redirect_del btn btn-sm d-block d-sm-inline btn-secondary ms-auto"><i class="bi bi-x-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user