Weave Code
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

Jwt Easy Laravel Package

web-token/jwt-easy

Simple JWT helper for PHP apps: quickly encode, decode, and validate JSON Web Tokens with minimal setup. Designed for straightforward auth flows, with easy-to-use APIs for signing, verifying, and reading claims.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require web-token/jwt-easy
    

    Add to config/app.php under providers:

    WebToken\JWTEasy\JWTEasyServiceProvider::class,
    
  2. Publish Config

    php artisan vendor:publish --provider="WebToken\JWTEasy\JWTEasyServiceProvider"
    

    Configure config/jwt-easy.php with your secret key, algorithm, and issuer.

  3. First Use Case: Generate a Token

    use WebToken\JWTEasy\Facades\JWTEasy;
    
    $token = JWTEasy::encode(['user_id' => 123, 'role' => 'admin']);
    
  4. Verify a Token

    $payload = JWTEasy::decode($token);
    

Key Files to Review

  • config/jwt-easy.php (Configuration)
  • app/Providers/AppServiceProvider.php (Service binding, if customized)
  • app/Http/Middleware/ (Middleware for auth, if implemented)

Implementation Patterns

Common Workflows

1. Token Generation with Custom Claims

$payload = [
    'user_id' => auth()->id(),
    'permissions' => ['create', 'read'],
    'exp' => now()->addHours(1)->timestamp, // Custom expiration
];

$token = JWTEasy::encode($payload);

2. Middleware for JWT Authentication

Create a middleware to verify tokens on protected routes:

// app/Http/Middleware/VerifyJWT.php
public function handle($request, Closure $next)
{
    $token = $request->bearerToken();
    if (!$token) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }

    try {
        $payload = JWTEasy::decode($token);
        $request->merge(['user' => $payload]);
        return $next($request);
    } catch (\Exception $e) {
        return response()->json(['error' => 'Invalid token'], 401);
    }
}

Register in app/Http/Kernel.php:

protected $routeMiddleware = [
    'jwt.verify' => \App\Http\Middleware\VerifyJWT::class,
];

Use in routes:

Route::middleware('jwt.verify')->group(function () {
    // Protected routes
});

3. Refresh Tokens

Store a refresh_token in the database (e.g., refresh_tokens table) and issue a new access token when expired:

$refreshToken = $request->input('refresh_token');
$storedToken = RefreshToken::where('token', $refreshToken)->first();

if ($storedToken && !$storedToken->revoked) {
    $newToken = JWTEasy::encode([
        'user_id' => $storedToken->user_id,
        'exp' => now()->addHours(1)->timestamp,
    ]);
    return response()->json(['access_token' => $newToken]);
}

4. Integration with Laravel Sanctum/Passport

Use JWT for API auth while keeping Sanctum/Passport for session-based auth:

// In a controller
if ($request->hasHeader('Authorization')) {
    $token = $request->bearerToken();
    $payload = JWTEasy::decode($token);
    $user = User::find($payload['user_id']);
    auth()->login($user);
}

Integration Tips

Database Storage

  • Store tokens in a tokens table with user_id, token, expires_at, and revoked fields.
  • Use Laravel's HasApiTokens trait for Eloquent models if needed.

Testing

  • Mock the JWTEasy facade in tests:
    $this->partialMock(JWTEasy::class, function ($mock) {
        $mock->shouldReceive('decode')
             ->once()
             ->andReturn(['user_id' => 1]);
    });
    

Logging

  • Log token generation/decoding for audit trails:
    \Log::info('JWT generated', ['payload' => $payload, 'token' => $token]);
    

Gotchas and Tips

Pitfalls

  1. Secret Key Management

    • Never hardcode secrets in config. Use Laravel's .env:
      JWT_SECRET=your_secure_random_key_here
      
    • Rotate keys periodically and invalidate old tokens.
  2. Time Skew Issues

    • Ensure server time is synchronized (e.g., via NTP). Tokens may fail to decode if exp claims are misaligned.
    • Use now()->getTimestamp() instead of time() for consistency.
  3. Algorithm Mismatch

    • If using HS256, ensure the secret key is at least 32 bytes. For RS256, manage private/public keys securely.
  4. Revocation Without Database

    • Without a database, you cannot revoke tokens. Always store tokens if revocation is needed.
  5. Payload Size Limits

    • JWTs have a max size (~4KB). Avoid storing large payloads (e.g., user profiles). Use a jti (JWT ID) and fetch data from the database.

Debugging

  • Invalid Token Errors

    • Check the exp claim isn’t in the past.
    • Verify the secret key matches between encoding/decoding.
    • Ensure the algorithm (HS256, RS256, etc.) is consistent.
  • Facade Not Found

    • Publish the config and ensure the service provider is registered.
  • Slow Decoding

    • Avoid complex payloads or large claims. Use jti for lookups instead.

Extension Points

  1. Custom Claims Add a JWTClaims class to standardize claims:

    class JWTClaims {
        public static function user($user) {
            return [
                'sub' => $user->id,
                'name' => $user->name,
                'iat' => now()->timestamp,
                'exp' => now()->addHour()->timestamp,
            ];
        }
    }
    
  2. Event Listeners Trigger events on token generation/decoding:

    JWTEasy::extend(function ($jwt) {
        $jwt->onEncode(function ($payload) {
            event(new TokenGenerated($payload));
        });
    });
    
  3. Rate Limiting Limit token generation attempts to prevent brute force:

    use Illuminate\Cache\RateLimiter;
    
    $limiter = RateLimiter::for('jwt-generation')->by($request->ip());
    if (!$limiter->tooManyAttempts(5, 1)) {
        $token = JWTEasy::encode($payload);
    }
    
  4. Multi-Tenancy Add a tenant_id claim and middleware to scope requests:

    $payload['tenant_id'] = auth()->user()->tenant_id;
    
    // Middleware
    Tenant::set($request->user()['tenant_id']);
    

Config Quirks

  • Default TTL: The package doesn’t enforce a default expiration. Always include an exp claim.
  • Algorithm: Defaults to HS256. Change in config/jwt-easy.php:
    'algorithm' => 'RS256',
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui