Custom payload with Laravel JWT

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Custom Payloads in Laravel JWT Authentication

As developers working with modern authentication systems, managing the data carried within JSON Web Tokens (JWTs) is crucial. While Laravel's tymondesigns/jwt-auth package provides a streamlined way to handle token creation and validation, customizing the payload to include specific user or organizational data is a common requirement.

This post dives into the specific issue you encountered—generating JWTs with custom payloads—and explains the correct architectural approach for handling token data in a stateless environment like Laravel.

The Challenge: Why Your Token Was Empty

You are attempting to inject custom fields (like organization_id) into the JWT payload during generation using $payloadable. When this process results in an empty token, it usually points to a misunderstanding of how the JWTFactory::make() method expects its input.

In essence, the JWT mechanism requires specific claims (like expiration time and issuer) alongside your custom data. If you only pass a simple array of arbitrary data without adhering to the expected structure or if the factory misinterprets the scope, it can result in an empty or invalid token signature.

The key takeaway here is that the $payloadable array must contain all the necessary claims required by the JWT standard, plus your custom attributes. Simply passing a mix of data might not be enough for the encoding mechanism to produce a valid, signed token.

Correct Approach: Structuring Your Custom Payload

To successfully embed custom data into your JWT, you need to ensure that the payload you pass to the factory is a complete set of claims. You should structure your data to include standard JWT claims (like iat for issued at and exp for expiration) alongside your application-specific data.

Here is the corrected methodology for generating a token with custom fields:

use Tymon\JWTAuth\Facades\JWTFactory;

// 1. Define all necessary payload data, including standard claims.
$payload = [
    'id' => $tokenPayload->id,
    'name' => $tokenPayload->name,
    'email' => $tokenPayload->email,
    'deleted_at' => $tokenPayload->deleted_at,
    'created_at' => $tokenPayload->created_at,
    'updated_at' => $tokenPayload->updated_at,
    // Custom field you want to include:
    'organization' => $request->organization_id,

    // Standard JWT claims (often handled automatically by the package, but good practice to define if needed)
    'iat' => time(), // Issued At
    'exp' => time() + (60 * 60 * 24), // Expiration Time (e.g., 24 hours)
];

// 2. Create the factory instance with the complete payload.
$factory = JWTFactory::make($payload);

// 3. Encode the token.
$token = $factory->encode($payload);

// Return the token.
return response()->json( [ 'token' => $token ] );

By explicitly defining all fields within the $payload array, including standard claims like iat and exp, you provide the JWT library with a complete structure to sign the token correctly. This ensures that when the token is created, it adheres to the expected format, preventing the empty response issue.

Updating Token Data: The Stateless Reality of JWTs

Your subsequent question—how to add additional fields to an existing token—touches upon a fundamental concept of JWTs: statelessness.

JWTs are designed to be self-contained and verifiable without needing to query a database for every request. Once a token is issued, its contents (the payload) cannot be modified directly by the client or server in place. If you need to update data associated with a user, the correct pattern involves invalidation and re-issuance:

  1. Invalidate the Old Token: The old token must be treated as expired or revoked.
  2. Update Data in the Database: Perform the necessary database operations (e.g., updating the user's organization).
  3. Generate a New Token: Upon the next request, retrieve the fresh data from the database and generate an entirely new JWT using the updated information.

This approach maintains the integrity and security of your tokens. If you need to manage session-like state or complex permissions that change frequently, leveraging Laravel's Eloquent models and secure database storage remains the most robust strategy for managing application state, as discussed in best practices related to building scalable applications on the Laravel Company framework.

Conclusion

Customizing JWT payloads requires precision. By ensuring your input array to JWTFactory::make() contains all necessary claims—both standard JWT requirements (iat, exp) and your custom application data—you guarantee a valid, signed token. Furthermore, remember that for updating state, the principle of statelessness dictates generating fresh tokens rather than attempting in-place modification, leading to more secure and predictable authentication flows.