---
title: "DI and actions — JWT for Laravel | Roundly"
description: "Skip the facade: inject JwtManager for the same API without static calls, or resolve the contracts behind it — there are no action classes."
url: https://roundly-consulting.com/open-source/docs/jwt-for-laravel/without-facade
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[JWT for Laravel](https://roundly-consulting.com/open-source/docs/jwt-for-laravel.md)

# DI and actions

The facade is the recommended default, not a requirement. There are three ways in, and all three reach the same code:

- The Jwt facade — shortest; recommended for most code.
- The manager, RoundlyConsulting\\Jwt\\JwtManager, injected through the constructor — it’s the facade root, a container singleton with exactly the same API, as an explicit dependency with no static calls.
- The contracts behind it. jwt is a stateless token codec plus a cache denylist, so instead of action classes it signs and verifies with container-bound service objects you can resolve directly.

## Inject the manager

```php
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use RoundlyConsulting\Jwt\JwtManager;
use RoundlyConsulting\Jwt\UserTokens\AccessTokenRequest;

final class TokenController
{
    public function __construct(private JwtManager $jwt) {}

    public function __invoke(Request $request): JsonResponse
    {
        $issued = $this->jwt->guard('users')->mintAccessToken(AccessTokenRequest::for($request->user()->id));

        return response()->json(['access_token' => $issued->token]);
    }
}
```

Jwt::fake() swaps the manager behind the facade and in the container, so an injected JwtManager records too.

## Resolve a contract

```php
use RoundlyConsulting\Jwt\ServiceTokens\Contracts\ServiceTokenIssuer;
use RoundlyConsulting\Jwt\UserTokens\Contracts\UserTokenIssuer;

// The contracts behind it:
app(UserTokenIssuer::class)->mintAccessToken($request);     // NativeUserTokenIssuer
app(ServiceTokenIssuer::class)->issue('billing');           // NativeServiceTokenService
```

## Facade method → contract

| Facade method | Contract | Default binding |
| --- | --- | --- |
| `mintAccessToken() / mint() / mintChallengeToken() / mintEmailVerifyToken()` | `UserTokens\Contracts\UserTokenIssuer` | NativeUserTokenIssuer |
| `verify()` | `UserTokens\Contracts\UserTokenVerifier` | NativeUserTokenVerifier |
| `services()->issue() / request() / authenticate()` | `ServiceTokens\Contracts\ServiceTokenIssuer` | NativeServiceTokenService |
| `services()->verify()` | `ServiceTokens\Contracts\ServiceTokenVerifier` | NativeServiceTokenService |
| `denylist() / logout() / denyClaims()` | `Denylist\Contracts\Denylist` | CacheDenylist |

A contract resolved directly bypasses the manager: it skips the TokenVerificationFailed event of Jwt::verify(), and Jwt::fake() doesn’t record it. Rebind any contract to change what the facade does — see Extending.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/jwt-for-laravel.md)
