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

novosga/oauth-server-bundle

OAuth 2.0 server bundle for the NovoSGA ecosystem, providing authorization and token endpoints so applications can issue access tokens and secure API access. Integrates into PHP projects to handle client authentication, grants, and protected resources.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony 5 bundle, not a Laravel package. If you are working in Laravel, the day-to-day answer is: you will not use this package — you'd reach for Laravel Passport/Sanctum, or consume a Novo SGA instance's /oauth/v2/token endpoint with Http::asForm()->post(...). Everything below assumes you are inside a Symfony 5 app (or evaluating the package to expose OAuth2 from a Novo SGA-adjacent service).

Minimal steps:

  1. Require it and check the platform constraints first — the 2022-03 release targets Symfony 5:

    composer require novosga/oauth-server-bundle
    

    It is a maintained-fork of the abandoned friendsofsymfony/oauth-server-bundle (which wraps bshaffer/oauth2-server-php). Do not expect Symfony 6/7 support.

  2. Register the bundle in config/bundles.php:

    FOS\OAuthServerBundle\FOSOAuthServerBundle::class => ['all' => true],
    
  3. Import the routes in config/routes.yaml:

    fos_oauth_server_token:
        resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml"
    fos_oauth_server_authorize:
        resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml"
    
  4. Configure config/packages/fos_oauth_server.yaml:

    fos_oauth_server:
        db_driver: orm
        client_class:        App\Entity\OAuthClient
        access_token_class:  App\Entity\OAuthAccessToken
        refresh_token_class: App\Entity\OAuthRefreshToken
        auth_code_class:     App\Entity\OAuthAuthCode
        service:
            user_provider: App\Security\UserProvider
            options:
                access_token_lifetime: 3600
                refresh_token_lifetime: 1209600
    
  5. Create entity subclasses extending the bundle's mapped superclasses (FOS\OAuthServerBundle\Entity\Client, AccessToken, RefreshToken, AuthCode) with an id property each, then generate schema:

    bin/console doctrine:migrations:diff
    bin/console doctrine:migrations:migrate
    
  6. Provision a client and hit the token endpoint:

    bin/console fos:oauth-server:create-client --redirect-uri=https://app.example/cb --grant-type=authorization_code
    curl -X POST http://localhost:8000/oauth/v2/token \
      -d grant_type=client_credentials \
      -d client_id=$CLIENT_ID -d client_secret=$CLIENT_SECRET
    

First use case: machine-to-machine client_credentials tokens for an internal API, or authorization_code for a third-party integration that needs to act on behalf of a Novo SGA user.

Implementation Patterns

Pick the grant type per consumer, not per app.

  • client_credentials — service-to-service, no user context. Cheapest to operate.
  • password — trusted first-party clients only (mobile/SPA you control). Requires wiring the user_provider so the bundle can load users by username.
  • authorization_code — third-party apps. This is the only flow that needs the /oauth/v2/auth routes, a login form, and the authorize template.
  • refresh_token — always pair with authorization_code/password; issue short access tokens (15–60 min) and long refresh tokens.

Firewall layout that actually works:

security:
    firewalls:
        oauth_token:
            pattern: ^/oauth/v2/token
            security: false          # must be anonymous
        oauth_authorize:
            pattern: ^/oauth/v2/auth
            form_login:
                provider: app_user_provider
                check_path: /oauth/v2/auth_login_check
                login_path: /oauth/v2/auth_login
            anonymous: lazy
        api:
            pattern: ^/api
            stateless: true
            fos_oauth: true

The fos_oauth: true firewall validates the bearer token and populates the token in the security context; use it rather than hand-rolling a listener.

Override the authorize screen rather than forking the bundle:

templates/bundles/FOSOAuthServerBundle/Authorize/authorize.html.twig

The controller renders this path by convention; replacing the file is the supported extension point.

Programmatic client management (useful for provisioning tenants):

$manager = $container->get('fos_oauth_server.client_manager');
$client = $manager->createClient();
$client->setRedirectUris(['https://tenant.example/cb']);
$client->setAllowedGrantTypes(['authorization_code', 'refresh_token']);
$manager->updateClient($client);
// persist $client->getPublicId() and $client->getSecret() into env/secret store

Protect routes with scopes — the server exposes $server->verifyResourceRequest(); the simplest reliable pattern is to keep fos_oauth: true for authentication and add a small kernel.controller listener or voter for scope checks based on $token->getScope().

Token hygiene — write a scheduled command that deletes rows from the access/refresh token tables where expiresAt < now(). The bundle never cleans up; token tables become the largest tables in the schema within months.

Testing — use WebTestCase + KernelBrowser against /oauth/v2/token, and in unit tests replace fos_oauth_server.server with a mock. For integration suites, seed a dedicated test client via fixture and assert the JSON error shape (error, error_description) rather than status codes alone.

Gotchas and Tips

  • Health check before adoption. 2 stars, last release 2022-03-29, zero dependents, and it is a low-activity fork of a bundle the Symfony community has largely retired. There is no visible security-response process. Pin the exact version in composer.json and put a migration ticket in the backlog the day you install it. The intended successor path is league/oauth2-server with oauth2-server-bundle or a thin PSR-7 bridge.
  • Symfony version trap. Composer will silently resolve against old Symfony polyfills or fail with an opaque conflict. Check composer why-not symfony/framework-bundle 6.4 before you spend time debugging config that "should work" — it won't on Symfony 6+.
  • Missing *_class config = confusing Doctrine errors. If you omit refresh_token_class or auth_code_class, the schema tool produces partial tables and the token endpoint throws during hydration. Configure all four classes even if you only use client_credentials.
  • Doctrine mapping and auto_mapping. The bundle ships XML mappings for its abstract classes; if you disable auto-mapping or scope entity managers, you must register the bundle's mapping explicitly or the inherited fields ($expiresAt, $token, $scope) never appear in the schema.
  • /oauth/v2/token must be anonymous. A form_login-guarded firewall on the whole /oauth prefix is the single most common misconfiguration — the token endpoint returns a login redirect instead of JSON, which clients report as "invalid JSON response."
  • Bearer header stripping. The underlying bshaffer/oauth2-server-php reads Authorization: Bearer and the access_token query/body param. Nginx/Apache under CGI, and some reverse proxies, drop the Authorization header — the symptom is 401 on every call while curl locally succeeds. Confirm with getallheaders() or an echo endpoint behind the same proxy.
  • Refresh tokens are single-use. Two concurrent refresh requests from the same client (e.g., multiple browser tabs) invalidate each other and log the user out. Serialize refresh calls client-side or accept a small grace window by overriding the token controller.
  • Plaintext client secrets. The client manager stores secrets as-is. Treat the DB as a secret store, restrict access, and rotate on exposure — there is no hash-on-write option out of the box.
  • Customizing the token response. Decorate or replace the fos_oauth_server.controller.token service if you need extra claims (e.g., expires_in tuning, tenant id). Avoid editing vendor code; the bundle's service definitions are stable enough to override in services.yaml.
  • Debugging. bin/console debug:container fos_oauth_server.server to inspect grant types; bin/console debug:router | grep oauth to confirm routes; and watch var/log/dev.log for OAuth2\ServerException — the bundle logs the underlying library's exception with the real cause (bad client, expired code, mismatched redirect URI) while the HTTP response only says invalid_grant.
  • Laravel interop. If your Laravel app is the client, nothing here applies — just call the token endpoint with Http::asForm() and store access_token/refresh_token/expires_in; refresh with the refresh_token grant. Do not attempt to install this bundle in a Laravel app.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle