mydaniel/laravel-temporary-tokens
Installation:
composer require mydaniel/laravel-temporary-tokens
php artisan vendor:publish --provider="MyDaniel\TemporaryTokens\TemporaryTokensServiceProvider" --tag="config"
php artisan vendor:publish --provider="MyDaniel\TemporaryTokens\TemporaryTokensServiceProvider" --tag="migrations"
php artisan migrate
First Use Case: Generate a token for a user (e.g., password reset):
use MyDaniel\TemporaryTokens\Facades\TemporaryToken;
$token = TemporaryToken::generate(
user: $user,
length: 6,
expiresAt: now()->addMinutes(15),
maxUses: 1,
metadata: ['purpose' => 'password_reset']
);
Validate a Token:
$isValid = TemporaryToken::validate($tokenValue, $user);
Consume the Token:
$consumed = TemporaryToken::consume($tokenValue, $user);
config/temporary-tokens.php (adjust token length, expiration defaults, etc.).php artisan temporary-tokens:prune (run via cron or manually to clean up expired tokens).MyDaniel\TemporaryTokens\Facades\TemporaryToken (primary entry point for most operations).Token Generation:
$token = TemporaryToken::generate(
user: $user,
length: 8,
expiresAt: now()->addMinutes(30),
metadata: ['device' => 'mobile']
);
$tokens = TemporaryToken::generateMany(
userIds: [1, 2, 3],
length: 6,
expiresAt: now()->addHours(1)
);
Token Validation and Consumption:
$isValid = TemporaryToken::validate(
$tokenValue,
$user,
fn ($metadata) => $metadata['purpose'] === 'password_reset'
);
$consumed = TemporaryToken::consume($tokenValue, $user, function ($token) {
// Perform action after token is consumed (e.g., update user password).
$user->forceFill(['password' => bcrypt('new_password')])->save();
});
Token Management:
$tokens = TemporaryToken::forUser($user)->get();
$tokens = TemporaryToken::whereMetadata('purpose', 'email_verification')->get();
$newToken = TemporaryToken::regenerate($user, $oldTokenValue);
Integration with Eloquent:
// In User model:
public function tokens()
{
return $this->hasMany(TemporaryToken::class);
}
$user->tokens()->where('purpose', 'login')->first();
Custom Token Storage: Override the default storage by binding a custom repository:
// In a service provider:
$this->app->bind(
MyDaniel\TemporaryTokens\Contracts\TokenRepository::class,
App\Repositories\CustomTokenRepository::class
);
Event-Based Workflows:
Listen for token events (e.g., TokenGenerated, TokenConsumed) to trigger side effects:
// In EventServiceProvider:
protected $listen = [
\MyDaniel\TemporaryTokens\Events\TokenGenerated::class => [
\App\Listeners\SendTokenViaEmail::class,
],
];
Rate Limiting: Combine with Laravel's rate limiting to restrict token generation/consumption:
use Illuminate\Cache\RateLimiting\Limit;
RateLimiter::for('generate_tokens', function (Request $request) {
return Limit::perMinute(5)->by($request->user()->id);
});
Token Expiration Handling:
php artisan temporary-tokens:prune manually or schedule it via cron (e.g., daily):
* * * * * cd /path-to-project && php artisan temporary-tokens:prune >> /dev/null 2>&1
TemporaryToken::prune() in a scheduled job for finer control.Metadata Serialization:
json_encode() explicitly:
$metadata = ['data' => json_encode(['key' => 'value'])];
Token Consumption Race Conditions:
DB::transaction(function () use ($tokenValue, $user) {
$consumed = TemporaryToken::consume($tokenValue, $user);
});
Token Length and Security:
config/temporary-tokens.php or override dynamically:
$token = TemporaryToken::generate(..., length: 12);
TemporaryToken::generateAlphanumeric() for mixed-case tokens.Model Association:
user_id) can lead to orphaned tokens.TemporaryToken::generate(user: $user, ...);
Query Logs: Enable Laravel's query logging to inspect token-related queries:
DB::enableQueryLog();
$token = TemporaryToken::generate(...);
dd(DB::getQueryLog());
Token Inspection: Dump token details for debugging:
$token = TemporaryToken::find($tokenValue);
dd($token->toArray());
Event Listeners: Temporarily log token events to trace workflows:
// In a listener:
\Log::info('Token generated', ['token' => $token->value, 'metadata' => $token->metadata]);
Custom Token Generators: Extend the default generator to support custom logic (e.g., time-based tokens):
use MyDaniel\TemporaryTokens\Contracts\TokenGenerator;
class CustomTokenGenerator implements TokenGenerator
{
public function generate(int $length): string
{
return Str::random($length); // Or custom logic.
}
}
Bind it in a service provider:
$this->app->bind(TokenGenerator::class, CustomTokenGenerator::class);
Token Validation Rules: Create reusable validation rules for tokens:
use Illuminate\Validation\Rule;
$rules = [
'token' => [
'required',
Rule::exists('temporary_tokens', 'value')
->where('user_id', $user->id)
->where('expires_at', '>', now())
->where('max_uses', '>', \DB::raw('(SELECT COUNT(*) FROM token_consumptions WHERE token_id = temporary_tokens.id)')),
],
];
Token Notifications: Extend the package to send notifications (e.g., emails/SMS) when tokens are generated:
// In a listener for TokenGenerated:
$user->notify(new TokenGeneratedNotification($token));
Testing: Use the package's testing helpers to mock tokens:
use MyDaniel\TemporaryTokens\Testing\Fakes\FakeToken;
$fakeToken = FakeToken::create($user, '123456');
$this->assertTrue(TemporaryToken::validate('123456', $user));
How can I help you explore Laravel packages today?