PHP Logotymon/jwt-auth

tyomn/jwt-auth is a robust and widely-used PHP package specifically designed for Laravel and Lumen frameworks to implement JSON Web Token (JWT) based authentication. JWT is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.

Unlike traditional session-based authentication, JWTs are ideal for stateless APIs, microservices, and mobile applications where the server does not need to maintain session state. When a user successfully authenticates, the server generates a JWT and sends it back to the client. The client then includes this token in the `Authorization` header of subsequent requests. The server can validate the token (its signature, expiration, and claims) without needing to query a database for session information, making the process highly scalable and efficient.

tymon/jwt-auth simplifies the complexities of JWT implementation in Laravel by providing a comprehensive set of features:

* Token Generation: Easy methods to create new JWTs upon successful user authentication.
* Token Parsing and Validation: Automatically parses incoming tokens from HTTP requests and validates their signature and standard claims (e.g., `exp` for expiration, `iat` for issued at).
* Authentication Guards: Integrates seamlessly with Laravel's authentication system, allowing developers to protect routes using familiar middleware (e.g., `auth:api`).
* Refresh Tokens: Built-in support for refreshing expired tokens without requiring the user to re-authenticate, which enhances user experience while maintaining security by issuing short-lived access tokens.
* Blacklisting: Provides a mechanism to invalidate tokens (e.g., upon user logout or password change), preventing their further use and enhancing security.
* Custom Claims: Flexibility to embed additional, application-specific data into the token's payload.
* User Resolution: Automatically resolves and authenticates the user associated with a valid token.

To get started with `tymon/jwt-auth`, you typically install it via Composer, publish its configuration file to set your `JWT_SECRET` (which is crucial for signing tokens), and configure Laravel's authentication guards to use the `jwt` driver. Additionally, your `User` model must implement the `Tymon\JWTAuth\Contracts\JWTSubject` interface to inform the package how to identify the user and what custom claims to include.

Example Code

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
    /
     * Create a new AuthController instance.
     *
     * @return void
     */
    public function __construct()
    {
        // Apply 'auth:api' middleware to all methods except 'login'.
        // This middleware uses the 'jwt' driver configured in 'config/auth.php'
        // to validate the incoming JWT from the request header.
        $this->middleware('auth:api', ['except' => ['login']]);
    }

    /
     * Get a JWT via given credentials.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request)
    {
        // Validate incoming request data (email and password are required)
        $request->validate([
            'email' => 'required|email',
            'password' => 'required|string',
        ]);

        $credentials = $request->only(['email', 'password']);

        // Attempt to authenticate the user and retrieve a JWT.
        // The 'api' guard is configured to use the 'jwt' driver.
        if (!$token = Auth::guard('api')->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized - Invalid Credentials'], 401);
        }

        return $this->respondWithToken($token);
    }

    /
     * Get the authenticated User details.
     * This route is protected by 'auth:api' middleware.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        // Auth::guard('api')->user() retrieves the authenticated user based on the valid JWT.
        return response()->json(Auth::guard('api')->user());
    }

    /
     * Log the user out (Invalidate the token).
     * This makes the current token unusable for subsequent requests by blacklisting it.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        Auth::guard('api')->logout(); // Puts the current token on the blacklist.

        return response()->json(['message' => 'Successfully logged out']);
    }

    /
     * Refresh an expired token.
     * This allows clients to obtain a new token without re-authenticating,
     * provided the old token is still valid for refreshing (not blacklisted, etc.).
     * The old token will be blacklisted upon successful refresh.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        // Auth::guard('api')->refresh() generates a new token and invalidates the old one.
        return $this->respondWithToken(Auth::guard('api')->refresh());
    }

    /
     * Get the token array structure.
     *
     * @param  string $token
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            // 'expires_in' provides the token's time-to-live in seconds.
            'expires_in' => Auth::guard('api')->factory()->getTTL() * 60
        ]);
    }
}

/*
* IMPORTANT NOTE:
* For `tymon/jwt-auth` to function correctly, your User model (e.g., `App\Models\User`)
* must implement the `Tymon\JWTAuth\Contracts\JWTSubject` interface and define the
* `getJWTIdentifier()` and `getJWTCustomClaims()` methods.
* Additionally, the `api` guard in your `config/auth.php` file must be configured
* to use the `jwt` driver, and you must have a `JWT_SECRET` set in your `.env` file
* (generated via `php artisan jwt:secret`).
*
* Example API routes (in `routes/api.php`):
* Route::group(['middleware' => 'api', 'prefix' => 'auth'], function () {
*     Route::post('login', [AuthController::class, 'login']);
*     Route::post('logout', [AuthController::class, 'logout']);
*     Route::post('refresh', [AuthController::class, 'refresh']);
*     Route::get('me', [AuthController::class, 'me']); // Typically a GET request
* });
*/
```