orchestra/oneauth
OneAuth provides a unified authentication layer for Orchestra Platform and Laravel applications, replacing the default auth setup with a single, extensible system for managing users, credentials, and login flows across your application.
This is the package's first published release (v3.0.0, "Initial version"), so there is no prior assessment, no deprecation surface, and no migration path to plan for. Treat it as a greenfield evaluation: your job in the first hour is to establish what the package actually commits to, not to compare it against v2.
Start here, in this order:
composer.json of the package — the require block is the strongest signal you have. It tells you the supported PHP and illuminate/* ranges, which in turn tells you whether it works on your Laravel version without --ignore-platform-reqs. Also read extra.laravel.providers and extra.laravel.aliases to see whether auto-discovery is wired up or whether you must register the provider by hand.register() vs boot() split — this is where you learn what is bound into the container and what is deferred. Anything bound in register() is fair game to resolve in your own providers; anything in boot() (routes, migrations, publishing, event listeners) happens after yours.config/*.php in the package root — the config file is the de facto documented API. Read every key and its default before writing integration code.CHANGELOG.md / README.md — with a lone "Initial version" note, the README is the only narrative documentation that exists. If it is thin, plan on reading source.Then install and pin:
composer require vendor/package:"^3.0"
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider"
Publish before writing any code — the published config is what you will actually be tuning, and discovering keys later means unpicking assumptions.
For the first use case, do not start in a controller. Run it once from php artisan tinker or inside a throwaway artisan command. That isolates package behaviour from your HTTP stack and confirms credentials, connections, and container bindings resolve before routing, middleware, or validation are in the picture.
Wrap it behind your own boundary. For a first-release dependency, put a thin application-level service or interface in front of the package's entry points and resolve that from the container. Every call site then depends on your class, not the package. When a 3.0.x patch lands, you have exactly one file to audit.
Keep configuration out of the package config file. The published config lives under config/ and is version-controlled, but anything environment-dependent (credentials, endpoints, feature flags, tenant IDs) belongs in config/services.php or your own config file, with the package config referencing env() only at the top level. This keeps config:cache honest and stops secrets from spreading into a file you may re-publish.
Test with the real container, not mocks, first. For an unreleased-to-you package you do not yet know its seams. Write one integration test using RefreshDatabase and the real service provider; only after you understand the call graph should you introduce fakes. Package-level Facade::swap() or bound fakes are useful, but guessing the interface before you have read the source is how you end up testing your mock.
Integrate through the queue if the package touches I/O. Any package that makes HTTP calls, writes files, or talks to a third-party API should be invoked from a job, not inline in a request. This is not a commentary on the package's quality — it is that a first release gives you no performance characteristics to rely on, and a job buys you retries, timeouts, and failed_jobs visibility for free.
Pin the version and pin the lockfile. ^3.0 plus a committed composer.lock is the right posture for a 3.0.0. Do not use * or dev-main. If the package publishes tags actively, review each 3.0.x diff for the first few weeks.
Gate feature adoption on a config flag. If you are rolling it into an existing application, route the new code path behind a config boolean or a Laravel Pennant feature flag so you can disable it in production without a deploy.
"Initial version" is not the same as "stable". A 3.0.0 with no preceding 2.x line means the public API has not been hardened by real-world use. Expect the first few patch releases to contain breaking-ish changes that are technically semver-legal. Budget for one upgrade cycle you did not plan.
Auto-discovery silently does nothing if extra.laravel is malformed. If facades or bindings are missing, check that the provider is listed under extra.laravel.providers in the package's composer.json and that you have run composer dump-autoload. A stale bootstrap/cache/services.php after composer update produces identical symptoms — run php artisan optimize:clear.
Publishing tags may not exist. vendor:publish without --tag will dump every publishable asset including migrations. Always pass --tag= once you know the tags, and run vendor:publish --list if you are unsure.
Package migrations collide with yours. If the package ships migrations, check their timestamps against your existing ones and whether they are loaded via loadMigrationsFrom() (which means they run from the package, and migrate:rollback behaves differently than you expect) or published into database/migrations. Never publish package migrations without renaming them into your own timestamp namespace.
Config caching changes behaviour. A package that reads env() outside its config file works in local development and breaks under php artisan config:cache. Test with the cache enabled at least once before shipping — this is the single most common Laravel integration failure and a first release is exactly where it hides.
Debug by resolving from the container directly. app()->make(Vendor\Package\SomeClass::class) inside tinker will surface binding errors with a real stack trace, which is faster than reading storage/logs/laravel.log after a 500. Follow with php artisan about to confirm your provider is actually booted.
Extension points to identify early. Before building on the package, find out whether it fires events, exposes an interface you can rebind, or offers a manager/driver pattern. If it has none of these, keep your wrapper layer (see above) — it becomes your only extension point.
Report upward, not around it. If you hit a defect, check the issue tracker before patching vendor code. If you must patch, use composer-patches with a committed patch file so the fix is visible and survives composer install.
How can I help you explore Laravel packages today?