Illuminate\Http\Client). The SDK’s promise-based async model (wait()) can be adapted to Laravel’s synchronous/queued task patterns.ClientCredentialContext, AuthorizationCodeContext, OnBehalfOfContext) enable granular integration with Laravel’s authentication stack (e.g., Sanctum, Passport, or custom OAuth providers). The scopes-based permission model maps cleanly to Laravel’s middleware and policy systems.HttpClient via custom GraphRequestAdapter (see docs). This reduces vendor lock-in.AccessTokenCache implementation (e.g., using Laravel’s cache facade) is recommended for persistence.sync promises or queues to avoid blocking requests.ApiException must be mapped to Laravel’s exception hierarchy (e.g., HttpException) for consistent error responses.guzzlehttp/guzzle). Pin versions in composer.json.AuthorizationCodeContext), or will a frontend SPA manage this?retry helper)?clientSecret/certificates be stored (Laravel’s .env, Azure Key Vault, etc.)?Log facade, OpenTelemetry)?GraphServiceClient to the container with configurable auth contexts.HttpClient via a custom GraphRequestAdapter to:
// Example: Custom Request Adapter
$httpClient = app(\Illuminate\Http\Client\PendingRequest::class);
$requestAdapter = new GraphRequestAdapter(
new GraphPhpLeagueAuthenticationProvider($tokenContext),
$httpClient
);
$client = GraphServiceClient::createWithRequestAdapter($requestAdapter);
auth.login) to trigger Graph syncs (e.g., user profile updates).ClientCredentialContext for server-to-server flows (lowest risk).AuthorizationCodeContext with Laravel middleware for OAuth redirects.authCode/redirectUri.OnBehalfOfContext for API-to-API calls.GraphServiceClient->users()->get()->wait() in a job).league/oauth2-client (SDK dependency).guzzlehttp/guzzle (pin versions to avoid breaking changes)..env with TENANT_ID, CLIENT_ID, CLIENT_SECRET.php artisan vendor:publish --provider=MicrosoftGraphServiceProvider).GraphServiceClient to Laravel’s container.users()->get()).users()->create()) with proper authorization checks.Log::debug($request->getUrl(), ['payload' => $request->getBody()])).composer update should be tested in staging.AccessToken::getExpiresAt()).tap() to inspect SDK responses:
$user = $client->me()->get()->wait()->tap(fn($u) => Log::info($u->toJson()));
$httpClient->withMiddleware(function ($handler) {
return function ($request, $options) use ($handler) {
Log::debug('Graph Request:', [$request->getUri(), $options]);
return $handler($request, $options);
};
});
App\Exceptions\Handler:
catch (ApiException $e) {
throw new \Illuminate\Http\JsonResponse([
'error' => $e->getError()->getMessage(),
'code' => $e->getStatusCode(),
], $e->getStatusCode());
}
graph:tokens:{tenantId}) for invalidation.throttle middleware can limit Graph API calls per user/IP.retry helper).GraphServiceClient instances can scale with Laravel’s queue workers.| Failure Scenario | Mitigation |
|---|---|
| Token expiry/refresh failure | Fallback to manual token acquisition (e.g., admin-triggered refresh). |
| Azure AD auth server downtime | Implement circuit breakers (e.g., spatie/flysystem-caching-driver). |
| Microsoft Graph API throttling | Queue retries with jitter (Laravel’s retryAfter header support). |
| Laravel cache failure | Use multi-cache backends (e.g., Redis + database fallback). |
| SDK version incompatibility | Pin SDK version in composer.json and test upgrades in staging. |
config/graph.php with:
'auth'
How can I help you explore Laravel packages today?