smorken/ms-graph
A Laravel package for integrating Microsoft Graph, making it easy to access Microsoft 365 data and services such as users, mail, calendars, and files through a simple, fluent PHP API.
What we are evaluating. smorken/ms-graph is a thin Laravel wrapper around Microsoft Graph: a service provider plus a publishable config file that registers a Graph client, acquires OAuth2 tokens against the Microsoft identity platform, and exposes a handful of convenience calls for mail, calendar, users, and files through the service container. The value proposition is the wiring — credentials, token handling, HTTP plumbing — not the API surface area.
Architecture fit. Conceptually idiomatic for a Laravel codebase; the service-provider + config-publish pattern is exactly how we would want Graph credentials centralized. The risk is depth. Microsoft Graph is an enormous, versioned surface (identity, mail, calendar, Teams, SharePoint/OneDrive, Intune) and packages of this shape typically cover only the endpoints the author needed. Assume we reach past the wrapper's abstractions within the first sprint — at which point the wrapper is no longer saving us glue code, it is just a dependency we have to keep current. A secondary fit concern: it couples Graph access to a PHP/Laravel package. If a queue worker, a Python data job, or a separate integration service later needs the same tenant, credential and retry policy fragment across two places.
Integration feasibility. Composer can consume a Bitbucket VCS source, but only via an explicit repositories entry, and a private repo requires credentials provisioned on every build agent and developer machine. There is no Packagist listing, which means no discovery signal, no dependents graph, no automated security-advisory feed, and no Dependabot-style update PRs. The install itself is a half-day of work; the real cost is that "install from a VCS branch" is a supply-chain practice we would have to codify and then defend in review.
Technical risk — high, and concentrated in provenance rather than code quality.
| Risk | Evidence | Severity |
|---|---|---|
| Maintenance uncertainty | 0 stars, 0 dependents, score 0, opportunity 30.1; cannot distinguish "new but healthy" from "abandoned after extraction" | High |
| Bus factor of one | Single-author namespace, no visible co-maintainers or contribution process | High |
| Security surface | Sits in the auth path — handles client secrets and bearer tokens; no verifiable disclosure process, unknown token caching/logging behavior | High |
| Licensing ambiguity | No license metadata surfaced | Blocker for commercial use until resolved |
| Availability | Bitbucket repo can be made private or deleted without notice; build breaks unless mirrored internally | Medium |
| Version drift | No stated Laravel/PHP support matrix; illuminate/support constraint must be re-checked at every major upgrade |
Medium |
| Graph API drift | Microsoft deprecates endpoints on its own cadence, not the package's; a stalled wrapper becomes a liability | Medium |
We would be the first external consumer. That means we absorb every defect, every Laravel bump, and every Graph schema change ourselves.
Key questions to resolve before any commitment.
Retry-After and @odata.nextLink pagination?microsoft/microsoft-graph PHP SDK a viable baseline with a real support contract?TPM position. Do not fund this as a production dependency. Its highest-value use to us is as a reference implementation: two engineers reading it for an afternoon will learn more about idiomatic Laravel Graph wiring than from the vendor docs. That is worth a spike, not a roadmap commitment.
Stack fit. Reasonable for a Laravel monolith or a small number of Laravel services needing Graph access. A poor fit for a polyglot estate, or for any organization that already has — or intends to have — a single integration layer where Graph credentials and retry policy live. In that case this package is a second, divergent integration path.
Recommended path, in preference order.
microsoft/microsoft-graph. Define narrow domain interfaces (MailClient, CalendarClient, DirectoryClient), implement them with the official SDK, and keep Graph types out of business logic. Roughly the same effort as wiring the third-party package, and defensible at architecture and security review.smorken/ms-graph anyway, treat it as a fork, not a dependency. Mirror to our VCS, add a LICENSE, take ownership of composer.json, pin to a commit (never a branch), and place our adapter interface in front so replacement is a one-class change.Migration path if adopted.
1.0.0-internal.repositories VCS entry pointing at our mirror; publish config; source credentials from the existing secret store, not .env files on servers.Compatibility. Three independent axes must be verified and re-verified: our Laravel/PHP version against the package's illuminate/support constraint; the package's Graph API version (v1.0 vs beta — beta is not a production target); and the auth model (app-only vs delegated), which determines whether the package is applicable at all.
Sequencing with gates.
Maintenance. Effectively zero external maintenance and therefore full internal ownership. With one consumer, every Graph API change, Laravel major, and PHP bump lands on us. Budget a recurring allowance — realistically a few days a year plus reactive work when Microsoft changes a response shape — and name an owner. Unowned, this decays into an undocumented black box in the auth path.
Support. No vendor, no SLA, no issue tracker we can escalate through. Internal teams will route Graph questions to whoever owns the integration, so document the adapter interface, the credential owner, and the Azure AD app registration in a runbook. Otherwise this becomes tribal knowledge and a single point of failure that outlives the original engineer.
Scaling. Two dimensions. Request volume: a thin wrapper rarely implements token caching, Retry-After backoff, or batching, and Graph throttles aggressively per-tenant — an integration that works in a pilot can 429 in production the first time it runs in a loop. Footprint: as the app's Graph permission set grows from one scope to ten, the security review burden grows with it, and a package we do not control becomes harder to defend each time.
Failure modes to instrument for explicitly.
| Failure | Symptom | Mitigation |
|---|---|---|
| Client secret/certificate expiry | Hard 401 outage, no warning | Expiry monitoring + rotation calendar |
| No token cache | Repeated 429s under load | Cache tokens; single-flight refresh |
No Retry-After handling |
Cascading throttling across jobs | Centralized backoff policy |
| No pagination handling | Silent truncation (e.g. first 100 users) | Explicit paging in adapter, tested |
| Graph schema drift | Silent nulls, failed deserialization | Contract tests + alerting on parse failures |
| Repo disappears / goes private | Build breaks on a fresh agent | Internal mirror, pinned commit |
| Scope creep | Failed security review, delayed release | Least-privilege scope manifest, reviewed quarterly |
Ramp-up. Low for anyone already fluent in Laravel and OAuth2 — a day to read the package, a day to authenticate against a dev tenant. The steeper curve is Microsoft-side, not Laravel-side: Azure AD app registration, admin consent, permission scopes, and tenant policy. Budget for that regardless of which client library we choose; it is the dominant cost and the package does not remove it.
Decision requested. Approve a two-to-three day technical spike and an internal fork if the patterns prove useful — not adoption as a dependency. Success criteria: we can authenticate and call three endpoints we care about, we can state in one page what the wrapper saves versus the official SDK, and we exit with either a fork we are content to own or a clear decision to standardize on Microsoft's SDK behind a thin internal adapter.
How can I help you explore Laravel packages today?