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

Laravel应用集成Google Identity登录时持续出现401未授权错误

问题:Laravel Sanctum集成Google身份认证时401错误,无法跳转至Gallery组件

已通过Laravel Sanctum完成用户登录/注册功能,现在要新增Google Identity作为认证方式。尝试访问/api/google-login接口触发dd("test")失败,收到POST http://localhost:8000/api/google-login 401 (Unauthorized)错误。已成功从Google JWT解析出用户对象,但无法跳转至Gallery组件(Sanctum原生登录/注册成功后可正常跳转)。


相关代码

api.php

Route::middleware('auth:sanctum')->post('/google-login', [AuthController::class, 'googleLogin']);

AuthController.php

public function googleLogin(Request $request)
{
    dd("test");

    $token = $request->input('token');

    // Validate and process the token, obtain user data from Google Identity Services

    // Assuming you have retrieved the user data from Google Identity Services
    $user = [
        'name' => 'John Doe',
        'email' => 'johndoe@example.com',
        // Other user data...
    ];

    // Create a new Sanctum token for the authenticated user
    $accessToken = $this->createToken($user);

    return response()->json([
        'access_token' => $accessToken,
        'user' => $user,
    ]);
}

Home.js

useEffect(() => {
    // Using window.onload to ensure that the code is executed
    // only after the Google Sign-In library is fully loaded
    // in the app.blade.php file
    /* global google */
    window.onload = function () {
        google.accounts.id.initialize({
            client_id: 'my-client-id.com',
            callback: handleCallbackResponse
        });

        google.accounts.id.renderButton(
            document.getElementById('signInDiv'),
            { theme: "outline", size: "large" }
        )
    };
}, []);


function handleCallbackResponse(response) {
    console.log("response", response);
    console.log("Encoded JWT ID token: " + response.credential);
    let userObject = jwtDecode(response.credential);
    console.log(userObject);

    // Make a POST request to your Laravel API endpoint for Google login
    ApiClient.post('/google-login', { token: response.credential }, {
        headers: {
            'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
        }
    })
        .then(response => {
            const { access_token, user } = response.data;

            // Store the access token and user object in local storage or cookies
            localStorage.setItem('access_token', access_token);
            localStorage.setItem('user', JSON.stringify(user));

            // Redirect to the Gallery component
            history.push('/gallery');
        })
        .catch(error => {
            console.log(error);
        });
}

function handleSignOut() {
    setUser(null);
    document.getElementById("signInDiv").hidden = false;
    localStorage.removeItem("user"); // Remove user object from local storage on sign out
}

问题分析与解决

1. 401 Unauthorized错误根源

你的/api/google-login路由加了auth:sanctum中间件,但Google登录本身是认证入口,此时用户还未通过Sanctum认证,自然会被拦截。

修复方式:移除路由的auth:sanctum中间件:

Route::post('/google-login', [AuthController::class, 'googleLogin']);

2. 无法跳转至Gallery组件的问题

当前接口因为dd("test")中断执行,根本不会返回access_token和用户数据,前端then回调无法触发,所以跳转逻辑不会执行。另外需要修正后端的用户令牌生成逻辑:

修正后的googleLogin方法示例

use Illuminate\Support\Facades\Http;
use App\Models\User;

public function googleLogin(Request $request)
{
    $token = $request->input('token');

    // 调用Google官方接口校验令牌有效性
    $response = Http::get('https://oauth2.googleapis.com/tokeninfo', [
        'id_token' => $token,
    ]);

    if (!$response->successful()) {
        return response()->json(['error' => '无效的Google令牌'], 401);
    }

    $googleUser = $response->json();

    // 查找本地用户,不存在则创建
    $user = User::firstOrCreate(
        ['email' => $googleUser['email']],
        ['name' => $googleUser['name']]
    );

    // 生成Sanctum令牌(必须基于Eloquent用户实例调用)
    $accessToken = $user->createToken('google-auth-token')->plainTextToken;

    return response()->json([
        'access_token' => $accessToken,
        'user' => $user,
    ]);
}

3. 额外注意事项

  • 确保Google Cloud Console已配置正确的授权域名(本地开发需添加http://localhost:8000)
  • 前端后续请求需携带Authorization: Bearer {access_token}请求头,才能通过Sanctum认证
  • 确认前端history.push的路由配置正确,且Gallery组件的认证拦截逻辑能识别本地存储的access_token

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 12:02:47