You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Passport创建OAuth令牌遇cURL 28超时错误求助

问题:Laravel Passport密码授权令牌创建时出现cURL超时错误

在按照Laravel官方文档实现Passport密码授权令牌创建时,API返回500错误,具体错误信息如下:

{
    "status": false,
    "message": "Something went wrong",
    "error": "cURL error 28: Operation timed out after 30016 milliseconds with 0 bytes received for http://127.0.0.1:8000/oauth/token"
}

以下是实现谷歌登录并获取令牌的相关代码:

public function googleLogin(Request $request)
{
    $validator = Validator::make($request->all(), [
        'googleId'     => 'required|numeric',
        'name'         => 'required|string',
        'email'        => 'required|string|email',
        'profileImage' => 'nullable|url',
        'device_id'    => 'required|string',
        'device_name'  => 'required|string',
        'fcmToken'     => 'nullable|string',
        'apnToken'     => 'nullable|string',
    ]);

    if ($validator->fails()) {
        return response()->json(['status' => false, 'message' => $validator->errors()], 422);
    }

    try {
        // Find or create user
        $user = User::where('googleId', $request->googleId)
            ->orWhere('email', $request->email)
            ->first();

        $isNewUser = false;
        // Generate a temporary password for OAuth2 grant
        $plainPassword = Str::random(16);

        if (! $user) {
            $user = User::create([
                'name'         => $request->name,
                'email'        => $request->email,
                'googleId'     => $request->googleId,
                'profileImage' => $request->profileImage,
                'password'     => $plainPassword,
                'referralCode' => $this->generateReferralCode(),
                'planId'       => 1,
                'currencyId'   => 2,
                'fcmToken'     => $request->fcmToken,
                'apnToken'     => $request->apnToken,
            ]);
            $isNewUser = true;
            Space::create([
                'userId'        => $user->id,
                'name'          => 'Personal Space',
                'isAutoCreated' => true,
                'spaceType'     => 'personal',
            ]);
        } else {
            // Reset password for OAuth2 grant
            $user->password = $plainPassword;
            $user->save();
        }

        // Device registration and limit enforcement
        $plan = Plan::find($user->planId);
        $limit = $plan ? $plan->deviceLimit : 2;

        UserDevice::firstOrCreate([
            'userId'   => $user->id,
            'deviceId' => $request->device_id,
        ], [
            'deviceName' => $request->device_name,
        ]);

        $deviceCount = UserDevice::where('userId', $user->id)->count();
        if ($deviceCount > $limit) {
            return response()->json([
                'status'  => false,
                'message' => "Device limit exceeded! You can use up to {$limit} devices only.",
            ], 403);
        }

        // Revoke existing tokens for this device
        $user->tokens()->where('name', $request->device_id)->each(function (Token $t) {
            $t->revoke();
            RefreshToken::where('access_token_id', $t->id)->update(['revoked' => true]);
            $t->delete();
        });

        // Issue tokens via OAuth2 password grant
        $oauthResponse = Http::post(config('app.url') . '/oauth/token', [
            'grant_type'    => 'password',
            'client_id'     => env('PASSPORT_PASSWORD_CLIENT_ID'),
            'client_secret' => env('PASSPORT_CLIENT_SECRET'),
            'username'      => $user->email,
            'password'      => $plainPassword,
            'scope'         => '',
        ]);

        $tokenData = json_decode($oauthResponse->body(), true);

        $user->load(['currency', 'devices']);

        return response()->json(array_merge([
            'status'  => true,
            'message' => $isNewUser ? 'Signup successful' : 'Login successful',
            'data'    => ['user' => $user],
        ], $tokenData), $oauthResponse->status());
    } catch (\Exception $e) {
        return response()->json([
            'status'  => false,
            'message' => 'Something went wrong',
            'error'   => $e->getMessage(),
        ], 500);
    }
}
修复方案
  • 直接生成令牌替代内部HTTP请求:
    避免内部请求超时问题,直接调用Passport的API生成令牌,替换原代码中Http::post部分:

    // 替换原有HTTP请求代码
    $tokenInstance = $user->createToken($request->device_id);
    
    $tokenData = [
        'access_token' => $tokenInstance->accessToken,
        'token_type' => 'Bearer',
        'expires_in' => config('passport.access_token_expires_in') * 60,
        'refresh_token' => $tokenInstance->refreshToken,
    ];
    

    此方法无需依赖内部HTTP调用,性能更稳定,还能避免环境配置带来的请求问题。

  • 验证Passport客户端配置:

    • 执行php artisan passport:client --password重新生成密码客户端,确保.env文件中的PASSPORT_PASSWORD_CLIENT_ID和PASSPORT_CLIENT_SECRET与生成的客户端信息一致。
    • 确认APP_URL配置正确,本地开发建议使用127.0.0.1而非localhost,避免DNS解析问题。
  • 优化HTTP请求配置(若坚持使用内部请求):
    给HTTP请求添加超时限制,开发环境可临时禁用SSL验证:

    $oauthResponse = Http::timeout(10)->withOptions(['verify' => false])->post(config('app.url') . '/oauth/token', [
        'grant_type'    => 'password',
        'client_id'     => env('PASSPORT_PASSWORD_CLIENT_ID'),
        'client_secret' => env('PASSPORT_CLIENT_SECRET'),
        'username'      => $user->email,
        'password'      => $plainPassword,
        'scope'         => '',
    ]);
    

内容的提问来源于stack exchange,提问作者Sujeet kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 10:15:55