config('app.url'), 'sub' => $client->client_id, 'aud' => $aud, 'iat' => $now, 'exp' => $exp, 'jti' => \Illuminate\Support\Str::uuid()->toString(), 'scope' => $client->scopes, 'client_db_id' => $client->id, ]; return \Firebase\JWT\JWT::encode($payload, $privateKey, 'RS256'); } /** * Issue a refresh token for the client (random string, store in DB as needed) */ public static function issueRefreshToken($client) { return false; // $rawToken = \Illuminate\Support\Str::random(64); // $hashedToken = hash('sha256', $rawToken); // or use bcrypt if you prefer // $refresh = RefreshToken::create([ // 'client_id' => $client->id, // 'token' => $hashedToken, // 'expires_at' => now()->addDays(30), // 'revoked' => false, // ]); // // Return the raw token to the client // return $rawToken; } /** * Verify JWT token and return decoded payload or false */ public static function verifyToken($token) { $publicKeyPath = env('JWT_PUBLIC_KEY_PATH', storage_path('keys/public.pem')); if (!file_exists($publicKeyPath)) { throw new \Exception('JWT public key not found'); } $publicKey = file_get_contents($publicKeyPath); try { return \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key($publicKey, 'RS256')); } catch (\Exception $e) { return false; } } public static function verifyClientToken($token) { try { $parts = explode('.', $token); if (count($parts) !== 3) { return false; } $payload = json_decode(base64_decode(strtr($parts[1], '-_', '+/'))); $clientId = $payload->sub ?? null; if (!$clientId) { return false; } $clients = config('api_clients.clients'); $client = collect($clients)->where('api_key', $clientId)->first(); if (!$client || !isset($client['api_secret'])) { return false; } return \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key($client['api_secret'], 'HS256')); } catch (\Exception $e) { return false; } } }