使用 Laravel Socialite 和 API?
Using Laravel Socialite with an API?
我正在尝试在 api 上使用 Laravel Socialite 包。我尝试将代码传递到我的 api 中以获取用户,但它一直给我一个错误:
Fatal error: Call to a member function pull() on null
由于我是通过 API 执行请求的,因此我将执行以下步骤。
向 api 发送请求 url 以获取代码:
Socialite::with('facebook')->stateless()->redirect()->getTargetUrl()
然后使用上面获取的 url 进行请求,该请求使用 code
参数重定向。
将代码发送到 api 并获取用户:
$fb_user = Socialite::with('facebook')->user();
这是它崩溃的地方。我不确定为什么。
我以前用过这个包,当我只有一个重新加载页面的应用程序时它工作正常。但是当我将它发送到 api(在不同的域上)时它崩溃了。我认为代码的生成方式存在一些问题。有办法解决这个问题吗?
刚刚找到我的答案。需要在两个调用中使用 stateless
:
Socialite::with('facebook')->stateless()->redirect()->getTargetUrl()
$fb_user = Socialite::with('facebook')->stateless()->user();
希望这对某人有所帮助。
我做了 SocialController.php
和 url(POST 请求)/api/social-login
接受 provider
和 access_token
。
SocialAccount
这是一个 laravel 模型,您将在其中提供 provider_user_id 和本地数据库用户 ID。下面是 social_accounts
table
的例子
并且在 SocialController
中:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\User;
use App\SocialAccount;
use Socialite;
class SocialController extends Controller
{
public function social(Request $request) {
$provider = $request->input('provider');
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$social_user = Socialite::driver(SocialAccount::SERVICE_FACEBOOK)->fields([
'name',
'first_name',
'last_name',
'email'
]);
break;
case SocialAccount::SERVICE_GOOGLE:
$social_user = Socialite::driver(SocialAccount::SERVICE_GOOGLE)
->scopes(['profile','email']);
break;
default :
$social_user = null;
}
abort_if($social_user == null , 422,'Provider missing');
$social_user_details = $social_user->userFromToken($request->input('access_token'));
abort_if($social_user_details == null , 400,'Invalid credentials'); //|| $fb_user->id != $request->input('userID')
$account = SocialAccount::where("provider_user_id",$social_user_details->id)
->where("provider",$provider)
->with('user')->first();
if($account){
return $this->issueToken($account->user);
}
else {
// create new user and social login if user with social id not found.
$user = User::where("email",$social_user_details->getEmail())->first();
if(!$user){
// create new social login if user already exist.
$user = new User;
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$user->first_name = $social_user_details->user['first_name'];
$user->last_name = $social_user_details->user['last_name'];
break;
case SocialAccount::SERVICE_GOOGLE:
$user->first_name = $social_user_details->user['name']['givenName'];
$user->last_name = $social_user_details->user['name']['familyName'];
break;
default :
}
$user->email = $social_user_details->getEmail();
$user->username = $social_user_details->getEmail();
$user->password = Hash::make('social');
$user->save();
}
$social_account = new SocialAccount;
$social_account->provider = $provider;
$social_account->provider_user_id = $social_user_details->id;
$user->social_accounts()->save($social_account);
return $this->issueToken($user);
}
}
private function issueToken(User $user) {
$userToken = $user->token() ?? $user->createToken('socialLogin');
return [
"token_type" => "Bearer",
"access_token" => $userToken->accessToken
];
}
}
编辑:
我已经创建了相同的包 https://packagist.org/packages/pimplesushant/laravelsocialiteapi
我正在尝试在 api 上使用 Laravel Socialite 包。我尝试将代码传递到我的 api 中以获取用户,但它一直给我一个错误:
Fatal error: Call to a member function pull() on null
由于我是通过 API 执行请求的,因此我将执行以下步骤。
向 api 发送请求 url 以获取代码:
Socialite::with('facebook')->stateless()->redirect()->getTargetUrl()
然后使用上面获取的 url 进行请求,该请求使用 code
参数重定向。
将代码发送到 api 并获取用户:
$fb_user = Socialite::with('facebook')->user();
这是它崩溃的地方。我不确定为什么。
我以前用过这个包,当我只有一个重新加载页面的应用程序时它工作正常。但是当我将它发送到 api(在不同的域上)时它崩溃了。我认为代码的生成方式存在一些问题。有办法解决这个问题吗?
刚刚找到我的答案。需要在两个调用中使用 stateless
:
Socialite::with('facebook')->stateless()->redirect()->getTargetUrl()
$fb_user = Socialite::with('facebook')->stateless()->user();
希望这对某人有所帮助。
我做了 SocialController.php
和 url(POST 请求)/api/social-login
接受 provider
和 access_token
。
SocialAccount
这是一个 laravel 模型,您将在其中提供 provider_user_id 和本地数据库用户 ID。下面是 social_accounts
table
并且在 SocialController
中:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\User;
use App\SocialAccount;
use Socialite;
class SocialController extends Controller
{
public function social(Request $request) {
$provider = $request->input('provider');
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$social_user = Socialite::driver(SocialAccount::SERVICE_FACEBOOK)->fields([
'name',
'first_name',
'last_name',
'email'
]);
break;
case SocialAccount::SERVICE_GOOGLE:
$social_user = Socialite::driver(SocialAccount::SERVICE_GOOGLE)
->scopes(['profile','email']);
break;
default :
$social_user = null;
}
abort_if($social_user == null , 422,'Provider missing');
$social_user_details = $social_user->userFromToken($request->input('access_token'));
abort_if($social_user_details == null , 400,'Invalid credentials'); //|| $fb_user->id != $request->input('userID')
$account = SocialAccount::where("provider_user_id",$social_user_details->id)
->where("provider",$provider)
->with('user')->first();
if($account){
return $this->issueToken($account->user);
}
else {
// create new user and social login if user with social id not found.
$user = User::where("email",$social_user_details->getEmail())->first();
if(!$user){
// create new social login if user already exist.
$user = new User;
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$user->first_name = $social_user_details->user['first_name'];
$user->last_name = $social_user_details->user['last_name'];
break;
case SocialAccount::SERVICE_GOOGLE:
$user->first_name = $social_user_details->user['name']['givenName'];
$user->last_name = $social_user_details->user['name']['familyName'];
break;
default :
}
$user->email = $social_user_details->getEmail();
$user->username = $social_user_details->getEmail();
$user->password = Hash::make('social');
$user->save();
}
$social_account = new SocialAccount;
$social_account->provider = $provider;
$social_account->provider_user_id = $social_user_details->id;
$user->social_accounts()->save($social_account);
return $this->issueToken($user);
}
}
private function issueToken(User $user) {
$userToken = $user->token() ?? $user->createToken('socialLogin');
return [
"token_type" => "Bearer",
"access_token" => $userToken->accessToken
];
}
}
编辑:
我已经创建了相同的包 https://packagist.org/packages/pimplesushant/laravelsocialiteapi