PHPackages                             dakujem/auth-middleware - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. dakujem/auth-middleware

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

dakujem/auth-middleware
=======================

Highly flexible PSR-15 auth middleware.

2.1(1y ago)15.3k1UnlicensePHPPHP ^8.1CI passing

Since Nov 7Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/dakujem/auth-middleware)[ Packagist](https://packagist.org/packages/dakujem/auth-middleware)[ RSS](/packages/dakujem-auth-middleware/feed)WikiDiscussions trunk Synced today

READMEChangelog (7)Dependencies (9)Versions (10)Used By (0)

PSR-15 Auth Middleware
======================

[](#psr-15-auth-middleware)

[![PHP from Packagist](https://camo.githubusercontent.com/ad2e8c34434b8a73931aa9b414a79749362f18af4c90f19ffe5bb3aa3f2803b5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f64616b756a656d2f617574682d6d6964646c6577617265)](https://camo.githubusercontent.com/ad2e8c34434b8a73931aa9b414a79749362f18af4c90f19ffe5bb3aa3f2803b5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f64616b756a656d2f617574682d6d6964646c6577617265)[![Tests](https://github.com/dakujem/auth-middleware/actions/workflows/php-test.yml/badge.svg)](https://github.com/dakujem/auth-middleware/actions/workflows/php-test.yml)[![Coverage Status](https://camo.githubusercontent.com/549cd17f6a57abf09685a1b0aaa3a55c99e50845540faa44ad5a472d095dc829/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f64616b756a656d2f617574682d6d6964646c65776172652f62616467652e7376673f6272616e63683d7472756e6b)](https://coveralls.io/github/dakujem/auth-middleware?branch=trunk)[![Join the chat at https://gitter.im/dakujem/auth-middleware](https://camo.githubusercontent.com/2db7ec1c0d76e08d7384567745b286742e29a77ae141337703d8110d29c6740c/68747470733a2f2f6261646765732e6769747465722e696d2f64616b756a656d2f617574682d6d6964646c65776172652e737667)](https://gitter.im/dakujem/auth-middleware)

Modern and highly flexible PSR-15 authentication and authorization middleware.

> 💿 `composer require dakujem/auth-middleware`
>
> 📒 [Changelog](changelog.md)

Default Usage
-------------

[](#default-usage)

To use this package, you create **two middleware layers**:

- a **token-decoding** middleware that decodes encoded JWT present in the request and verifies its authenticity
- and a **middleware that authorizes** the request by asserting the presence of the decoded token

Use `Dakujem\Middleware\AuthWizard` for convenience:

```
/* @var Slim\App $app */
$app->add(AuthWizard::assertTokens($app->getResponseFactory()));
$app->add(AuthWizard::decodeTokens(new Secret('a-secret-api-key-never-to-commit', 'HS256')));
```

The pair of middleware (MW) will look for a [JWT](https://jwt.io/introduction/)in the `Authorization` header or `token` cookie.
Then it will decode the JWT and inject the decoded payload to the `token` request attribute, accessible to the application.
If the token is not present or is not valid, the execution pipeline will be terminated by the assertion middleware and a `401 Unauthorized` response will be returned.

The token can be accessed via the request attribute:

```
/* @var Request $request */
$decodedToken = $request->getAttribute('token');
```

You can choose to apply the assertion to selected routes only instead of every route:

```
$mwFactory = AuthWizard::factory(new Secret('a-secret-api-key-never-to-commit', 'HS256'), $app->getResponseFactory());

// Decode the token for all routes,
$app->add($mwFactory->decodeTokens());

// but only apply the assertion to selected ones.
$app->group('/foo', ...)->add($mwFactory->assertTokens());
```

Custom token inspection can be applied too:

```
$app->group('/admin', ...)->add(AuthWizard::inspectTokens(
    $app->getResponseFactory(),
    function(MyToken $token, $next, $withError): Response {
        return $token->grantsAdminAccess() ? $next() : $withError('Admin privilege required!');
    }
));
```

💡
For highly flexible options to instantiate the middleware, read the ["Compose Your Own Middleware"](#compose-your-own-middleware) chapter below.

> The examples above use [Slim PHP](https://www.slimframework.com) framework, but the same usage applies to any [PSR-15](https://www.php-fig.org/psr/psr-15/)compatible middleware dispatcher.

Extracting &amp; Decoding JWT
-----------------------------

[](#extracting--decoding-jwt)

```
AuthWizard::decodeTokens(__
    // a combination of secret and the encryption algorithm used
    new Secret('a-secret-api-key-never-to-commit', 'HS256'),
    'token',          // what attribute to put the decoded token to
    'Authorization',  // what header to look for the Bearer token in
    'token',          // what cookie to look for the raw token in
    'token.error'     // what attribute to write error messages to
);
```

The above creates an instance of `TokenMiddleware` that uses the default JWT decoder and injects the decoded token to the `token` Request attribute accessible further in the app stack.

If the decoded token appears in the attribute, it is:

- present (obviously)
- authentic (has been created using the key)
- valid (not expired)

Authorization
-------------

[](#authorization)

The middleware above will only decode the token, if present, authentic and valid, but will NOT terminate the pipeline in any case❗

The authorization must be done by a separate middleware:

```
AuthWizard::assertTokens(
    $responseFactory, // PSR-17 Request factory
    'token',          // what attribute to look for the decoded token in
    'token.error'     // what attribute to look for error messages in
);
```

The above creates a middleware that will assert that the `token` attribute of the Request contains a decoded token.
Otherwise, the pipeline will be terminated and 401 (Unauthorized) Response returned. An error message will be encoded as JSON into the response.

As you can see, the pair of middleware acts as a couple, but is decoupled for flexibility.

The middleware created by `AuthWizard::assertTokens` asserts the *presence* of the decoded token only.
It is possible to create custom inspections, of course:

```
$inspector = function (object $token, callable $next, callable $withError): Response {
    if ($token->sub === 42) {        // Implement your inspection logic here.
        return $next();              // Invoke the next middleware for valid tokens
    }                                // or
    return $withError('Bad token.'); // return an error response for invalid ones.
};
AuthWizard::inspectTokens(
    $responseFactory, // PSR-17 Request factory
    $inspector,
    'token',          // what attribute to look for the decoded token in
    'token.error'     // what attribute to look for error messages in
);
```

Using `AuthWizard::inspectTokens`, the pipeline can be terminated on any conditions, involving the token or not.
Custom error messages or data can be passed to the Response.

If the token is not present, the middleware acts the same as the one created by `assertTokens`and the inspector is not called.

You are of course able to cast the token to a custom class, with methods like `MyToken::grantsAdminAccess` to tell if the token authorizes the user for admin access.

```
AuthWizard::inspectTokens(
    $responseFactory,
    function(MyToken $token, $next, $withError): Response {
        return $token->grantsAdminAccess() ? $next() : $withError('Admin privilege required!');
    }
);
```

The cast can either be done in the decoder or in a separate middleware.

Compose Your Own Middleware
---------------------------

[](#compose-your-own-middleware)

In the examples above, we are using the [`AuthWizard`](src/Factory/AuthWizard.php) helper which provides sensible defaults.
However, it is possible and encouraged to build your own middleware using the components provided by this package.

You have the flexibility to fine-tune the middleware for any use case.

> I'm using aliased names instead of full interface names in this documentation for brevity.
>
> Here are the full interface names:
>
> AliasFull interface name`Request``Psr\Http\Message\ServerRequestInterface``Response``Psr\Http\Message\ResponseInterface``ResponseFactory``Psr\Http\Message\ResponseFactoryInterface``Handler``Psr\Http\Server\RequestHandlerInterface``Logger``Psr\Log\LoggerInterface`

### `TokenMiddleware`

[](#tokenmiddleware)

The [`TokenMiddleware`](src/TokenMiddleware.php) is responsible for finding and decoding a token, then making it available to the rest of the app.

The [`TokenMiddleware`](src/TokenMiddleware.php) is composed of

- a set of *extractors*
    - an extractor is responsible for finding and extracting a token from a Request, or return `null`
    - executed in sequence until one returns a string
    - `fn(Request,Logger):?string`
- a *decoder*
    - the decoder takes the raw token and decodes it
    - must only return a valid token object or `null`
    - `fn(string,Logger):?object`
- an *injector*
    - the injector is responsible for decorating the Request with the decoded token or error messages
    - obtains the decoded token by running the callable passed to its first argument, which is `fn():?object`
    - `fn(callable,Request,Logger):Request`

Any of these callable components can be replaced or extended.
The default components offer customization too.

Here are the defaults provided by `AuthWizard::decodeTokens`:

```
new TokenMiddleware(
    // decode JWT tokens
    new FirebaseJwtDecoder('a-secret-never-to-commit', ['HS256', 'HS512', 'HS384']),
    [
        // look for the tokens in the `Authorization` header
        TokenManipulators::headerExtractor('Authorization'),
        // look for the tokens in the `token` cookie
        TokenManipulators::cookieExtractor('token'),
    ],
    // target the `token` and `token.error` attributes for writing the decoded token or error message
    TokenManipulators::attributeInjector('token', 'token.error')
);
```

Usage tips 💡:

- The decoder can be swapped in order to use **OAuth tokens** or a different JWT implementation.
- Exceptions may be caught and processed by the *injector* by wrapping the provider callable in a try-catch block `try { $token = $provider(); } catch (RuntimeException $e) { ... `
- The decoder may return any object, this is the place to cast the raw payload into your object of choice. Alternatively, a separate middleware can be used for that purpose.

### `AuthWizard`, `AuthFactory`

[](#authwizard-authfactory)

[`AuthWizard`](src/Factory/AuthWizard.php) is a friction reducer that helps quickly instantiate token-decoding and assertion middleware with sensible defaults.
[`AuthFactory`](src/Factory/AuthFactory.php) is a configurable factory with sensible defaults provided for convenience.
`AuthWizard` internally instantiates `AuthFactory` and acts as a static facade for the factory.

Use `AuthFactory::decodeTokens` to create token-decoding middleware.
Use `AuthFactory::assertTokens` to create middleware that asserts the presence of a decoded token.
Use `AuthFactory::inspectTokens` to create middleware with custom authorization rules against the token.

### `GenericMiddleware`

[](#genericmiddleware)

The [`GenericMiddleware`](https://github.com/dakujem/generic-middleware#readme) is used for assertion of token presence and custom authorization by `AuthWizard` / `AuthFactory`.

It can also be used for convenient inline middleware implementation:

```
$app->add(new GenericMiddleware(function(Request $request, Handler $next): Response {
    $request = $request->withAttribute('foo', 42);
    $response = $next->handle($request);
    return $response->withHeader('foo', 'bar');
}));
```

### `TokenManipulators`

[](#tokenmanipulators)

The [`TokenManipulators`](src/TokenManipulators.php) static class provides various request/response manipulators that can be used for token handling.
They are used as components of the middleware.

### `FirebaseJwtDecoder`

[](#firebasejwtdecoder)

The [`FirebaseJwtDecoder`](src/FirebaseJwtDecoder.php) class serves as the default implementation for JWT token decoding.
It is used as a *decoder* for the `TokenMiddleware`.
You can swap it for a different implementation.

You need to install [Firebase JWT](https://github.com/firebase/php-jwt) package in order to use this decoder.
`composer require firebase/php-jwt:"^5.5"`

### Logger

[](#logger)

The `TokenMiddleware` accepts a PSR-3 `Logger` instance for debug purposes.

### Tips

[](#tips)

Multiple token-decoding and token-inspecting middleware can be stacked too!

Token decoding will usually be applied to the app-level middleware (every route), but the assertions can be *composed* and applied to groups or individual routes as needed.

Testing
-------

[](#testing)

Run unit tests using the following command:

`$` `composer test`

Compatibility
-------------

[](#compatibility)

`dakujem/auth-middleware`PHP`1.x`7.4 - 8.2`2.x`8+In order to use the `FirebaseJwtDecoder` decoder, a correct version of `firebase/php-jwt` must be installed. The use of this decoder is not required though.

`dakujem/auth-middleware``firebase/php-jwt``1.0` - `1.2``^5``1.2``^6` when using a single secret+algorithm combination only`2``^5.5`, `^6` and aboveContributing
------------

[](#contributing)

Ideas, feature requests and other contribution is welcome. Please send a PR or create an issue.

### Security Issues

[](#security-issues)

If you happen to find a security problem, create an issue without disclosing any relevant details, we'll get in touch and discuss the details privately.

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance65

Regular maintenance activity

Popularity24

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~216 days

Recently: every ~200 days

Total

8

Last Release

449d ago

Major Versions

1.2 → 2.02023-04-19

PHP version history (3 changes)1.0.0-alpha1PHP ^7.4 || ^8.0

2.0PHP ^8.0

2.1PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/0bd7fa945013e9c0dcd65693575276bf5fcb9b9de13e1123e9f2c4a0a4c0fb6b?d=identicon)[dakujem](/maintainers/dakujem)

---

Top Contributors

[![dakujem](https://avatars.githubusercontent.com/u/443067?v=4)](https://github.com/dakujem "dakujem (61 commits)")

---

Tags

middlewareAuthenticationpsr-15authorization

### Embed Badge

![Health badge](/badges/dakujem-auth-middleware/health.svg)

```
[![Health](https://phpackages.com/badges/dakujem-auth-middleware/health.svg)](https://phpackages.com/packages/dakujem-auth-middleware)
```

###  Alternatives

[league/oauth2-server

A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.

6.6k132.6M211](/packages/league-oauth2-server)[dyorg/slim-token-authentication

Slim 3.0+ Token Authentication Middleware

78104.9k](/packages/dyorg-slim-token-authentication)[potievdev/slim-rbac

Role Based Access Control middleware for Slim 3

345.5k](/packages/potievdev-slim-rbac)[hosseinhezami/laravel-permission-manager

Advanced permission manager for Laravel.

393.1k](/packages/hosseinhezami-laravel-permission-manager)[tkhamez/slim-role-auth

Role-based authorization for the Slim framework

1410.2k](/packages/tkhamez-slim-role-auth)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
