config = new entra_c(); } public function get_users(bool $array = false): array { $accessToken = $this->requestAccessToken(); $usersResponse = $this->requestJson( 'https://graph.microsoft.com/v1.0/users?$select=id,displayName,mail,userPrincipalName', ['Authorization: Bearer ' . $accessToken] ); $users = is_array($usersResponse['value'] ?? null) ? $usersResponse['value'] : []; if (!$array) { return $users; } $result = []; foreach ($users as $user) { if (!is_array($user)) { continue; } $result[] = [ 'id' => $user['id'] ?? null, 'displayName' => $user['displayName'] ?? null, 'mail' => $user['mail'] ?? null, 'userPrincipalName' => $user['userPrincipalName'] ?? null, ]; } return $result; } private function requestAccessToken(): string { $tenantId = trim((string)$this->config->tenant_id->getVariableValue()); $response = $this->requestJson( 'https://login.microsoftonline.com/' . rawurlencode($tenantId) . '/oauth2/v2.0/token', ['Content-Type: application/x-www-form-urlencoded'], http_build_query([ 'client_id' => (string)$this->config->client_id->getVariableValue(), 'client_secret' => (string)$this->config->client_secret->getVariableValue(), 'scope' => 'https://graph.microsoft.com/.default', 'grant_type' => 'client_credentials', ]) ); $token = trim((string)($response['access_token'] ?? '')); if ($token === '') { throw new \RuntimeException('Microsoft Entra token response did not contain an access token.'); } return $token; } /** * @param list $headers * @return array */ private function requestJson(string $url, array $headers, ?string $postFields = null): array { $curl = curl_init($url); if ($curl === false) { throw new \RuntimeException('Unable to initialize Microsoft Entra request.'); } curl_setopt_array($curl, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 20, CURLOPT_HTTPHEADER => $headers, ]); if ($postFields !== null) { curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $postFields); } try { $body = curl_exec($curl); $status = (int)curl_getinfo($curl, CURLINFO_RESPONSE_CODE); if ($body === false) { throw new \RuntimeException('Microsoft Entra request failed: ' . curl_error($curl)); } } finally { curl_close($curl); } $decoded = json_decode((string)$body, true); if ($status < 200 || $status >= 300 || !is_array($decoded)) { $message = is_array($decoded) ? (string)($decoded['error_description'] ?? $decoded['error']['message'] ?? 'Unexpected response') : 'Invalid JSON response'; throw new \RuntimeException('Microsoft Entra request failed with HTTP ' . $status . ': ' . $message); } return $decoded; } }