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

Laravel中Socialite登录后调用API返回401未授权问题

问题根源

这个401错误的核心问题很明确:Web端通过Socialite登录用的是Session认证,但你的API路由用了auth:sanctum中间件,默认要求请求携带Sanctum Token。现在前端调用API时既没带Token,也没配置让Sanctum识别已有的Session登录状态,所以接口不认当前登录用户。

两种解决方案

根据你的项目场景(同域/跨域)选一种就行:

方案1:让Sanctum识别Session登录(同域前端用这个)

如果你的Vue前端和后端是同域的,最简单的办法是让Sanctum支持Session认证:

  1. 修改config/sanctum.php里的stateful数组,把你的前端域名加进去,比如前端跑在localhost:8080,就改成:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
    '%s%s',
    'localhost,localhost:3000,localhost:8080,127.0.0.1,127.0.0.1:8000,::1',
    env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
  1. 给Axios开启自动携带Cookie的配置,在Vue项目里全局设置:
axios.defaults.withCredentials = true;

这样同域的API请求会自动携带Session Cookie,Sanctum就能认出登录的用户了,不用额外传Token。

方案2:生成Token传给前端(跨域/前后端分离用这个)

如果是跨域场景,就得生成Sanctum Token并让前端存下来,请求时带上:

  1. 先修复Socialite回调里的Token逻辑,不管新老用户都生成Token并存好,还要传给前端:
public function handleProviderCallback($provider)
{
    try {
        $user_social = Socialite::driver($provider)->stateless()->user();
        $current_user = UserSocial::where("account_id", $user_social->getId())->first();
        $user = null;
        $token = '';

        if ($current_user) {
            $user = User::findOrFail($current_user->user_id);
            // 给老用户生成新Token
            $token = $user->createToken('social-login')->plainTextToken;
            $current_user->token = $token;
            $current_user->save();
        } else {
            $user = new User();
            $user->name = $user_social->getName();
            $user->email = $user_social->getEmail();
            $user->password = bcrypt($user_social->getId());
            $user->login_with = $provider;
            $user->assignRole(User::ROLE_USER);
            $user->save();

            $token = $user->createToken('social-login')->plainTextToken;

            $user_account = new UserSocial();
            $user_account->user_id = $user->id;
            $user_account->account_id = $user_social->getId();
            $user_account->provider = $provider;
            $user_account->token = $token;
            $user_account->save();
        }

        Auth::login($user);
        // 把Token存到Session,前端页面渲染时能拿到
        session(['sanctum_token' => $token]);
        return redirect()->intended("/");
    } catch (ClientException $exception) {
       return $this->errorResponse(["message" => "Invalid credentials provided."]);
    }
}
  1. 前端拿到Token后,给Axios加请求头:
    比如后端在页面里把Token注入成全局变量,然后:
const token = window.sanctumToken;
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;

或者从页面的meta标签取:

const token = document.querySelector('meta[name="sanctum-token"]').content;
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
必做检查
  • 你的User模型必须引入HasApiTokens trait,不然生成不了Token:
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
    // ...
}
  • 如果用方案1,还要修改config/cors.php里的supports_credentials为true,不然Cookie传不过去。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 23:05:25