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

Oauth Http Client Bundle Laravel Package

edspc/oauth-http-client-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Install the Bundle**
   ```bash
   composer require edspc/oauth-http-client-bundle

Register the bundle in config/bundles.php:

return [
    // ...
    Edspc\OauthHttpClientBundle\EdspcOauthHttpClientBundle::class => ['all' => true],
];
  1. Configure OAuth Providers Update config/packages/edspc_oauth_http_client.yaml with your OAuth provider details (e.g., Zoho):

    edspc_oauth_http_client:
        default_auth: zoho
        auth:
            zoho:
                token_url: 'https://accounts.zoho.com/oauth/v2/token'
                client_id: '%env(ZOHO_CLIENT_ID)%'
                client_secret: '%env(ZOHO_CLIENT_SECRET)%'
    
  2. Define HTTP Services Configure base URIs for API endpoints in the same file:

    http_services:
        desk_client:
            base_uri: 'https://desk.zoho.com/'
        crm_client:
            base_uri: 'https://www.zohoapis.com/crm/v2/'
    
  3. First Use Case: Fetching an Access Token Inject the OAuthHttpClient service and call getAccessToken():

    use Edspc\OauthHttpClientBundle\Service\OAuthHttpClient;
    
    public function __construct(private OAuthHttpClient $oauthClient) {}
    
    public function getToken()
    {
        $token = $this->oauthClient->getAccessToken('zoho', [
            'code' => $authorizationCodeFromUser,
            'grant_type' => 'authorization_code',
            'redirect_uri' => 'https://your-app.com/callback',
        ]);
        return $token;
    }
    
  4. Make an Authenticated API Request Use the createClient() method to generate a Guzzle client with the token:

    $client = $this->oauthClient->createClient('desk_client', $token);
    $response = $client->get('/api/tickets');
    

Implementation Patterns

Workflow: OAuth Flow Integration

  1. Redirect to OAuth Provider Generate an authorization URL using getAuthorizationUrl():

    $url = $this->oauthClient->getAuthorizationUrl('zoho', [
        'response_type' => 'code',
        'scope' => 'ZohoDesk.tickets.ALL',
        'redirect_uri' => 'https://your-app.com/callback',
    ]);
    
  2. Handle Callback Exchange the authorization code for a token in your callback controller:

    public function callback(Request $request)
    {
        $token = $this->oauthClient->getAccessToken('zoho', [
            'code' => $request->query('code'),
            'grant_type' => 'authorization_code',
            'redirect_uri' => 'https://your-app.com/callback',
        ]);
        // Store token (e.g., in session or database)
    }
    
  3. Reuse Token for API Calls Attach the token to requests via the generated client:

    $client = $this->oauthClient->createClient('crm_client', $token);
    $response = $client->post('/Contacts', ['json' => ['data' => [...] ]]);
    

Integration Tips

  • Token Storage: Store tokens in the database or cache (e.g., Redis) with a TokenRepository interface for persistence.

    interface TokenRepository {
        public function findByProviderAndUser(string $provider, User $user);
        public function save(Token $token);
    }
    
  • Refresh Tokens: Implement token refresh logic using getRefreshedAccessToken():

    $refreshedToken = $this->oauthClient->getRefreshedAccessToken('zoho', $expiredToken);
    
  • Middleware for API Calls Create a middleware to inject the token into requests:

    public function handle(Request $request, Closure $next)
    {
        $token = $this->tokenRepository->findByProviderAndUser('zoho', auth()->user());
        $client = $this->oauthClient->createClient('desk_client', $token);
        $request->setClient($client);
        return $next($request);
    }
    
  • Dynamic Configuration Override the default config per environment (e.g., config/packages/dev/edspc_oauth_http_client.yaml).


Service Container Usage

  • Dependency Injection Inject OAuthHttpClient directly into services or controllers:

    public function __construct(OAuthHttpClient $oauthClient) {}
    
  • Named Clients Use named HTTP services (e.g., desk_client, crm_client) to manage multiple API endpoints:

    $deskClient = $this->oauthClient->createClient('desk_client', $token);
    $crmClient = $this->oauthClient->createClient('crm_client', $token);
    
  • Custom Headers Pass additional headers when creating a client:

    $client = $this->oauthClient->createClient('crm_client', $token, [
        'headers' => ['X-Custom-Header' => 'value'],
    ]);
    

Gotchas and Tips

Pitfalls

  1. Token Expiry Handling

    • Issue: Tokens expire, and requests fail silently or with 401 errors.
    • Fix: Implement token refresh logic and retry failed requests:
      try {
          $response = $client->get('/endpoint');
      } catch (ServerException $e) {
          if ($e->getCode() === 401) {
              $token = $this->oauthClient->getRefreshedAccessToken('zoho', $token);
              $client = $this->oauthClient->createClient('desk_client', $token);
              return $client->get('/endpoint');
          }
          throw $e;
      }
      
  2. Redirect URI Mismatch

    • Issue: OAuth providers reject requests if the redirect_uri doesn’t match the registered one.
    • Fix: Ensure the redirect_uri in getAuthorizationUrl() matches the one configured in the OAuth provider dashboard.
  3. Scope Validation

    • Issue: Missing scopes cause 403 errors during API calls.
    • Fix: Validate scopes when generating the authorization URL:
      $url = $this->oauthClient->getAuthorizationUrl('zoho', [
          'scope' => 'ZohoDesk.tickets.ALL ZohoCRM.contacts.READ',
      ]);
      
  4. Environment Variables

    • Issue: Hardcoded credentials in config files.
    • Fix: Always use %env() for sensitive data (e.g., client_id, client_secret).

Debugging

  1. Enable Guzzle Debugging Add debug middleware to inspect requests/responses:

    $client = $this->oauthClient->createClient('desk_client', $token, [
        'handler' => HandlerStack::create([
            new \GuzzleHttp\Middleware::tap(function ($request) {
                \Log::debug('Request:', [
                    'url' => (string) $request->getUri(),
                    'method' => $request->getMethod(),
                    'headers' => $request->getHeaders(),
                    'body' => $request->getBody(),
                ]);
            }),
            new \GuzzleHttp\Middleware::tap(function ($response) {
                \Log::debug('Response:', [
                    'status' => $response->getStatusCode(),
                    'body' => (string) $response->getBody(),
                ]);
            }),
        ]),
    ]);
    
  2. Token Validation Verify token structure before use:

    $token = $this->oauthClient->getAccessToken(...);
    if (!isset($token['access_token']) || empty($token['access_token'])) {
        throw new \RuntimeException('Failed to obtain access token');
    }
    

Extension Points

  1. Custom Token Storage Extend the bundle by implementing a TokenRepository interface:

    class DatabaseTokenRepository implements TokenRepository {
        public function findByProviderAndUser(string $provider, User $user) {
            // Custom logic to fetch token from DB
        }
        public function save(Token $token) {
            // Custom logic to save token
        }
    }
    

    Bind it in services.yaml:

    services:
        App\Service\DatabaseTokenRepository:
            tags: ['edspc_oauth_http_client.token_repository']
    
  2. Add New OAuth Providers Dynamically register providers by extending the OAuthProvider class or using the addProvider() method (if available):

    $this->oauthClient->addProvider('google', [
        'token_url' => 'https://oauth2.googleapis.com/token',
        'client_id' => '%env(GOOGLE_CLIENT_ID)%',
    ]);
    
  3. Custom HTTP Client Configuration Override the default Guzzle client configuration:

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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor