fix(microsoft): resolve AADSTS50194 by enforcing tenant-specific endpoint planningsagenda.nl instead of common for single-tenant app
This commit is contained in:
@@ -24,74 +24,100 @@ function microsoft_get_app_config(): array {
|
||||
$clientSecret = fociz_env('MICROSOFT_CLIENT_SECRET', '');
|
||||
$tenantId = fociz_env('MICROSOFT_TENANT_ID', '');
|
||||
|
||||
if (empty($clientId) || empty($clientSecret)) {
|
||||
try {
|
||||
$db = get_db_connection();
|
||||
// Zoek bij actieve beheerder(s) in de integrations tabel
|
||||
$stmt = $db->query("
|
||||
SELECT i.settings
|
||||
FROM integrations i
|
||||
JOIN users u ON i.user_id = u.id
|
||||
WHERE u.role = 'ADMIN' AND i.provider = 'OUTLOOK' AND i.settings IS NOT NULL
|
||||
ORDER BY i.updated_at DESC
|
||||
LIMIT 5
|
||||
try {
|
||||
$db = get_db_connection();
|
||||
$adminOrgDomain = '';
|
||||
|
||||
// Zoek bij actieve beheerder(s) in de integrations tabel
|
||||
$stmt = $db->query("
|
||||
SELECT i.settings, u.email as admin_email
|
||||
FROM integrations i
|
||||
JOIN users u ON i.user_id = u.id
|
||||
WHERE u.role = 'ADMIN' AND i.provider = 'OUTLOOK' AND i.settings IS NOT NULL
|
||||
ORDER BY i.updated_at DESC
|
||||
LIMIT 5
|
||||
");
|
||||
$rows = $stmt->fetchAll();
|
||||
foreach ($rows as $row) {
|
||||
if (!empty($row['admin_email']) && empty($adminOrgDomain)) {
|
||||
$emailParts = explode('@', $row['admin_email']);
|
||||
$domain = strtolower(trim(end($emailParts)));
|
||||
if (!in_array($domain, ['gmail.com', 'outlook.com', 'hotmail.com', 'live.com', 'yahoo.com', 'icloud.com'])) {
|
||||
$adminOrgDomain = $domain;
|
||||
}
|
||||
}
|
||||
if (!empty($row['settings'])) {
|
||||
$saved = json_decode($row['settings'], true) ?: [];
|
||||
if (empty($clientId) && !empty($saved['client_id'])) {
|
||||
$clientId = trim($saved['client_id']);
|
||||
}
|
||||
if (empty($clientSecret) && !empty($saved['client_secret'])) {
|
||||
$clientSecret = trim($saved['client_secret']);
|
||||
}
|
||||
if ((empty($tenantId) || $tenantId === 'common') && !empty($saved['tenant_id']) && $saved['tenant_id'] !== 'common') {
|
||||
$tenantId = trim($saved['tenant_id']);
|
||||
}
|
||||
if (!empty($clientId) && !empty($clientSecret) && !empty($tenantId) && $tenantId !== 'common') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: zoek een willekeurige OUTLOOK rij met ingevulde client_id
|
||||
if (empty($clientId) || empty($clientSecret) || empty($tenantId) || $tenantId === 'common') {
|
||||
$stmtFallback = $db->query("
|
||||
SELECT settings
|
||||
FROM integrations
|
||||
WHERE provider = 'OUTLOOK' AND settings LIKE '%client_id%'
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT 3
|
||||
");
|
||||
$rows = $stmt->fetchAll();
|
||||
foreach ($rows as $row) {
|
||||
if (!empty($row['settings'])) {
|
||||
$saved = json_decode($row['settings'], true) ?: [];
|
||||
$fallbackRows = $stmtFallback->fetchAll();
|
||||
foreach ($fallbackRows as $fbRow) {
|
||||
if (!empty($fbRow['settings'])) {
|
||||
$saved = json_decode($fbRow['settings'], true) ?: [];
|
||||
if (empty($clientId) && !empty($saved['client_id'])) {
|
||||
$clientId = trim($saved['client_id']);
|
||||
}
|
||||
if (empty($clientSecret) && !empty($saved['client_secret'])) {
|
||||
$clientSecret = trim($saved['client_secret']);
|
||||
}
|
||||
if (empty($tenantId) && !empty($saved['tenant_id'])) {
|
||||
if ((empty($tenantId) || $tenantId === 'common') && !empty($saved['tenant_id']) && $saved['tenant_id'] !== 'common') {
|
||||
$tenantId = trim($saved['tenant_id']);
|
||||
}
|
||||
if (!empty($clientId) && !empty($clientSecret)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: zoek een willekeurige OUTLOOK rij met ingevulde client_id
|
||||
if (empty($clientId) || empty($clientSecret)) {
|
||||
$stmtFallback = $db->query("
|
||||
SELECT settings
|
||||
FROM integrations
|
||||
WHERE provider = 'OUTLOOK' AND settings LIKE '%client_id%'
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT 3
|
||||
");
|
||||
$fallbackRows = $stmtFallback->fetchAll();
|
||||
foreach ($fallbackRows as $fbRow) {
|
||||
if (!empty($fbRow['settings'])) {
|
||||
$saved = json_decode($fbRow['settings'], true) ?: [];
|
||||
if (empty($clientId) && !empty($saved['client_id'])) {
|
||||
$clientId = trim($saved['client_id']);
|
||||
}
|
||||
if (empty($clientSecret) && !empty($saved['client_secret'])) {
|
||||
$clientSecret = trim($saved['client_secret']);
|
||||
}
|
||||
if (empty($tenantId) && !empty($saved['tenant_id'])) {
|
||||
$tenantId = trim($saved['tenant_id']);
|
||||
}
|
||||
if (!empty($clientId) && !empty($clientSecret)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
error_log("microsoft_get_app_config error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// Als tenantId nog leeg of 'common' is, leid het domein af van de beheerder
|
||||
if (empty($tenantId) || $tenantId === 'common') {
|
||||
if (empty($adminOrgDomain)) {
|
||||
$firstAdminEmail = $db->query("SELECT email FROM users WHERE role = 'ADMIN' ORDER BY id ASC LIMIT 1")->fetchColumn();
|
||||
if ($firstAdminEmail) {
|
||||
$parts = explode('@', $firstAdminEmail);
|
||||
$domain = strtolower(trim(end($parts)));
|
||||
if (!in_array($domain, ['gmail.com', 'outlook.com', 'hotmail.com', 'live.com', 'yahoo.com', 'icloud.com'])) {
|
||||
$adminOrgDomain = $domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($adminOrgDomain)) {
|
||||
$tenantId = $adminOrgDomain;
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
error_log("microsoft_get_app_config error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// Default tenantId voor de organisatie
|
||||
if (empty($tenantId) || $tenantId === 'common') {
|
||||
$tenantId = 'planningsagenda.nl';
|
||||
}
|
||||
|
||||
return [
|
||||
'client_id' => $clientId ?: '',
|
||||
'client_secret' => $clientSecret ?: '',
|
||||
'tenant_id' => !empty($tenantId) ? $tenantId : 'common',
|
||||
'tenant_id' => $tenantId,
|
||||
'is_configured' => !empty($clientId) && !empty($clientSecret),
|
||||
];
|
||||
}
|
||||
@@ -99,8 +125,8 @@ function microsoft_get_app_config(): array {
|
||||
/**
|
||||
* Genereert de Microsoft OAuth2 login URL
|
||||
*/
|
||||
function microsoft_get_auth_url(string $clientId, string $redirectUri, string $tenantId = 'common', string $state = ''): string {
|
||||
$tenant = !empty($tenantId) ? trim($tenantId) : 'common';
|
||||
function microsoft_get_auth_url(string $clientId, string $redirectUri, string $tenantId = '', string $state = ''): string {
|
||||
$tenant = (!empty($tenantId) && $tenantId !== 'common') ? trim($tenantId) : 'planningsagenda.nl';
|
||||
$baseUrl = sprintf(MS_OAUTH_AUTHORIZE_URL, urlencode($tenant));
|
||||
|
||||
$params = [
|
||||
@@ -119,8 +145,8 @@ function microsoft_get_auth_url(string $clientId, string $redirectUri, string $t
|
||||
/**
|
||||
* Wisselt de ontvangen autorisatiecode om voor access- en refresh tokens
|
||||
*/
|
||||
function microsoft_exchange_code(string $code, string $clientId, string $clientSecret, string $redirectUri, string $tenantId = 'common'): array {
|
||||
$tenant = !empty($tenantId) ? trim($tenantId) : 'common';
|
||||
function microsoft_exchange_code(string $code, string $clientId, string $clientSecret, string $redirectUri, string $tenantId = ''): array {
|
||||
$tenant = (!empty($tenantId) && $tenantId !== 'common') ? trim($tenantId) : 'planningsagenda.nl';
|
||||
$tokenUrl = sprintf(MS_OAUTH_TOKEN_URL, urlencode($tenant));
|
||||
|
||||
$payload = [
|
||||
@@ -210,7 +236,8 @@ function microsoft_get_valid_token(int $userId): ?string {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tokenUrl = sprintf(MS_OAUTH_TOKEN_URL, urlencode(!empty($tenantId) ? $tenantId : 'common'));
|
||||
$cleanTenant = (!empty($tenantId) && $tenantId !== 'common') ? $tenantId : 'planningsagenda.nl';
|
||||
$tokenUrl = sprintf(MS_OAUTH_TOKEN_URL, urlencode($cleanTenant));
|
||||
$payload = [
|
||||
'client_id' => $clientId,
|
||||
'client_secret' => $clientSecret,
|
||||
|
||||
Reference in New Issue
Block a user