webfox/laravel-xero-oauth2
A Laravel package for integrating Xero OAuth2 authentication. It streamlines the authorization flow, token storage and refresh, and authenticated Xero API requests, making it easier to connect Laravel applications to Xero.
Architecture fit. The package is a thin Laravel adapter over Xero's official xeroapi/xero-php-oauth2 SDK and the league/oauth2-client stack. It sits in the correct architectural layer for our purposes: it owns the consent/redirect flow, token persistence, and SDK bootstrapping, and exposes the SDK to application code through a service provider, config file, and facade. That is the right shape for a Laravel service — it does not attempt to model accounting domain logic, so it does not fight our own domain layer. If we need Xero Accounting API access for contacts, invoices, or bank transactions, this is the shortest path from zero to a working authenticated client. The package is best treated as infrastructure plumbing, not as a domain abstraction; any business logic (invoice sync rules, reconciliation mapping, retry semantics) must live in our code.
Integration feasibility. High for a first integration, conditional on verification of a small number of unknowns. Expected surface area is a published config file, a migration for a token table, an OAuth callback route/controller, and a facade accessor. That is typically a one-to-two day spike for an experienced Laravel engineer, and the real work is not the package — it is the surrounding concerns: multi-tenant token scoping, refresh scheduling, webhook ingestion, and rate-limit-aware job design. The 59-star count and low composite score are a signal about ecosystem validation, not about code correctness; the package is likely adequate but under-exercised, meaning we will discover edge cases in our environment rather than reading about them.
Technical risk.
xeroapi/xero-php-oauth2 major version, we inherit that SDK's version lag and its generated-model churn.Key questions.
xeroapi/xero-php-oauth2 major version is pinned, and how quickly has the maintainer tracked upstream releases?Stack fit. Good fit for a Laravel monolith or a Laravel-based integration service that already uses service providers, facades, queues, and Eloquent. Poor fit if we are on a non-Laravel runtime, a heavily modular DDD codebase that resists facades, or an event-driven platform where a dedicated Xero connector service is the intended boundary. For a single-tenant or few-tenant back-office application, the package is proportionate. For a multi-tenant SaaS where every customer connects their own Xero organisation, we must wrap the package behind our own XeroConnectionRepository and XeroClientFactory interfaces so the OAuth mechanics are swappable.
Migration path. Two viable routes:
Xero:: facade calls outside a single adapter module. This preserves exit velocity: if the package stalls, we replace the adapter with direct SDK calls and delete the dependency.xeroapi/xero-php-oauth2 plus league/oauth2-client directly. Higher upfront cost (~3–5 days), zero third-party maintenance exposure, full control over token storage and refresh locking. Recommended if Xero is revenue-critical rather than a convenience integration.If we have an existing Xero integration (e.g., drovetech/laravel-xero for OAuth1, or raw API keys), treat this as a greenfield connection: Xero's OAuth 2.0 migration means old tokens cannot be carried forward. Every connected organisation must re-consent. Budget for a customer-facing reconnection campaign, not a silent backend swap.
Compatibility. Gate the decision on a version matrix check before any code is written: Laravel version, PHP version, SDK version, and database driver for the token table. Also confirm the package's config-publishing and migration behaviour under our deploy pipeline (migrations run in CI, config cached in production — config:cache frequently breaks packages that read env() outside config files).
Sequencing.
Maintenance. Low ongoing code maintenance if the package stays healthy — the API surface is small. The real maintenance load is upstream: Xero deprecates API versions and changes scope requirements on its own cadence, and the package's release lag becomes our exposure. Budget roughly one engineer-day per quarter for dependency review plus whatever upstream breaking changes cost. Pin the version, review changelogs on a schedule, and keep the adapter layer thin enough that a fork is a one-day exercise rather than a rewrite.
Support. No commercial support. Community-only via GitHub issues with a single-maintainer response profile. Internal ownership must be explicit: name a code owner for the Xero integration, document the fork procedure, and vendor the package into our repository if the integration becomes customer-facing. Do not let this become "the integration nobody owns."
Scaling. The package itself does not scale — the constraints are Xero's. Xero enforces per-tenant rate limits (roughly 60 calls/minute, 5,000/day, and a small concurrency ceiling), which means throughput scales with tenant count, not with our infrastructure. Design implications: all Xero calls go through queued jobs, per-tenant rate limiters are mandatory, and bulk syncs need batching and checkpointing. Token refresh must be centralised and serialised per tenant — a distributed lock keyed by connection ID is the standard mitigation. Horizontal scaling of our app tier is fine; horizontal scaling of refresh logic is not, unless locked.
Failure modes.
env() reads outside config files fail in production. Verify at spike time.Ramp-up. A Laravel developer unfamiliar with Xero can be productive on the happy path within a day — the consent flow and facade are conventional. Genuine competence takes two to three weeks and comes from the OAuth 2.0 and rate-limit semantics, not from the package. Ramp-up material should cover: the token lifecycle and refresh rules, tenancy/scoping model, queue and retry conventions, webhook contract, and the runbook for "customer says Xero disconnected." Allocate a half-day of pairing to hand over the refresh-locking design specifically; it is the piece most likely to be reimplemented incorrectly by the next engineer.
Recommendation. Conditionally adopt. Use the package behind a strict adapter boundary for a non-critical or single-tenant integration where time-to-first-call matters. For a multi-tenant, revenue-critical Xero integration, prefer the official SDK directly and treat this package as a reference implementation for the consent flow. In both cases, gate on the version-matrix spike and make refresh serialisation an explicit, owned design decision.
How can I help you explore Laravel packages today?