Laravel集成Firebase时反复出现invalid_grant错误如何解决?
invalid_grant问题 我之前在Laravel项目里集成Firebase的时候,也反复踩过这个invalid_grant的坑,结合你的代码和问题,给你几个亲测有效的排查和解决方向:
先梳理你的代码实现
控制器引入部分:
namespace App\Http\Controllers; use Kreait\Firebase; use Kreait\Firebase\Factory; use Kreait\Firebase\ServiceAccount; use Kreait\Firebase\Database;
store函数逻辑:
public function store(Request $request) { $serviceAccount = ServiceAccount::fromJsonFile(__DIR__.'/resturant-f7e23-firebase-adminsdk-sziig-4bd11864d7.json'); $firebase = (new Factory) ->withServiceAccount($serviceAccount) ->withDatabaseUri('https://resturant-f7e23.firebaseio.com/') ->create(); $db = $firebase->getDatabase(); $db->getReference('reserves/'.'1') ->set([ 'name' => 'John', 'emails' => 'john@gmail.com', 'website' => 'http://john.com', ]); return ('You did it'); }
从你提到的错误截图来看,核心报错是invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe,下面是针对性的解决方法:
检查服务账号JSON文件的路径与有效性
你用__DIR__拼接JSON文件路径,要确认这个路径确实指向正确的文件。比如__DIR__对应当前控制器所在的目录(一般是app/Http/Controllers),如果JSON文件没放在这里,就得调整路径——更规范的做法是把JSON文件放到storage/app/firebase/目录,然后用storage_path('app/firebase/xxx.json')来引用。另外,建议重新下载一次服务账号JSON文件,避免文件下载时损坏或内容被修改,确保里面的client_email和private_key完整且正确。同步服务器系统时间
这是触发invalid_grant最常见的原因!Google的JWT令牌对时间精度要求极高,如果你的服务器系统时间和Google服务器时间偏差超过几分钟,就会直接报错。你可以在服务器上执行命令同步NTP时间:# Ubuntu/Debian系统 sudo timedatectl set-ntp on # CentOS/RHEL系统 sudo ntpdate pool.ntp.org同步完成后重启Laravel项目,大概率能解决问题。
确认服务账号的权限配置
登录Firebase控制台,找到你的项目→【设置】→【服务账号】,确认你正在使用的服务账号已经被分配了足够的权限——至少要给它【Editor】角色,或者更细粒度的【Firebase Database Admin】权限,确保它具备读写Firebase数据库的权限。优化Firebase实例初始化(避免重复创建)
你现在每次调用store方法都会重新初始化Firebase实例,不仅效率低,还可能导致令牌缓存异常。建议把Firebase实例配置成单例,比如创建一个服务提供者:- 把JSON文件放到
storage/app/firebase-service-account.json - 创建
app/Providers/FirebaseServiceProvider.php:
namespace App\Providers; use Illuminate\Support\ServiceProvider; use Kreait\Firebase\Factory; use Kreait\Firebase\ServiceAccount; class FirebaseServiceProvider extends ServiceProvider { public function register() { $this->app->singleton('firebase', function ($app) { $serviceAccount = ServiceAccount::fromJsonFile(storage_path('app/firebase-service-account.json')); return (new Factory) ->withServiceAccount($serviceAccount) ->withDatabaseUri('https://resturant-f7e23.firebaseio.com/') ->create(); }); } }- 在
config/app.php的providers数组里添加App\Providers\FirebaseServiceProvider::class - 在控制器里直接注入使用:
public function store(Request $request, $firebase) { $db = $firebase->getDatabase(); $db->getReference('reserves/1') ->set([ 'name' => 'John', 'emails' => 'john@gmail.com', 'website' => 'http://john.com', ]); return 'You did it'; }- 把JSON文件放到
按照上面的步骤逐一排查,应该就能解决你的invalid_grant问题了!
内容的提问来源于stack exchange,提问作者MD. HASAN MUNSI

