mirror of
https://github.com/ellite/Wallos.git
synced 2026-07-30 17:55:53 -04:00
266 lines
8.8 KiB
PHP
266 lines
8.8 KiB
PHP
<?php
|
|
|
|
function wallos_get_oidc_defaults()
|
|
{
|
|
return [
|
|
'name' => '',
|
|
'client_id' => '',
|
|
'client_secret' => '',
|
|
'authorization_url' => '',
|
|
'token_url' => '',
|
|
'user_info_url' => '',
|
|
'redirect_url' => '',
|
|
'logout_url' => '',
|
|
'user_identifier_field' => 'sub',
|
|
'scopes' => 'openid email profile',
|
|
'auth_style' => 'auto',
|
|
'auto_create_user' => 0,
|
|
'password_login_disabled' => 0,
|
|
'require_email_verified' => 1,
|
|
];
|
|
}
|
|
|
|
function wallos_get_oidc_env_value($name)
|
|
{
|
|
$value = getenv($name);
|
|
if ($value !== false) {
|
|
return $value;
|
|
}
|
|
|
|
if (array_key_exists($name, $_ENV)) {
|
|
return $_ENV[$name];
|
|
}
|
|
|
|
if (array_key_exists($name, $_SERVER)) {
|
|
return $_SERVER[$name];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function wallos_has_oidc_env_value($name)
|
|
{
|
|
return wallos_get_oidc_env_value($name) !== null;
|
|
}
|
|
|
|
function wallos_parse_oidc_boolean($value)
|
|
{
|
|
if (is_bool($value)) {
|
|
return $value ? 1 : 0;
|
|
}
|
|
|
|
$normalized = strtolower(trim((string) $value));
|
|
if (in_array($normalized, ['1', 'true', 'yes', 'on'], true)) {
|
|
return 1;
|
|
}
|
|
|
|
if (in_array($normalized, ['0', 'false', 'no', 'off'], true)) {
|
|
return 0;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function wallos_get_db_oidc_settings($db)
|
|
{
|
|
$settings = wallos_get_oidc_defaults();
|
|
|
|
$stmt = $db->prepare('SELECT * FROM oauth_settings WHERE id = 1');
|
|
$result = $stmt->execute();
|
|
$row = $result ? $result->fetchArray(SQLITE3_ASSOC) : false;
|
|
|
|
if ($row) {
|
|
unset($row['id']);
|
|
$settings = array_merge($settings, $row);
|
|
}
|
|
|
|
// Column added via ALTER TABLE may return NULL for existing rows in SQLite
|
|
$settings['require_email_verified'] = $settings['require_email_verified'] ?? 1;
|
|
|
|
return $settings;
|
|
}
|
|
|
|
function wallos_get_db_oidc_enabled($db)
|
|
{
|
|
$stmt = $db->prepare('SELECT oidc_oauth_enabled FROM admin WHERE id = 1');
|
|
$result = $stmt->execute();
|
|
$row = $result ? $result->fetchArray(SQLITE3_ASSOC) : false;
|
|
|
|
return $row ? (int) $row['oidc_oauth_enabled'] : 0;
|
|
}
|
|
|
|
function wallos_fetch_oidc_discovery_document($issuer)
|
|
{
|
|
$issuer = rtrim(trim((string) $issuer), '/');
|
|
if ($issuer === '') {
|
|
return [null, 'OIDC_ISSUER is empty.'];
|
|
}
|
|
|
|
$url = $issuer . '/.well-known/openid-configuration';
|
|
$ch = curl_init($url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']);
|
|
$response = curl_exec($ch);
|
|
$httpCode = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
|
|
$curlError = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if ($response === false || $httpCode >= 400) {
|
|
$error = $curlError !== '' ? $curlError : 'HTTP ' . $httpCode;
|
|
return [null, 'OIDC discovery failed for ' . $url . ': ' . $error];
|
|
}
|
|
|
|
$document = json_decode($response, true);
|
|
if (!is_array($document)) {
|
|
return [null, 'OIDC discovery returned invalid JSON for ' . $url . '.'];
|
|
}
|
|
|
|
return [$document, null];
|
|
}
|
|
|
|
function wallos_get_effective_oidc_configuration($db)
|
|
{
|
|
$settings = wallos_get_db_oidc_settings($db);
|
|
$managedFields = [];
|
|
$notes = [];
|
|
$discoveryDocument = null;
|
|
|
|
$enabled = wallos_get_db_oidc_enabled($db);
|
|
if (wallos_has_oidc_env_value('OIDC_ENABLED')) {
|
|
$parsedEnabled = wallos_parse_oidc_boolean(wallos_get_oidc_env_value('OIDC_ENABLED'));
|
|
if ($parsedEnabled !== null) {
|
|
$enabled = $parsedEnabled;
|
|
$managedFields['enabled'] = 'OIDC_ENABLED';
|
|
} else {
|
|
$notes[] = 'Ignoring invalid boolean value in OIDC_ENABLED.';
|
|
}
|
|
}
|
|
|
|
if (wallos_has_oidc_env_value('OIDC_CLIENT_SECRET_FILE')) {
|
|
$managedFields['client_secret'] = 'OIDC_CLIENT_SECRET_FILE';
|
|
$settings['client_secret'] = '';
|
|
$secretFile = trim((string) wallos_get_oidc_env_value('OIDC_CLIENT_SECRET_FILE'));
|
|
|
|
if ($secretFile === '') {
|
|
$notes[] = 'OIDC_CLIENT_SECRET_FILE is empty.';
|
|
} elseif (is_readable($secretFile)) {
|
|
$settings['client_secret'] = rtrim((string) file_get_contents($secretFile), "\r\n");
|
|
} else {
|
|
$notes[] = 'OIDC client secret file is not readable: ' . $secretFile;
|
|
}
|
|
} elseif (wallos_has_oidc_env_value('OIDC_CLIENT_SECRET')) {
|
|
$settings['client_secret'] = (string) wallos_get_oidc_env_value('OIDC_CLIENT_SECRET');
|
|
$managedFields['client_secret'] = 'OIDC_CLIENT_SECRET';
|
|
}
|
|
|
|
if (wallos_has_oidc_env_value('OIDC_AUTO_CREATE_USER')) {
|
|
$parsedValue = wallos_parse_oidc_boolean(wallos_get_oidc_env_value('OIDC_AUTO_CREATE_USER'));
|
|
if ($parsedValue !== null) {
|
|
$settings['auto_create_user'] = $parsedValue;
|
|
$managedFields['auto_create_user'] = 'OIDC_AUTO_CREATE_USER';
|
|
} else {
|
|
$notes[] = 'Ignoring invalid boolean value in OIDC_AUTO_CREATE_USER.';
|
|
}
|
|
}
|
|
|
|
if (wallos_has_oidc_env_value('OIDC_DISABLE_PASSWORD_LOGIN')) {
|
|
$parsedValue = wallos_parse_oidc_boolean(wallos_get_oidc_env_value('OIDC_DISABLE_PASSWORD_LOGIN'));
|
|
if ($parsedValue !== null) {
|
|
$settings['password_login_disabled'] = $parsedValue;
|
|
$managedFields['password_login_disabled'] = 'OIDC_DISABLE_PASSWORD_LOGIN';
|
|
} else {
|
|
$notes[] = 'Ignoring invalid boolean value in OIDC_DISABLE_PASSWORD_LOGIN.';
|
|
}
|
|
}
|
|
|
|
if (wallos_has_oidc_env_value('OIDC_REQUIRE_EMAIL_VERIFIED')) {
|
|
$parsedValue = wallos_parse_oidc_boolean(wallos_get_oidc_env_value('OIDC_REQUIRE_EMAIL_VERIFIED'));
|
|
if ($parsedValue !== null) {
|
|
$settings['require_email_verified'] = $parsedValue;
|
|
$managedFields['require_email_verified'] = 'OIDC_REQUIRE_EMAIL_VERIFIED';
|
|
} else {
|
|
$notes[] = 'Ignoring invalid boolean value in OIDC_REQUIRE_EMAIL_VERIFIED.';
|
|
}
|
|
}
|
|
|
|
if (wallos_has_oidc_env_value('OIDC_ISSUER')) {
|
|
$issuer = (string) wallos_get_oidc_env_value('OIDC_ISSUER');
|
|
$managedFields['issuer'] = 'OIDC_ISSUER';
|
|
|
|
foreach (['authorization_url', 'token_url', 'user_info_url'] as $field) {
|
|
$settings[$field] = '';
|
|
$managedFields[$field] = 'OIDC_ISSUER';
|
|
}
|
|
|
|
if (trim($issuer) !== '') {
|
|
[$discoveryDocument, $discoveryError] = wallos_fetch_oidc_discovery_document($issuer);
|
|
if ($discoveryError !== null) {
|
|
$notes[] = $discoveryError;
|
|
} elseif ($discoveryDocument !== null) {
|
|
$discoveryMap = [
|
|
'authorization_url' => 'authorization_endpoint',
|
|
'token_url' => 'token_endpoint',
|
|
'user_info_url' => 'userinfo_endpoint',
|
|
];
|
|
|
|
foreach ($discoveryMap as $field => $documentField) {
|
|
if (isset($discoveryDocument[$documentField])) {
|
|
$settings[$field] = $discoveryDocument[$documentField];
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$notes[] = 'Ignoring empty OIDC_ISSUER value.';
|
|
}
|
|
}
|
|
|
|
$envFieldMap = [
|
|
'name' => 'OIDC_PROVIDER_NAME',
|
|
'client_id' => 'OIDC_CLIENT_ID',
|
|
'authorization_url' => 'OIDC_AUTH_URL',
|
|
'token_url' => 'OIDC_TOKEN_URL',
|
|
'user_info_url' => 'OIDC_USERINFO_URL',
|
|
'redirect_url' => 'OIDC_REDIRECT_URL',
|
|
'logout_url' => 'OIDC_LOGOUT_URL',
|
|
'user_identifier_field' => 'OIDC_USER_IDENTIFIER',
|
|
'scopes' => 'OIDC_SCOPES',
|
|
];
|
|
|
|
foreach ($envFieldMap as $field => $envVar) {
|
|
if (wallos_has_oidc_env_value($envVar)) {
|
|
$settings[$field] = (string) wallos_get_oidc_env_value($envVar);
|
|
$managedFields[$field] = $envVar;
|
|
}
|
|
}
|
|
|
|
$requiredFields = [
|
|
'client_id',
|
|
'client_secret',
|
|
'authorization_url',
|
|
'token_url',
|
|
'user_info_url',
|
|
'redirect_url',
|
|
'user_identifier_field',
|
|
];
|
|
$isConfigured = true;
|
|
foreach ($requiredFields as $field) {
|
|
if (trim((string) $settings[$field]) === '') {
|
|
$isConfigured = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'enabled' => (int) $enabled,
|
|
'settings' => $settings,
|
|
'managed_fields' => $managedFields,
|
|
'notes' => $notes,
|
|
'discovery_document' => $discoveryDocument,
|
|
'is_configured' => $isConfigured,
|
|
];
|
|
}
|