Laravel Passport与Socialite实现SSO登录后无法跳转回调问题
问题描述
我正在开发一个基于Laravel Passport的应用B,用于为同体系的其他Laravel应用处理授权,当前设定的流程如下:
- 应用A的用户点击登录按钮
- 跳转至应用B
- 若用户已登录,直接跳转至回调地址
- 若用户未登录,引导其通过Google账号登录后跳转回调地址
目前遇到的问题:用户完成登录后无法跳转至应用A的回调地址,流程卡在回调环节。
相关代码与配置
SocialiteController.php
class SocialiteController extends Controller { public function redirectProvider() { return Socialite::driver('github')->stateless()->redirect(); } public function callbackProvider() { // 获取尝试登录的用户 $githubUser = Socialite::driver('github')->stateless()->user(); // 检查用户是否存在,不存在则创建 $user = User::updateOrCreate([ 'email' => $githubUser->email ], [ 'name' => $githubUser->name, 'email' => $githubUser->email, 'github_token' => $githubUser->token, 'github_refresh_token' => $githubUser->refresh_token, 'last_login' => now() ]); // 为用户创建认证令牌 Auth::guard('api')->setUser($user); // 此处应跳转至应用A,并带上获取Bearer令牌所需的code查询参数 } }
config/auth.php
'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ] ],
config/passport.php 中的guard配置
'guard' => 'web',
路由配置
Route::controller(SocialiteController::class)->group(function () { Route::get('redirect', 'redirectProvider')->name('socialite.redirect'); Route::get('callback', 'callbackProvider')->name('socialite.callback'); });
授权请求示例URL
http://localhost:7003/oauth/authorize?client_id=9a622876-4a3a-4046-a41d-76b303fa0f4e&redirect_uri=http://localhost:7005&response_type=code&scope=*
解决方案
问题核心是丢失了应用A发起授权请求时的上下文参数,导致Google登录回调后无法恢复Passport的授权流程。按以下步骤修正:
- 保存授权请求参数
修改redirectProvider方法,把应用A传来的授权参数暂存到session:
public function redirectProvider() { // 保存授权请求的关键参数 session()->put('oauth_request', request()->only('client_id', 'redirect_uri', 'response_type', 'scope', 'state')); return Socialite::driver('github')->stateless()->redirect(); }
- 回调后恢复授权流程
用户登录成功后,取出暂存的参数,生成Passport授权码并跳转回应用A:
public function callbackProvider() { $githubUser = Socialite::driver('github')->stateless()->user(); $user = User::updateOrCreate([ 'email' => $githubUser->email ], [ 'name' => $githubUser->name, 'email' => $githubUser->email, 'github_token' => $githubUser->token, 'github_refresh_token' => $githubUser->refresh_token, 'last_login' => now() ]); // 使用web guard登录用户(Passport授权流程依赖session认证) Auth::guard('web')->login($user); // 取出之前保存的授权参数 $oauthRequest = session()->pull('oauth_request'); // 查找对应客户端 $client = \Laravel\Passport\Client::find($oauthRequest['client_id']); // 创建授权码 $authCode = \Laravel\Passport\AuthCode::create([ 'user_id' => $user->id, 'client_id' => $client->id, 'scopes' => explode(' ', $oauthRequest['scope']), 'redirect_uri' => $oauthRequest['redirect_uri'], 'expires_at' => now()->addMinutes(5), ]); // 拼接跳转URL,携带授权码和state参数 $redirectUrl = $oauthRequest['redirect_uri'] . '?code=' . $authCode->id . '&state=' . $oauthRequest['state']; return redirect($redirectUrl); }
- 确认session配置正常
确保应用B的session配置(config/session.php)有效,因为我们需要用session暂存授权参数。
内容的提问来源于stack exchange,提问作者sNok3
相关产品推荐
相关产品推荐

