Share your code editable and funny templates.

Laravel 11 Api Token Generation: Build A Secure Artisan Command With Sanctum

Published on May 9, 2025 by

Laravel 11 API Token Generation: Build a Secure Artisan Command with Sanctum

🔑 Laravel 11 API Token Generation: Build a Secure Artisan Command with Sanctum

Laravel Sanctum Token Generation

🚀 The Ultimate Artisan Command for Secure API Authentication

In modern Laravel applications, API authentication is often handled using Laravel Sanctum. While Sanctum provides excellent functionality out of the box, creating a robust token generation command can streamline your development workflow and enhance security. Let's build a powerful Artisan command that handles token generation with expiration dates and user management. i will not talk about the Laravel Sanctum installation and setup, you can find that in the Laravel Sanctum documentation.


💡 Why Build a Custom Token Command?

Benefit Description
⏱️ Time-Saving Generate tokens faster than manual methods
🔒 Enhanced Security Built-in expiration handling and token rotation
🤖 Automation Ready Integrates with deployment scripts and CI/CD pipelines
📊 Consistent Process Standardized token generation across your team
🛠️ Developer Experience Beautiful CLI interface with interactive prompts

🛠️ Implementation Deep Dive

1. The Token Generation Action (app/Actions/GenerateTokenAction.php)

This action handles the core logic of generating a token for a user. It checks if the user exists, creates a new one if not, and generates a token with an optional expiration date.

<?php
 
declare(strict_types=1);
 
namespace App\Actions;
 
use Carbon\Carbon;
use App\Models\User;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;
 
final class GenerateTokenAction
{
public function execute(string $username, ?string $expires = null): array
{
$user = User::query()
->firstOrCreate(
['email' => $username],
[
'name' => $username,
'password' => Hash::make(Str::random(16)),
]
);
 
$user->tokens()->delete();
 
$expiresAt = $expires !== null && $expires !== '' && $expires !== '0' ? Carbon::parse($expires) : null;
$token = $user->createToken(
name: $username,
expiresAt: $expiresAt,
);
 
return [
'user' => $user->name,
'token' => $token->plainTextToken,
'expires_at' => $expiresAt,
'created_at' => $user->created_at,
];
}
}

Key Features:

  • 🔄 Automatic token rotation (deletes old tokens)
  • 🔐 Secure password generation for new users
  • ⏳ Flexible expiration handling
  • 📦 Clean, standardized return format

2. The Artisan Command (app/Console/Commands/GenerateToken.php)

Create a new Artisan command using the following command:

php artisan make:command GenerateToken

After that, replace the contents of the generated file with the following code:

<?php
 
declare(strict_types=1);
 
namespace App\Console\Commands;
 
use App\Actions\GenerateTokenAction;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function Laravel\Prompts\{clear, confirm, info, progress, text};
 
final class GenerateToken extends Command implements PromptsForMissingInput
{
protected $signature = 'generate:token
{username : User email or username}
{expires? : Expiration date (e.g. "1 day", "2025-12-31")}';
 
protected $description = 'Generate or update user token with expiration';
 
public function handle(GenerateTokenAction $action): void
{
$expires = $this->argument('expires') === 'yes'
? text('Enter expiration (e.g., "1 day", "2025-12-31")')
: $this->argument('expires');
 
$results = progress(
label: 'Generating token',
steps: 1,
callback: function () use ($action, $expires): array {
sleep(1); // Simulate a delay for the progress bar note: this is just for demonstration
 
return $action->execute(
username: $this->argument('username'),
expires: $expires,
);
},
);
 
// Extract the first (and only) result from the progress array
$result = $results[0];
$this->line('');
info('✅ API Token Generated Successfully');
$this->table(
['🆔 User', '🔑 Token', '⏳ Expires At'],
[
[
$result['user'],
$result['token'],
$result['expires_at']->toDateTimeString(),
],
]
);
}
 
protected function promptForMissingArgumentsUsing(): array
{
return [
'username' => 'Enter the username or email address',
];
}
 
protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void
{
if (confirm('Do you want to set an expiration date for the token?')) {
$input->setArgument(
'expires',
text('Enter expiration (e.g., "1 day", "2025-12-31")')
);
}
}
}

UX Enhancements:

  • 🎨 Color-coded output
  • 🔄 Progress indicators
  • ❓ Interactive prompts
  • 📝 Clear, organized information display

🏗️ Usage Examples

🔧 Basic Interactive Mode

php artisan generate:token

Prompts for:

  • Username/Email address
  • Whether to set expiration
  • Expiration timeframe if selected

⚡ Direct Command Usage

# Token without expiration
php artisan generate:token [email protected]
 
# Token with 30-day expiration
php artisan generate:token [email protected] "30 days"

🤖 CI/CD Integration

# Create deployment token (expires in 1 hour)
php artisan generate:token [email protected] "1 hour" >> deploy_token.txt

Output

 
✅ API Token Generated Successfully
 
+---------+-----------------------------------------------------+---------------------+
| 🆔 User | 🔑 Token | ⏳ Expires At |
+---------+-----------------------------------------------------+---------------------+
| bb | 50|q2uPCYho0wHnZ2AvPtBia8IB8hp9hRWpfqUD8crA20370e93 | 2025-05-15 07:49:51 |
+---------+-----------------------------------------------------+---------------------+

🚀 Advanced Extensions

you can enhance more features such as given in flow chart.

flow chart


🎯 Conclusion

This implementation provides:

  • Enterprise-grade security 🔐 in a developer-friendly package
  • Beautiful CLI UX 🎨 that teams will love using
  • Production-ready features 🏗️ out of the box
  • Extensible architecture ⚙️ for future needs

Dinesh Uprety

Senior Software Engineer • Writer @ Laranepal • PHP, Laravel, Livewire, TailwindCSS & VueJS • CEO @ Laranepal & Founder @ laracodesnap

Filed in:

Discussion

Login or register to comment or ask questions

No comments yet

Be the first to share your thoughts or ask a question.

Join the conversation

Sign in to share your thoughts with the community.

SPONSORED
Codesnap

Codesnap

Share your code editable and funny templates.