$scopes * @return array{token: ApiToken, plain_text: string} */ public function create(string $name, array $scopes, ?int $expiresInDays = null): array { $plain = config('api.token_prefix') . Str::random(48); $prefix = substr($plain, 0, 12); $token = ApiToken::create([ 'name' => $name, 'token_prefix' => $prefix, 'token_hash' => hash('sha256', $plain), 'scopes' => array_values(array_unique($scopes)), 'expires_at' => $expiresInDays ? now()->addDays($expiresInDays) : null, ]); return ['token' => $token, 'plain_text' => $plain]; } public function findByPlainText(string $plainText): ?ApiToken { if (! str_starts_with($plainText, config('api.token_prefix'))) { return null; } $prefix = substr($plainText, 0, 12); $token = ApiToken::where('token_prefix', $prefix)->first(); if ($token === null || ! hash_equals($token->token_hash, hash('sha256', $plainText))) { return null; } if ($token->expires_at !== null && $token->expires_at->isPast()) { return null; } $token->update(['last_used_at' => now()]); return $token; } public function revoke(ApiToken $token): void { $token->delete(); } /** * @return list */ public function listAll(): array { return ApiToken::orderByDesc('created_at')->get()->all(); } }