Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Oauth Server Bundle Laravel Package

gregoryeple/oauth-server-bundle

gregoryeple/oauth-server-bundle is a PHP OAuth 2.0 server bundle that adds authorization and token endpoints, client registration, and grant handling to help secure APIs with standards-based authentication and delegated access. It provides server-side pieces for issuing access tokens and protecting...

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first. gregoryeple/oauth-server-bundle is a fork of FOSOAuthServerBundle — a Symfony bundle, not a Laravel package. It will not composer require into a Laravel app in any useful way (it depends on symfony/security-bundle, symfony/http-kernel event wiring, and Doctrine MappedSuperclass entities registered through the bundle's DI container). So "leveraging it day-to-day" from Laravel means one of two things:

  1. You are standing up a separate Symfony OAuth2 authorization server (a small Symfony app) that your Laravel services consume as clients — the bundle runs there, not in Laravel.
  2. You want the pattern, not the package. For 95% of Laravel teams the correct move is laravel/passport (or league/oauth2-server directly). Treat this assessment as "what a FOSOAuthServerBundle server looks like, so you can mirror or interoperate with it."

If you must run the Symfony bundle (e.g. inheriting a legacy auth server):

composer require gregoryeple/oauth-server-bundle
// config/bundles.php
FOS\OAuthServerBundle\FOSOAuthServerBundle::class => ['all' => true],

Then the four-step bootstrap, in order:

  1. Generate a keypair — openssl genrsa -out var/oauth/private.pem 2048 and the matching public key. The bundle does not do this for you; without it every token request 500s on a missing-key error.
  2. Create the three entity classes — Client, AccessToken, RefreshToken (plus AuthCode if you use the authorization-code grant), each extending the bundle's MappedSuperclass base and annotated with your own @ORM\Entity. This is the single biggest source of confusion: the bundle ships mappings, not tables, and doctrine:schema:update only picks them up once your subclasses exist.
  3. Configure fos_oauth_server — db_driver: orm, client_class, access_token_class, refresh_token_class, auth_code_class, service.user_provider, and options.access_token_lifetime.
  4. Wire the security firewall — register the oauth2 security listener on your API firewall and protect the token endpoint (/oauth/v2/token) as security: false.

Where to look first: the upstream FriendsOfSymfony/FOSOAuthServerBundle docs (this fork's README is thin and the upstream is where the real documentation lives), then DependencyInjection/Configuration.php in the vendor tree to see the actual supported config keys for the version you pinned.

First use case: the password grant for a first-party mobile app. It needs no redirect dance and no login UI — just POST /oauth/v2/token with grant_type=password, client_id, client_secret, username, password, and you get back access_token + refresh_token. Create the client row directly via SQL or a one-off console command; there is no admin UI in the bundle.

Implementation Patterns

Extend, never map directly. All persisted models are abstract in the bundle. Your app owns the schema:

// src/Entity/Client.php
use FOS\OAuthServerBundle\Entity\Client as BaseClient;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class Client extends BaseClient {}

Do the same for tokens. The subclasses inherit the MappedSuperclass columns, which is why the bundle's Configuration.php insists on class parameters rather than table names.

Grant-type selection is a config decision, not code. authorization_code for third-party apps with a consent screen, password for first-party trusted clients, client_credentials for machine-to-machine, refresh_token for anything long-lived. Each enabled grant is a service tagged fos_oauth_server.grant_extension; you can attach your own by implementing GrantExtensionInterface and tagging it — this is the extension point people miss when they need a custom assertion (e.g. tenant-scoped grants).

Custom user provider. The bundle delegates authentication to whatever you point service.user_provider at. In a Symfony app that's typically FOSUserBundle; the interface is just loadUserByUsername. Keep this thin — the bundle calls it on every token mint, and any expensive lookup there is a per-request tax.

Token lifecycle in daily work. Access tokens are opaque, stored in the DB, and looked up by the oauth2 firewall listener on every request. So:

  • GET /api/me with Authorization: Bearer <token> is the smoke test.
  • Expiry is access_token_lifetime (seconds, default 3600). Refresh tokens are rotated by the refresh_token grant — old rows are removed and new ones issued, so don't cache refresh tokens client-side beyond what you must.
  • Cleanup is your job. Nothing in the bundle prunes expired tokens. Add a console command cron (DELETE FROM access_token WHERE expires_at < NOW()) or you'll accumulate millions of dead rows within months. This is the most common operational debt in FOSOAuthServerBundle deployments.

Client provisioning without an admin UI. Write a app:oauth:create-client console command early. You need it on day one and every time a partner integrates. Generate random_bytes(32) for both the public id and secret, store the secret hashed only if your fork supports it (upstream historically stores it in plaintext — check before you promise otherwise to a security reviewer).

Interop with Laravel. A Laravel app consuming this server doesn't need Passport. Use league/oauth2-client with the generic provider, or a small Guzzle wrapper around /oauth/v2/token. Point your Laravel config at the Symfony host and cache the token in the Laravel cache with a TTL slightly under access_token_lifetime; add a retry-once-on-401 that refreshes and replays. Keep the client credentials in Laravel's config/services.php, never in the frontend bundle.

Gotchas and Tips

Abandoned-by-community risk is the headline. This fork has 0 stars, 0 dependents, and its last release was June 2023. It is not the canonical package. Before adopting:

  • Diff the fork against FriendsOfSymfony/FOSOAuthServerBundle and confirm the delta is intentional (PHP 8.1/8.2 support, Symfony 6 fixes) rather than an unreviewed snapshot.
  • Audit the branch for anything touching token generation, secret comparison, or randomness. A 0-star auth-server fork is an unusually high-value supply-chain target — you are trusting whoever pushed it, and there is no downstream scrutiny to catch a bad release.
  • Pin the exact version in composer.lock and mirror the repo internally if you depend on it. With no dependents, a force-push or deleted tag would go unnoticed.

Version-matrix heartburn. The bundle's Symfony constraints are narrow and its PHPUnit/PHP floor lags. Expect to fight composer why-not against Symfony 7. If you're on a modern Symfony, check whether the fork was cut for that version or in spite of it. The failure mode is usually a deprecation-to-error at container compile time, not at runtime — so it fails loudly and early, which is the good news.

Keys and permissions. openssl keys must be readable by the PHP-FPM user and nothing else, and must not live in public/. The classic bug is a keypair generated on the dev machine with a passphrase that production can't decrypt — the bundle reports this as an opaque oauth2_server exception, not "bad key." Test the key load path in a staging deploy, not just on your laptop.

CORS on the token endpoint. Browsers hit /oauth/v2/token from SPAs, which means a preflight. The bundle doesn't ship CORS handling; pair it with nelmio/cors-bundle scoped to that path only, and be deliberate about whether you allow Authorization on the preflight (you usually shouldn't need it there).

Opaque tokens mean DB on every request. There's no JWT option here. If the token lookup is a hot path, index access_token.token and put a Redis cache in front of the lookup — but invalidate on revoke, and remember refresh_token rotation writes through. Debugging hint: enable the Symfony profiler's Doctrine panel and count queries on a single authenticated request; if you see more than two, something is re-loading the client on every call.

Error responses are not RFC 6749 by default in edge cases. Malformed grants return the OAuth error body, but a bad client id or a listener exception can leak a Symfony error page. Assert on invalid_client, invalid_grant, invalid_scope in your integration tests — clients will branch on error, and a 500 in place of a 400 breaks retry logic.

Scope handling is minimal. The bundle stores scopes on the token but does not enforce them per-route. You either add a security voter that inspects $token->getScope() or accept coarse-grained authorization. Decide this before you tell partners they get "read-only" tokens.

Final call for a Laravel shop: pass this to a team standing up a Symfony auth server, with the supply-chain caveat above. For everyone else, laravel/passport gives you the same grants, the same opaque-token model, artisan commands for client creation, built-in token pruning (passport:purge), and an actively maintained codebase — at the cost of coupling auth to a Laravel app. Don't adopt a 0-star Symfony fork to solve a Laravel problem.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings