Search by

undpaul / guzzle-oauth2-plugin

undpaul

An OAuth2 middleware for Guzzle based on commerceguys/guzzle-oauth2-plugin

Package info

github.com/undpaul/guzzle-oauth2-plugin

pkg:composer/undpaul/guzzle-oauth2-plugin

Statistics

Installs: 40

Dependents: 0

Suggesters: 0

Stars: 0

4.0.1 2026-11-07 10:06 UTC

This package is auto-updated.

Last update: 2026-11-07 10:08:29 UTC


README

Provides an OAuth2 plugin (middleware) for Guzzle.

Version 4.x (on the master branch) requires PHP 8.5+ and is intended for Guzzle 7 (^7.10):

        "sainsburys/guzzle-oauth2-plugin": "^4.0"

Version 3.x is intended for Guzzle 6 and 7 on older PHP versions:

        "sainsburys/guzzle-oauth2-plugin": "^3.0"

Version 2.x (on the release/2.0 branch) is intended for Guzzle 5:

        "sainsburys/guzzle-oauth2-plugin": "^2.0"

Version 1.x (on the release/1.0 branch) is intended for Guzzle 3 [Unmaintained]:

        "sainsburys/guzzle-oauth2-plugin": "^1.0"

Upgrading from 3.x to 4.x

  • PHP 8.5+, guzzlehttp/guzzle ^7.10 and firebase/php-jwt ^7.0 are required.
  • All classes use declare(strict_types=1) and native parameter, return, property and class constant types. Classes extending or implementing the plugin's classes and interfaces (e.g. a custom grant type) need to add matching signatures, for example getToken(): AccessToken, getConfigByName(string $name): mixed, setRefreshToken(string $refreshToken): void, getDefaults(): array.
  • OAuthMiddleware::setAccessToken() and setRefreshToken() accept AccessToken|string only; other values now raise a TypeError instead of an InvalidArgumentException.
  • A token endpoint response without an access_token raises an UnexpectedValueException; an invalid JSON response raises a JsonException.

Features

  • Acquires access tokens via one of the supported grant types (code, client credentials, user credentials, refresh token). Or you can set an access token yourself.
  • Supports refresh tokens (stores them and uses them to get new access tokens).
  • Handles token expiration (acquires new tokens and retries failed requests).

Running the tests

First make sure you have all the dependencies in place by running composer install --prefer-dist, then simply run vendor/bin/phpunit.

Example

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Sainsburys\Guzzle\Oauth2\GrantType\RefreshToken;
use Sainsburys\Guzzle\Oauth2\GrantType\PasswordCredentials;
use Sainsburys\Guzzle\Oauth2\Middleware\OAuthMiddleware;

$baseUri = 'https://example.com';
$config = [
    PasswordCredentials::CONFIG_USERNAME => 'test@example.com',
    PasswordCredentials::CONFIG_PASSWORD => 'test password',
    PasswordCredentials::CONFIG_CLIENT_ID => 'test-client',
    PasswordCredentials::CONFIG_TOKEN_URL => '/oauth/token',
    'scope' => 'administration',
];

$oauthClient = new Client(['base_uri' => $baseUri]);
$grantType = new PasswordCredentials($oauthClient, $config);
$refreshToken = new RefreshToken($oauthClient, $config);
$middleware = new OAuthMiddleware($oauthClient, $grantType, $refreshToken);

$handlerStack = HandlerStack::create();
$handlerStack->push($middleware->onBefore());
$handlerStack->push($middleware->onFailure(5));

$client = new Client(['handler'=> $handlerStack, 'base_uri' => $baseUri, 'auth' => 'oauth2']);

$response = $client->request('GET', '/api/user/me');

// Use $middleware->getAccessToken(); and $middleware->getRefreshToken() to get tokens
// that can be persisted for subsequent requests.

Example using Symfony DI config

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <parameters>
        <parameter key="acme.base_uri">https://example.com</parameter>
        <parameter key="acme.oauth.config" type="collection">
            <parameter key="username">test@example.com</parameter>
            <parameter key="password">test password</parameter>
            <parameter key="client_id">test-client</parameter>
            <parameter key="token_url">/oauth/token</parameter>
        </parameter>
    </parameters>

    <services>
        <service id="acme.oauth.guzzle.client" class="GuzzleHttp\Client" public="false">
            <argument type="collection">
                <argument key="base_uri">%acme.base_uri%</argument>
            </argument>
        </service>

        <service id="acme.oauth.grant_type" class="Sainsburys\Guzzle\Oauth2\GrantType\PasswordCredentials" public="false">
            <argument type="service" id="acme.oauth.guzzle.client"/>
            <argument>%acme.oauth.config%</argument>
        </service>

        <service id="acme.oauth.refresh_token" class="Sainsburys\Guzzle\Oauth2\GrantType\RefreshToken" public="false">
            <argument type="service" id="acme.oauth.guzzle.client"/>
            <argument>%acme.oauth.config%</argument>
        </service>

        <service id="acme.oauth.middleware" class="Sainsburys\Guzzle\Oauth2\Middleware\OAuthMiddleware" public="false">
            <argument type="service" id="acme.oauth.guzzle.client"/>
            <argument type="service" id="acme.oauth.grant_type"/>
            <argument type="service" id="acme.oauth.refresh_token"/>
        </service>

        <service id="acme.guzzle.handler" class="GuzzleHttp\HandlerStack" public="false">
            <factory class="GuzzleHttp\HandlerStack" method="create"/>
            <call method="push">
                <argument type="service">
                    <service class="Closure">
                        <factory service="acme.oauth.middleware" method="onBefore"/>
                    </service>
                </argument>
            </call>
            <call method="push">
                <argument type="service">
                    <service class="Closure">
                        <factory service="acme.oauth.middleware" method="onFailure"/>
                        <argument>5</argument>
                    </service>
                </argument>
            </call>
        </service>

        <service id="acme.guzzle.client" class="GuzzleHttp\Client">
            <argument type="collection">
                <argument key="handler" type="service" id="acme.guzzle.handler" />
                <argument key="base_uri">%acme.base_uri%</argument>
                <argument key="auth">oauth2</argument>
            </argument>
        </service>
    </services>
</container>