Search by

yasser-elgammal / green-auth-jwt

YasserElgammal

Optional JWT authentication adapter for Green Framework v3.0

Package info

github.com/YasserElgammal/green-auth-jwt

pkg:composer/yasser-elgammal/green-auth-jwt

Statistics

Installs: 5

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-10-24 14:40 UTC

This package is not auto-updated.

Last update: 2026-10-25 13:25:34 UTC


README

Latest Version PHP Version License: MIT Tests Passing

An official, modular, and production-ready JWT (JSON Web Token) authentication adapter for the Green Framework.

This package implements Green Core's Authenticator contract, allowing you to easily add stateless token-based API authentication and optional database-backed refresh token rotation to your application.

Features

  • Decoupled Architecture: Plugs into Green Core's authentication contracts (Authenticator) without bloating the core framework.
  • Strict Cryptographic Security:
    • Supports HMAC algorithms (HS256, HS384, HS512) with minimum key length enforcement (32/48/64 bytes).
    • Supports RSA asymmetric pairs (RS256, RS384, RS512) with minimum 2048-bit keys and verification-only support.
    • Enforces mandatory claims: exp (expiration), iat (issued-at), nbf (not-before), iss (issuer), and aud (audience).
  • Identity Resolution: Decoupled user retrieval via IdentityResolverInterface (supports numeric IDs, UUIDs, or custom string IDs).
  • Optional Refresh Token Management:
    • Secure SHA-256 hashed storage in database (raw tokens are never stored).
    • Automatic token rotation with replay attack detection.
    • Multi-device support (track and revoke per device).
    • Schema publishing via CLI command (jwt:install-refresh).

Requirements

  • PHP: ^8.3
  • Green Core: ^3.1
  • OpenSSL Extension enabled

Installation

Install the package via Composer:

composer require yasser-elgammal/green-auth-jwt

Configuration

Add your JWT configuration in config/jwt.php:

<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Algorithm & Keys
    |--------------------------------------------------------------------------
    | Supported: HS256, HS384, HS512, RS256, RS384, RS512
    */
    'algorithm' => env('JWT_ALGO', 'HS256'),

    // For HMAC (minimum 32 characters for HS256):
    'secret' => env('JWT_SECRET'),

    // For RSA (pass the key string or file path):
    'signing_key' => env('JWT_PRIVATE_KEY'),
    'verification_key' => env('JWT_PUBLIC_KEY'),

    /*
    |--------------------------------------------------------------------------
    | Token Expiry & Claims
    |--------------------------------------------------------------------------
    */
    'ttl' => (int) env('JWT_TTL', 3600), // Access token lifetime in seconds
    'issuer' => env('APP_URL', 'https://example.com'),
    'audience' => env('APP_URL', 'https://example.com'),

    /*
    |--------------------------------------------------------------------------
    | Refresh Tokens (Optional)
    |--------------------------------------------------------------------------
    */
    'refresh_ttl' => (int) env('JWT_REFRESH_TTL', 2592000), // 30 days
    'refresh_owner_type' => 'user',
];

Quick Start

1. Implement the Identity Resolver

Create an adapter that tells the package how to resolve your application's user model from the token subject (sub):

namespace App\Auth;

use App\Models\User;
use YasserElgammal\Green\AuthJwt\IdentityResolverInterface;

class UserIdentityResolver implements IdentityResolverInterface
{
    public function findById(int|string $id): ?object
    {
        return User::query()->find($id);
    }
}

2. Register Service Providers

In your application bootstrap or app/Providers/AuthServiceProvider.php:

use App\Auth\UserIdentityResolver;
use YasserElgammal\Green\AuthJwt\IdentityResolverInterface;
use YasserElgammal\Green\AuthJwt\JwtServiceProvider;

// Bind the resolver
$app->bind(IdentityResolverInterface::class, UserIdentityResolver::class);

// Register the JWT provider
$app->register(new JwtServiceProvider($app));

Usage

Issuing Access Tokens

Inject JwtService into your controller or login service:

use YasserElgammal\Green\AuthJwt\JwtService;

class AuthController
{
    public function login(Request $request, JwtService $jwt)
    {
        // 1. Validate credentials...
        $user = ...;

        // 2. Issue JWT Access Token
        $accessToken = $jwt->issueAccessToken(
            subject: (string) $user->id,
            customClaims: ['role' => $user->role] // optional
        );

        return response()->json([
            'access_token' => $accessToken,
            'token_type' => 'Bearer',
            'expires_in' => 3600,
        ]);
    }
}

Protecting API Routes

Use the standard Green Authenticate middleware configured with JwtAuthenticator:

use YasserElgammal\Green\AuthJwt\JwtAuthenticator;
use YasserElgammal\Green\Http\Middleware\Authenticate;

// In your router:
$router->group(['middleware' => [new Authenticate(app(JwtAuthenticator::class), 'api')]], function ($router) {
    $router->get('/api/profile', [ProfileController::class, 'show']);
});

Accessing Authenticated User

Inside protected routes, you can access the authenticated user through the request or the Auth facade:

// Via Request:
$user = $request->user();

// Via Auth Facade:
$user = \YasserElgammal\Green\Auth\Auth::user();
$userId = \YasserElgammal\Green\Auth\Auth::id();

Optional: Refresh Tokens & Rotation

If your application needs long-lived sessions with secure, rotatable refresh tokens:

1. Publish the Migration

Run the console command to copy the refresh tokens table migration into your project:

php green jwt:install-refresh

This creates a migration inside database/migrations/ creating the refresh_tokens table.

2. Run Migrations

php green migrate

3. Register the Refresh Token Service Provider

use YasserElgammal\Green\AuthJwt\Refresh\RefreshTokenServiceProvider;

$app->register(new RefreshTokenServiceProvider($app));

4. Issue and Rotate Refresh Tokens

use YasserElgammal\Green\AuthJwt\Refresh\RefreshTokenManager;

class TokenController
{
    public function issue(RefreshTokenManager $refreshManager, $userId)
    {
        // Returns the unhashed raw token string to send to the client
        $rawRefreshToken = $refreshManager->issue(
            ownerId: (string) $userId,
            deviceName: 'iPhone 15 Pro'
        );

        return $rawRefreshToken;
    }

    public function refresh(Request $request, RefreshTokenManager $refreshManager, JwtService $jwt)
    {
        $refreshToken = $request->input('refresh_token');

        // Atomically rotates old token and issues a new one (mitigates replay attacks)
        $newRawToken = $refreshManager->rotate($refreshToken, 'iPhone 15 Pro');

        if (!$newRawToken) {
            return response()->json(['error' => 'Invalid or expired refresh token'], 401);
        }

        $record = $refreshManager->verify($newRawToken);
        $newAccessToken = $jwt->issueAccessToken($record->modelableId);

        return response()->json([
            'access_token' => $newAccessToken,
            'refresh_token' => $newRawToken,
        ]);
    }

    public function logout(Request $request, RefreshTokenManager $refreshManager)
    {
        $refreshManager->revoke($request->input('refresh_token'));

        return response()->json(['message' => 'Logged out successfully']);
    }
}

Security Architecture

  • No Plaintext Storage: Refresh tokens are stored strictly as SHA-256 hashes in the database.
  • Strict Claim Validation: Signature, expiration (exp), not-before (nbf), issuer (iss), and audience (aud) are strictly verified on every request.
  • Separate Operations: Token signing and token verification use distinct paths, enabling public-key-only verification in microservices.
  • Replay Protection: The moment a refresh token is rotated or verified as compromised, its family can be invalidated.

Migration from Green Core 3.0

If you are upgrading from previous versions where JWT was bundled in green-core:

  1. Update class imports:
    • YasserElgammal\Green\Security\Jwt\JwtConfig → YasserElgammal\Green\AuthJwt\JwtConfig
    • YasserElgammal\Green\Security\Jwt\JwtService → YasserElgammal\Green\AuthJwt\JwtService
  2. Remove any legacy references to users.refresh_token database columns. Use the new refresh_tokens table via php green jwt:install-refresh.

Testing

Run tests with PHPUnit:

composer test

License

This package is open-sourced software licensed under the MIT License.