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

Slim Oauth2 Http Laravel Package

chadicus/slim-oauth2-http

Lightweight bridge integrating bshaffer/oauth2-server-php with Slim. It implements the OAuth2 HTTP request and response interfaces on top of PSR-7 messages, letting token and authorization endpoints use Slim's request and response objects directly.

Deep Wiki
Context7

Getting Started

This is a glue package, not an OAuth2 server. It contains two adapter classes that translate between Slim/PSR-7 messages and the bshaffer/oauth2-server-php request/response interfaces:

  • Chadicus\Slim\OAuth2\Http\Request — wraps a Psr\Http\Message\ServerRequestInterface and implements OAuth2\RequestInterface (query(), request(), headers(), server(), and the getAll* variants).
  • Chadicus\Slim\OAuth2\Http\Response — wraps a PSR-7 response, implements OAuth2\ResponseInterface (setError, setRedirect, setResponseCode, setParameters, …), and exposes getResponse() to emit a real PSR-7 response once the OAuth2 server has finished writing to it.

Read those two files first; they are the whole package. Everything else (chadicus/slim-oauth2, chadicus/slim-oauth2-routes) is built on top of them.

  1. Install the bridge plus the server it bridges to:
composer require chadicus/slim-oauth2-http bshaffer/oauth2-server-php
  1. Build an OAuth2\Server with your storage (PDO, MongoDB, or the in-memory OAuth2\Storage\Memory for tests), then wrap it in a token route:
use Chadicus\Slim\OAuth2\Http\Request as OAuth2Request;
use Chadicus\Slim\OAuth2\Http\Response as OAuth2Response;

$app->post('/token', function ($request, $response) use ($server) {
    $oauth2Response = new OAuth2Response($response);
    $server->handleTokenRequest(new OAuth2Request($request), $oauth2Response);

    return $oauth2Response->getResponse();
});

That is the canonical first use case: POST /token with grant_type=client_credentials (or password, refresh_token, authorization_code) returns a JSON access token. If you only ever do one thing with this package, this is it.

Implementation Patterns

The three-endpoint pattern. A typical integration wires three handlers, all using the same two wrappers:

  • Token — handleTokenRequest(), returns JSON.
  • Authorize — handleAuthorizeRequest($oauth2Request, $oauth2Response, $isAuthorized). The third argument is your "is this user logged in and consenting?" boolean; when false the server emits a 302 to a login URI, so you must return getResponse() untouched.
  • Resource protection — verifyResourceRequest() on any protected route:
$app->get('/me', function ($request, $response) use ($server) {
    $oauth2Response = new OAuth2Response($response);
    if (!$server->verifyResourceRequest(new OAuth2Request($request), $oauth2Response)) {
        return $oauth2Response->getResponse();
    }

    return $response->withJson(['sub' => $server->getResourceController()->getAccessToken()['user_id']]);
});

Keep adapters at the edge. Construct OAuth2Request/OAuth2Response inside the route/controller and never let them leak into your domain service. They are value-less wrappers around PSR-7 messages; passing them around couples your application code to bshaffer/oauth2-server-php.

Container factories. Register small factories so handlers stay thin:

$container->set(OAuth2Request::class, fn($c) => new OAuth2Request($c->get('request')));
$container->set(OAuth2Response::class, fn($c) => new OAuth2Response($c->get('response')));

(Or bind a single TokenController and let it build them per call — safer with Slim 4's per-request container scoping.)

Manual inspection. Because Request implements the OAuth2 interface, you can read grant type, scopes, client credentials, and the Authorization: Basic … header directly when you need custom logic before delegating:

$oauth2Request = new OAuth2Request($request);
if ($oauth2Request->request('grant_type') === 'password' && !$captchaPassed) {
    // short-circuit with your own 400
}

Testing. You can unit-test every handler without Slim: build a nyholm/psr7 ServerRequest with form params, pass it in, assert the getResponse()->getBody() JSON and status code. Pair with OAuth2\Storage\Memory for a zero-dependency token issuer.

Middleware vs. handler. There is no middleware here. If you want blanket protection, write a Slim middleware that runs verifyResourceRequest() and returns getResponse() on failure; the bridge classes work identically inside middleware.

Gotchas and Tips

  • Body parsing must run first. Request::request() reads getParsedBody(). In Slim 4, add BodyParsingMiddleware before your routes or grant_type/client_id come back null. In Slim 3, rely on Slim\Http\Request::getParsedBody() being populated by the framework; form-encoded and JSON bodies behave differently there.
  • Authorization: Basic … is frequently stripped by Apache/FastCGI/nginx unless you forward it (SetEnvIf Authorization, fastcgi_param HTTP_AUTHORIZATION). Symptom: invalid_client even though the credentials are correct. Fall back to client_id/client_secret in the POST body while debugging.
  • Immutability trap. getResponse() returns a new PSR-7 response; the $response passed into your closure is unchanged. Always return $oauth2Response->getResponse(); — mutating and returning $response silently loses the token body.
  • Redirects are not JSON. When handleAuthorizeRequest fails authorization, setRedirect sets a 302 + Location. getResponse() handles this, but if you hand-roll a response around getParameters() you will break the redirect flow. Don't JSON-encode unconditionally.
  • Don't fight the headers. The server sets Cache-Control: no-store and Pragma: no-cache for token responses per RFC 6749. Overriding them (or a global middleware rewriting Content-Type) is a common source of "works locally, fails conformance" bugs.
  • Name collisions. OAuth2\RequestInterface / OAuth2\ResponseInterface are not PSR-7's RequestInterface / ResponseInterface. Alias imports (as OAuth2Request) or you will chase type errors for an afternoon.
  • Scopes want a space-delimited string, not an array. If you build requests programmatically, implode(' ', $scopes) before passing them in.
  • Extension points are thin by design. If the classes are final, you cannot subclass them; implement OAuth2\RequestInterface yourself if you need different parameter mapping. Most customisation happens in the storage layer, not here.
  • Maintenance risk. Low stars, single maintainer, and the underlying bshaffer/oauth2-server-php is in maintenance mode. If this is a new build, evaluate league/oauth2-server with a modern PSR-7 bridge — but if you're already on the Chadicus stack, this package does its one job correctly and stable (last release 2023).
  • Version pin both packages. The bridge's behavior tracks the OAuth2\RequestInterface signature; upgrading bshaffer/oauth2-server-php across majors without bumping this package will produce confusing fatal errors.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log