Laravel Socialite
簡介
除了一般基於表單的登入方式之外,在 Laravel 中,還可以通過 Laravel Socialite 來以簡單、方便的方式使用 OAuth Provider 登入。目前 Socialite 支援使用 Facebook、Twitter、LinkedIn、Google、GitHub、GitLab 和 Bitbucket 等服務來進行登入。
Socialite Providers 網站上還提供了由社群維護的其他平台的 Adapter。
安裝
若要開始使用 Socialite,請使用 Composer 套件管理器將 Socialite 套件新增至專案的相依性套件中:
1composer require laravel/socialite
1composer require laravel/socialite
更新 Socialite
將 Telescope 升級到新的主要 (Major) 版本時,請務必仔細閱讀升級指南。
設定
在使用 Socialite 之前,我們需要先為網站所要用的 OAuth Provider 設定憑證 (Credential)。請將這些憑證放在專案的 config/services.php
設定檔中,並依照你的專案所要使用的 OAuth Provider,設定 facebook
、twitter
(OAuth )、twitter-oauth-
(OAuth )、linkedin
、google
、github
、gitlab
或 bitbucket
等相對應的 key:
1'github' => [2 'client_id' => env('GITHUB_CLIENT_ID'),3 'client_secret' => env('GITHUB_CLIENT_SECRET'),4 'redirect' => 'http://example.com/callback-url',5],
1'github' => [2 'client_id' => env('GITHUB_CLIENT_ID'),3 'client_secret' => env('GITHUB_CLIENT_SECRET'),4 'redirect' => 'http://example.com/callback-url',5],
如果 redirect
選項包含相對路徑,則會為自動解析成完整的 URL。
登入
Routing
要使用 OAuth Provider 來登入使用者,需要兩個 Route:一個用來將使用者重新導向到 OAuth Provider,另一個用來接收登入後 Provider 傳回來的回呼。下面的範例 Controller 將說明如何實作這兩個 Route:
1use Laravel\Socialite\Facades\Socialite;23Route::get('/auth/redirect', function () {4 return Socialite::driver('github')->redirect();5});67Route::get('/auth/callback', function () {8 $user = Socialite::driver('github')->user();910 // $user->token11});
1use Laravel\Socialite\Facades\Socialite;23Route::get('/auth/redirect', function () {4 return Socialite::driver('github')->redirect();5});67Route::get('/auth/callback', function () {8 $user = Socialite::driver('github')->user();910 // $user->token11});
Socialite
Facade 上的 redirect
方法負責將使用者重新導向到 OAuth Provider。當使用者登入後,user
方法會讀取傳入的 Request,並向 OAuth Provider 取得使用者的資訊。
登入與檔案儲存
從 OAuth Provider 取得使用者後,就可以判斷該使用者是否存在我們的網站中,並登入該使用者。如果使用者不存在網站資料庫中,可以在資料庫中建立:
1use App\Models\User;2use Illuminate\Support\Facades\Auth;3use Laravel\Socialite\Facades\Socialite;45Route::get('/auth/callback', function () {6 $githubUser = Socialite::driver('github')->user();78 $user = User::where('github_id', $githubUser->id)->first();910 if ($user) {11 $user->update([12 'github_token' => $githubUser->token,13 'github_refresh_token' => $githubUser->refreshToken,14 ]);15 } else {16 $user = User::create([17 'name' => $githubUser->name,18 'email' => $githubUser->email,19 'github_id' => $githubUser->id,20 'github_token' => $githubUser->token,21 'github_refresh_token' => $githubUser->refreshToken,22 ]);23 }2425 Auth::login($user);2627 return redirect('/dashboard');28});
1use App\Models\User;2use Illuminate\Support\Facades\Auth;3use Laravel\Socialite\Facades\Socialite;45Route::get('/auth/callback', function () {6 $githubUser = Socialite::driver('github')->user();78 $user = User::where('github_id', $githubUser->id)->first();910 if ($user) {11 $user->update([12 'github_token' => $githubUser->token,13 'github_refresh_token' => $githubUser->refreshToken,14 ]);15 } else {16 $user = User::create([17 'name' => $githubUser->name,18 'email' => $githubUser->email,19 'github_id' => $githubUser->id,20 'github_token' => $githubUser->token,21 'github_refresh_token' => $githubUser->refreshToken,22 ]);23 }2425 Auth::login($user);2627 return redirect('/dashboard');28});
有關各個 OAuth Provider 所提供的使用者資訊,請參考說明文件中有關取得使用者詳細資料的部分。
Access Scope (存取範圍)
在重新導向使用者前,我們還可以使用 scopes
方法來在登入驗證 Request 中加上額外的「Scopes (範圍)」。此方法會將所提供的 Scopes 與其他現有的 Scopes 合併:
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('github')4 ->scopes(['read:user', 'public_repo'])5 ->redirect();
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('github')4 ->scopes(['read:user', 'public_repo'])5 ->redirect();
可以使用 setScopes
方法來複寫登入驗證 Request 上的所有已存在的 Scopes:
1return Socialite::driver('github')2 ->setScopes(['read:user', 'public_repo'])3 ->redirect();
1return Socialite::driver('github')2 ->setScopes(['read:user', 'public_repo'])3 ->redirect();
可選的參數
有一些 OAuth Provider 還支援在重新導向 Request 上設定可選的參數。若要在 Request 中包含任何可選的參數,請呼叫 with
方法並提供一個關聯式陣列:
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('google')4 ->with(['hd' => 'example.com'])5 ->redirect();
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('google')4 ->with(['hd' => 'example.com'])5 ->redirect();
在使用 with
方法時,請小心不要傳入任何保留字 (Reserved Keywords),如 state
或 response_type
等。
取得使用者詳細資料
使用者被重新導向到登入驗證 Callback Route 後,就可以使用 Socialite 的 user
方法來取得使用者的詳細資料。user
方法回傳的使用者物件提供了多種屬性與方法,我們可以將與該使用者有關的資訊存在資料庫中。根據所使用的 OAuth Provider 支援的是 OAuth 1.0 還是 OAuth 2.0,該物件上會有不同的屬性與方法:
1use Laravel\Socialite\Facades\Socialite;23Route::get('/auth/callback', function () {4 $user = Socialite::driver('github')->user();56 // OAuth 2.0 Provider...7 $token = $user->token;8 $refreshToken = $user->refreshToken;9 $expiresIn = $user->expiresIn;1011 // OAuth 1.0 Provider...12 $token = $user->token;13 $tokenSecret = $user->tokenSecret;1415 // 所有 Provider...16 $user->getId();17 $user->getNickname();18 $user->getName();19 $user->getEmail();20 $user->getAvatar();21});
1use Laravel\Socialite\Facades\Socialite;23Route::get('/auth/callback', function () {4 $user = Socialite::driver('github')->user();56 // OAuth 2.0 Provider...7 $token = $user->token;8 $refreshToken = $user->refreshToken;9 $expiresIn = $user->expiresIn;1011 // OAuth 1.0 Provider...12 $token = $user->token;13 $tokenSecret = $user->tokenSecret;1415 // 所有 Provider...16 $user->getId();17 $user->getNickname();18 $user->getName();19 $user->getEmail();20 $user->getAvatar();21});
以 Token 來取得使用者詳細資料 (OAuth2)
若你已經擁有使用者的有效 Access Token,就可使用 Socialite 的 userFromToken
方法來取得該使用者的詳細資料:
1use Laravel\Socialite\Facades\Socialite;23$user = Socialite::driver('github')->userFromToken($token);
1use Laravel\Socialite\Facades\Socialite;23$user = Socialite::driver('github')->userFromToken($token);
以 Token 與 Secret 來取得使用者詳細資料 (OAuth1)
若你已經擁有使用者的有效 Token 與 Secret,就可使用 Socialite 的 userFromTokenAndSecret
方法來取得該使用者的詳細資料:
1use Laravel\Socialite\Facades\Socialite;23$user = Socialite::driver('twitter')->userFromTokenAndSecret($token, $secret);
1use Laravel\Socialite\Facades\Socialite;23$user = Socialite::driver('twitter')->userFromTokenAndSecret($token, $secret);
Stateless 的登入驗證
使用 stateless
方法可關閉 Session 狀態驗證。此方法適合用在 API 中加入社群網站登入:
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('google')->stateless()->user();
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('google')->stateless()->user();
Twitter Driver 使用 OAuth 1.0 來驗證登入,因此不支援 Stateless 的登入驗證。