-
- Gebruik common of uw specifieke domeinnaam (bijv. planningsagenda.nl)
+
+ Vul uw domeinnaam in (planningsagenda.nl) of de Directory (tenant) ID uit Azure. Let op: Gebruik géén 'common' voor single-tenant apps.
diff --git a/auth/callback_microsoft.php b/auth/callback_microsoft.php
index 6087e3e..c1f00bd 100644
--- a/auth/callback_microsoft.php
+++ b/auth/callback_microsoft.php
@@ -77,7 +77,7 @@ $appConfig = microsoft_get_app_config();
$clientId = $appConfig['client_id'];
$clientSecret = $appConfig['client_secret'];
-$tenantId = $appConfig['tenant_id'];
+$tenantId = (!empty($appConfig['tenant_id']) && $appConfig['tenant_id'] !== 'common') ? $appConfig['tenant_id'] : 'planningsagenda.nl';
if (empty($clientId) || empty($clientSecret)) {
header('Location: /profile.php?error=' . urlencode('Microsoft 365 configuratie (Client ID of Secret) ontbreekt in Fociz. Neem contact op met de beheerder.'));
diff --git a/auth/oauth_microsoft.php b/auth/oauth_microsoft.php
index f30a180..2257126 100644
--- a/auth/oauth_microsoft.php
+++ b/auth/oauth_microsoft.php
@@ -15,6 +15,18 @@ $appConfig = microsoft_get_app_config();
$clientId = !empty($_GET['client_id']) ? trim($_GET['client_id']) : $appConfig['client_id'];
$tenantId = !empty($_GET['tenant_id']) ? trim($_GET['tenant_id']) : $appConfig['tenant_id'];
+// Voorkom AADSTS50194: single-tenant Azure applicaties mogen NOOIT het /common endpoint gebruiken
+if (empty($tenantId) || $tenantId === 'common') {
+ $userEmail = $user['email'] ?? '';
+ $parts = explode('@', $userEmail);
+ $domain = strtolower(trim(end($parts)));
+ if (!empty($domain) && !in_array($domain, ['gmail.com', 'outlook.com', 'hotmail.com', 'live.com', 'yahoo.com', 'icloud.com'])) {
+ $tenantId = $domain;
+ } else {
+ $tenantId = 'planningsagenda.nl';
+ }
+}
+
if (empty($clientId)) {
$err = ($user['role'] === 'ADMIN')
? 'Vul eerst de Application (Client) ID en het Client Secret in bij het Systeembeheer om te koppelen met Microsoft 365.'
diff --git a/includes/integrations/microsoft.php b/includes/integrations/microsoft.php
index 10bea3d..72d7be8 100644
--- a/includes/integrations/microsoft.php
+++ b/includes/integrations/microsoft.php
@@ -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,