This commit is contained in:
h44z 2026-01-10 12:28:32 +01:00 committed by GitHub
commit b43034683f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 66 additions and 9 deletions

View file

@ -18,6 +18,7 @@ function oauth2($_action, $_type, $_data = null) {
$client_id = bin2hex(random_bytes(6));
$client_secret = bin2hex(random_bytes(12));
$redirect_uri = $_data['redirect_uri'];
$trusted = $_data['trusted'] ?? 0;
$scope = 'profile';
// For future use
// $grant_type = isset($_data['grant_type']) ? $_data['grant_type'] : 'authorization_code';
@ -50,13 +51,14 @@ function oauth2($_action, $_type, $_data = null) {
);
return false;
}
$stmt = $pdo->prepare("INSERT INTO `oauth_clients` (`client_id`, `client_secret`, `redirect_uri`, `scope`)
VALUES (:client_id, :client_secret, :redirect_uri, :scope)");
$stmt = $pdo->prepare("INSERT INTO `oauth_clients` (`client_id`, `client_secret`, `redirect_uri`, `scope`, `trusted`)
VALUES (:client_id, :client_secret, :redirect_uri, :scope, :trusted)");
$stmt->execute(array(
':client_id' => $client_id,
':client_secret' => $client_secret,
':redirect_uri' => $redirect_uri,
':scope' => $scope
':scope' => $scope,
':trusted' => $trusted
));
$_SESSION['return'][] = array(
'type' => 'success',
@ -74,6 +76,7 @@ function oauth2($_action, $_type, $_data = null) {
$is_now = oauth2('details', 'client', $id);
if (!empty($is_now)) {
$redirect_uri = (!empty($_data['redirect_uri'])) ? $_data['redirect_uri'] : $is_now['redirect_uri'];
$trusted = $_data['trusted'] ?? 0;
}
else {
$_SESSION['return'][] = array(
@ -128,11 +131,13 @@ function oauth2($_action, $_type, $_data = null) {
continue;
}
$stmt = $pdo->prepare("UPDATE `oauth_clients` SET
`redirect_uri` = :redirect_uri
`redirect_uri` = :redirect_uri,
`trusted` = :trusted
WHERE `id` = :id");
$stmt->execute(array(
':id' => $id,
':redirect_uri' => $redirect_uri
':redirect_uri' => $redirect_uri,
':trusted' => $trusted
));
$_SESSION['return'][] = array(
'type' => 'success',
@ -238,5 +243,25 @@ function oauth2($_action, $_type, $_data = null) {
break;
}
break;
case 'details_by_client_id':
switch ($_type) {
case 'client':
$stmt = $pdo->prepare("SELECT * FROM `oauth_clients`
WHERE `client_id` = :client_id");
$stmt->execute(array(':client_id' => $_data));
$oauth_client_details = $stmt->fetch(PDO::FETCH_ASSOC);
return $oauth_client_details;
break;
}
break;
}
}
function oauth2trusted($_client_id) {
global $pdo;
$stmt = $pdo->prepare("SELECT `trusted` FROM `oauth_clients`
WHERE `client_id` = :client_id");
$stmt->execute(array(':client_id' => $_client_id));
$oauth_client_details = $stmt->fetch(PDO::FETCH_ASSOC);
return $oauth_client_details['trusted'] ?? 0;
}

View file

@ -4,7 +4,7 @@ function init_db_schema()
try {
global $pdo;
$db_version = "10312025_0525";
$db_version = "12152025_1550";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@ -1089,7 +1089,8 @@ function init_db_schema()
"redirect_uri" => "VARCHAR(2000)",
"grant_types" => "VARCHAR(80)",
"scope" => "VARCHAR(4000)",
"user_id" => "VARCHAR(80)"
"user_id" => "VARCHAR(80)",
"trusted" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(

View file

@ -210,6 +210,13 @@ jQuery(function($){
data: 'redirect_uri',
defaultContent: ''
},
{
title: lang.oauth2_trusted,
data: 'trusted',
searchable: false,
orderable: false,
defaultContent: ''
},
{
title: lang.action,
data: 'action',

View file

@ -285,6 +285,8 @@
"oauth2_redirect_uri": "Redirect-URI",
"oauth2_renew_secret": "Neues Client Secret generieren",
"oauth2_revoke_tokens": "Alle Client Tokens entfernen",
"oauth2_trusted": "Trusted",
"oauth2_trusted_client": "Trusted Client (Zustimmungsbildschirm überspringen)",
"optional": "Optional",
"options": "Einstellungen",
"password": "Passwort",
@ -726,6 +728,7 @@
"multiple_bookings": "Mehrfaches Buchen",
"nexthop": "Next Hop",
"none_inherit": "Keine Auswahl / Erben",
"oauth2_trusted_client": "Trusted Client (Zustimmungsbildschirm überspringen)",
"password": "Passwort",
"password_recovery_email": "E-Mail zur Passwortwiederherstellung",
"password_repeat": "Passwort wiederholen",

View file

@ -294,6 +294,8 @@
"oauth2_redirect_uri": "Redirect URI",
"oauth2_renew_secret": "Generate new client secret",
"oauth2_revoke_tokens": "Revoke all client tokens",
"oauth2_trusted": "Trusted",
"oauth2_trusted_client": "Trusted client (skip consent screen)",
"optional": "optional",
"options": "Options",
"password": "Password",
@ -725,6 +727,7 @@
"mta_sts_mx_notice": "Multiple MX servers can be specified (separated by commas).",
"multiple_bookings": "Multiple bookings",
"none_inherit": "None / Inherit",
"oauth2_trusted_client": "Trusted client (skip consent screen)",
"nexthop": "Next hop",
"password": "Password",
"password_recovery_email": "Password recovery email",

View file

@ -4,6 +4,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
if (!isset($_SESSION['mailcow_cc_role'])) {
$_SESSION['oauth2_request'] = $_SERVER['REQUEST_URI'];
header('Location: /?oauth');
exit;
}
$request = OAuth2\Request::createFromGlobals();
@ -14,7 +15,10 @@ if (!$oauth2_server->validateAuthorizeRequest($request, $response)) {
exit;
}
if (!isset($_POST['authorized'])) {
$client_id = $request->query('client_id', $request->request('client_id'));
$trusted_client = oauth2trusted($client_id);
if ($trusted_client == 0 && !isset($_POST['authorized'])) {
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
$template = 'oauth/authorize.twig';
@ -25,7 +29,7 @@ if (!isset($_POST['authorized'])) {
}
// print the authorization code if the user has authorized your client
$is_authorized = ($_POST['authorized'] == '1');
$is_authorized = ($trusted_client == 1 || $_POST['authorized'] == '1');
$oauth2_server->handleAuthorizeRequest($request, $response, $is_authorized, $_SESSION['mailcow_cc_username']);
if ($is_authorized) {
unset($_SESSION['oauth2_request']);

View file

@ -28,6 +28,13 @@
<input type="text" class="form-control" name="redirect_uri" id="redirect_uri" value="{{ result.redirect_uri }}">
</div>
</div>
<div class="row mb-4">
<div class="offset-sm-2 col-sm-10">
<div class="form-check">
<label><input type="checkbox" class="form-check-input" value="1" name="trusted"{% if result.trusted == '1' %} checked{% endif %}> {{ lang.edit.oauth2_trusted_client }}</label>
</div>
</div>
</div>
<div class="row">
<div class="offset-sm-2 col-sm-10">
<button class="btn btn-xs-lg d-block d-sm-inline btn-secondary" data-action="edit_selected" data-id="oauth2client" data-item="{{ oauth2client }}" data-api-url='edit/oauth2-client' data-api-attr='{}' href="#">{{ lang.admin.save }}</button>

View file

@ -140,6 +140,13 @@
<input type="text" class="form-control" name="redirect_uri" required>
</div>
</div>
<div class="row mb-4">
<div class="offset-sm-2 col-sm-10">
<div class="form-check">
<label><input type="checkbox" class="form-check-input" value="1" name="trusted"> {{ lang.admin.oauth2_trusted_client }}</label>
</div>
</div>
</div>
<div class="row mb-4">
<div class="offset-sm-2 col-sm-10">
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_oauth2_client" data-api-url='add/oauth2-client' data-api-attr='{}' href="#"><i class="bi bi-plus-lg"></i> {{ lang.admin.add }}</button>