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
相关产品推荐
相关产品推荐

