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 Http Client Laravel Package

benjaminfavre/oauth2-http-client

Lightweight OAuth 2 decorator for Symfony HttpClient. Supports standard grant types, fetches and caches access tokens, injects them into requests, and can retry on token expiry. Minimal dependencies (Symfony Contracts + PHP JSON) and highly customizable auth steps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require benjaminfavre/oauth2-http-client
    

    Add to config/app.php under providers:

    BenjaminFavre\OAuth2HttpClient\OAuth2HttpClientServiceProvider::class,
    
  2. First Use Case: Basic OAuth2 Request

    use BenjaminFavre\OAuth2HttpClient\OAuth2HttpClient;
    
    $client = new OAuth2HttpClient(
        new \Symfony\Contracts\HttpClient\HttpClientInterface(),
        'your-client-id',
        'your-client-secret',
        'https://oauth-provider.com/token'
    );
    
    $response = $client->request('GET', 'https://api.example.com/endpoint');
    
  3. Key Files to Review

    • config/oauth2.php (auto-generated after installation)
    • src/OAuth2HttpClient.php (core class)
    • src/OAuth2HttpClientServiceProvider.php (service binding)

Implementation Patterns

Common Workflows

  1. Token Management

    // Cache tokens for 59 minutes (default)
    $client = new OAuth2HttpClient(/* ... */, 3540); // 59m in seconds
    
    // Force token refresh
    $client->request('GET', '...', ['force_refresh' => true]);
    
  2. Scopes and Headers

    // Request with custom scopes
    $response = $client->request('GET', '...', [
        'scopes' => ['read:user', 'write:data']
    ]);
    
    // Add custom headers (merged with Authorization)
    $response = $client->request('GET', '...', [
        'headers' => ['X-Custom-Header' => 'value']
    ]);
    
  3. Integration with Laravel HTTP Client

    use Illuminate\Support\Facades\Http;
    
    $client = new OAuth2HttpClient(
        Http::getDecorator(),
        'client-id',
        'client-secret',
        'https://provider.com/token'
    );
    
    $response = $client->request('GET', 'https://api.example.com/data');
    
  4. Custom Token Endpoint Logic

    $client = new OAuth2HttpClient(/* ... */, null, null, null, function () {
        return [
            'access_token' => 'pre-generated-token',
            'expires_in' => 3600,
            'token_type' => 'Bearer'
        ];
    });
    

Best Practices

  • Use Dependency Injection: Bind the client in AppServiceProvider:
    $this->app->singleton(OAuth2HttpClient::class, function ($app) {
        return new OAuth2HttpClient(
            $app->make(\Symfony\Contracts\HttpClient\HttpClientInterface::class),
            config('oauth2.client_id'),
            config('oauth2.client_secret'),
            config('oauth2.token_endpoint')
        );
    });
    
  • Leverage Laravel’s HTTP Client: Combine with Http::macro() for reusable endpoints:
    Http::macro('oauthGet', function ($url, $scopes = []) use ($client) {
        return $client->request('GET', $url, ['scopes' => $scopes]);
    });
    

Gotchas and Tips

Pitfalls

  1. Token Expiry Handling

    • The package silently refreshes tokens on expiry. Log token refreshes for debugging:
      $client->setTokenRefreshListener(function ($token) {
          \Log::debug('Token refreshed', ['token' => $token]);
      });
      
    • Avoid race conditions: If multiple requests hit the expiry threshold simultaneously, the second request may fail. Use force_refresh or implement a mutex.
  2. Configuration Overrides

    • The config/oauth2.php file is auto-generated but may not reflect all options. Override via:
      $client = new OAuth2HttpClient(/* ... */, null, null, null, null, [
          'grant_type' => 'client_credentials',
          'custom_param' => 'value'
      ]);
      
  3. Symfony HTTP Client Quirks

    • If using Laravel’s HTTP client, ensure the decorator is not double-wrapped:
      // ❌ Wrong: Double decorator
      $client = new OAuth2HttpClient(Http::getDecorator()->getDecorator(), ...);
      
      // ✅ Correct: Single decorator
      $client = new OAuth2HttpClient(Http::getDecorator(), ...);
      
  4. PKCE for Public Clients

    • The package does not support PKCE out of the box. For public clients, use a library like league/oauth2-client alongside this package or implement a custom token endpoint handler.

Debugging Tips

  • Enable Symfony HTTP Client Debug:
    $client = new OAuth2HttpClient(
        Http::withOptions(['debug' => true]),
        ...
    );
    
  • Inspect Token Storage: Tokens are stored in memory by default. For persistence, bind a custom storage:
    $client->setTokenStorage(new \BenjaminFavre\OAuth2HttpClient\Storage\RedisTokenStorage());
    

Extension Points

  1. Custom Token Storage Implement \BenjaminFavre\OAuth2HttpClient\Storage\TokenStorageInterface:

    class DatabaseTokenStorage implements TokenStorageInterface {
        public function get(): ?array { /* ... */ }
        public function save(array $token): void { /* ... */ }
        public function delete(): void { /* ... */ }
    }
    
  2. Token Refresh Logic Override the refreshToken() method in a subclass:

    class CustomOAuth2Client extends OAuth2HttpClient {
        protected function refreshToken(): array {
            // Custom refresh logic (e.g., retry with exponential backoff)
            return parent::refreshToken();
        }
    }
    
  3. Event Listeners Hook into token events:

    $client->onTokenRefresh(function ($token) {
        // Log or broadcast token refresh
    });
    $client->onTokenExpiry(function () {
        // Handle expiry (e.g., notify user)
    });
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui