Weave Code
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

Oauth2 Server Bundle Laravel Package

bshaffer/oauth2-server-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for First Use

  1. Install the Bundle

    composer require bshaffer/oauth2-server-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        Bshaffer\OAuth2ServerBundle\OAuth2ServerBundle::class => ['all' => true],
    ];
    
  2. Configure Database & Clients Run migrations (if using Doctrine) to create oauth_clients, oauth_access_tokens, and oauth_auth_codes tables. Example client creation via CLI:

    php bin/console doctrine:fixtures:load --append --no-interaction
    

    (Use Fixtures/OAuthClientFixtures.php or create your own.)

  3. First Token Request Test the /token endpoint with curl:

    curl -X POST http://your-app.com/token \
      -d "grant_type=client_credentials" \
      -d "client_id=your_client_id" \
      -d "client_secret=your_client_secret"
    

    Expected response: {"access_token":"...", "token_type":"Bearer", "expires_in":3600}

  4. Key Configuration Files

    • config/packages/oauth2_server.yaml (default paths, grant types, etc.)
    • config/packages/security.yaml (for user credentials grant, if enabled).

Implementation Patterns

Core Workflows

  1. Grant Type Handling

    • Client Credentials: Machine-to-machine auth (no user involved).
      $server->addGrantType(new \Bshaffer\OAuth2\Grant\ClientCredentials());
      
    • Authorization Code: Web apps (redirects to /authorize).
      $server->addGrantType(new \Bshaffer\OAuth2\Grant\AuthorizationCode());
      
    • User Credentials: Username/password flow (deprecated in OAuth2 but supported).
      $server->addGrantType(new \Bshaffer\OAuth2\Grant\UserCredentials());
      
    • Refresh Token: Extend token lifespan.
      $server->addGrantType(new \Bshaffer\OAuth2\Grant\RefreshToken());
      
  2. Customizing the /authorize Endpoint Extend the controller to add UI or logic:

    // src/Controller/OAuthController.php
    namespace App\Controller;
    
    use Bshaffer\OAuth2ServerBundle\Controller\TokenController;
    use Symfony\Component\HttpFoundation\Request;
    
    class OAuthController extends TokenController
    {
        public function authorizeAction(Request $request)
        {
            // Custom logic (e.g., redirect to login if unauthenticated)
            return parent::authorizeAction($request);
        }
    }
    

    Update routing (config/routes.yaml):

    oauth_authorize:
        path:     /authorize
        defaults: { _controller: App\Controller\OAuthController::authorizeAction }
    
  3. Token Storage & Validation Implement custom storage for tokens/authorizations:

    // src/OAuth/Storage/DoctrineTokenStorage.php
    use Bshaffer\OAuth2\Storage\TokenStorageInterface;
    
    class DoctrineTokenStorage implements TokenStorageInterface
    {
        public function getAccessToken($token)
        {
            // Query your DB for the token
        }
    
        public function setAccessToken($tokenEntity)
        {
            // Save to DB
        }
    }
    

    Register in services.yaml:

    services:
        oauth2.storage.token:
            class: App\OAuth\Storage\DoctrineTokenStorage
            tags:
                - { name: oauth2.storage.token }
    
  4. Scopes & Permissions Define scopes in the client table (e.g., read write). Enforce them in your API:

    // src/EventListener/OAuthScopeListener.php
    use Symfony\Component\HttpKernel\Event\ControllerEvent;
    
    class OAuthScopeListener
    {
        public function onKernelController(ControllerEvent $event)
        {
            $request = $event->getRequest();
            $token = $request->attributes->get('oauth_token');
            if (!$token->getScope()->hasScope('read')) {
                throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
            }
        }
    }
    
  5. Integration with Symfony Security Use OAuth tokens for API authentication:

    # config/packages/security.yaml
    firewalls:
        api:
            pattern: ^/api
            stateless: true
            provider: oauth_token
            oauth_token:
                check_path: /login_check
                services:
                    - App\Security\OAuthTokenAuthenticator
    

Integration Tips

  • Laravel-Specific Adaptation: While this bundle is Symfony-focused, leverage it in Laravel via:

    1. Symfony Bridge: Use laravel/symfony-bundle to integrate Symfony components.
    2. Standalone PHP: Extract the oauth2-server-php library and adapt its classes to Laravel’s DI container.
    3. API Middleware: Create a Laravel middleware to validate tokens:
      // app/Http/Middleware/OAuthValidate.php
      public function handle($request, Closure $next)
      {
          $server = new \Bshaffer\OAuth2\Server();
          $server->addStorage(new \Bshaffer\OAuth2\Storage\Pdo());
          $request = $server->validateAuthenticatedRequest($request);
          return $next($request);
      }
      
  • Testing Tokens: Use HttpFoundation to mock requests in PHPUnit:

    $request = new Request([], [
        'grant_type' => 'client_credentials',
        'client_id' => 'test_client',
        'client_secret' => 'test_secret',
    ]);
    $response = $this->get('oauth2.response');
    $server = $this->get('oauth2.server');
    $server->handleTokenRequest($request, $response);
    $this->assertTrue($response->isSuccessful());
    

Gotchas and Tips

Common Pitfalls

  1. Deprecated Grant Types

    • The User Credentials grant (password) is deprecated in OAuth2 (RFC 6749). Avoid using it in production unless absolutely necessary.
    • Fix: Use Authorization Code with PKCE for web apps or Client Credentials for machine-to-machine.
  2. CSRF in Authorization Code Flow

    • The bundle does not enforce CSRF protection for the /authorize endpoint by default.
    • Fix: Add Symfony’s CSRF token to the redirect URI or use a middleware:
      // src/EventListener/OAuthCsrfListener.php
      public function onKernelRequest(GetResponseEvent $event)
      {
          $request = $event->getRequest();
          if ($request->getPathInfo() === '/authorize' && $request->isMethod('GET')) {
              if (!$request->query->has('_csrf_token')) {
                  throw new \Symfony\Component\HttpKernel\Exception\BadRequestHttpException();
              }
          }
      }
      
  3. Token Expiration Handling

    • Tokens expire silently. Clients must handle 401 Unauthorized and refresh tokens.
    • Tip: Use the expires_in field in the response to inform clients. Example:
      $response->setAccessToken($token);
      $response->setExpiresIn($token->getExpiresAt()->getTimestamp() - time());
      
  4. Database Schema Mismatches

    • The bundle expects specific tables (oauth_clients, oauth_access_tokens). Custom schemas may break functionality.
    • Fix: Extend the storage classes or use a migration tool like DoctrineFixtures to sync schemas.
  5. CORS Issues

    • The /token endpoint may block cross-origin requests if CORS headers are missing.
    • Fix: Add CORS middleware (e.g., nelmio/cors-bundle) and configure it for /token:
      # config/packages/nelmio_cors.yaml
      nelmio_cors:
          defaults:
              allow_origin: ["*"]
              allow_methods: ["POST"]
              allow_headers: ["Authorization", "Content-Type"]
              expose_headers: ["Authorization"]
          paths:
              '^/token':
                  allow_origin: ["*"]
      

Debugging Tips

  1. Enable Verbose Logging Configure Monolog to log OAuth2 events:

    # config/packages/monolog.yaml
    handlers:
        oauth:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.oauth.log"
            level: debug
            channels: ["oauth2"]
    

    Then enable the channel in oauth2_server.yaml:

    oauth2_server:
        logging: true
    
  2. Inspect Request/Response Dump the OAuth2 request/response objects in a controller:

    public function tokenAction()
    {
        $request = $this->get('oauth2.request
    
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle