Laravel Socialite
簡介
除了一般基於表單的登入方式之外,在 Laravel 中,還可以通過 Laravel Socialite 來以簡單、方便的方式使用 OAuth Provider 登入。目前 Socialite 支援使用 Facebook、Twitter、LinkedIn、Google、GitHub、GitLab、Bitbucket,與 Slack 等服務來進行登入。
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 1.0)、twitter-oauth-2
(OAuth 2.0)、linkedin-openid
、google
、github
、gitlab
、bitbucket
或 slack
等相對應的 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 傳回來的回呼。下面的範例說明如何實作這兩個 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::updateOrCreate([9 'github_id' => $githubUser->id,10 ], [11 'name' => $githubUser->name,12 'email' => $githubUser->email,13 'github_token' => $githubUser->token,14 'github_refresh_token' => $githubUser->refreshToken,15 ]);1617 Auth::login($user);1819 return redirect('/dashboard');20});
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::updateOrCreate([9 'github_id' => $githubUser->id,10 ], [11 'name' => $githubUser->name,12 'email' => $githubUser->email,13 'github_token' => $githubUser->token,14 'github_refresh_token' => $githubUser->refreshToken,15 ]);1617 Auth::login($user);1819 return redirect('/dashboard');20});
有關各個 OAuth Provider 所提供的使用者資訊,請參考說明文件中有關取得使用者詳細資料的部分。
Access Scope (存取範圍)
在為使用者重新導向前,我們可以使用 scopes
方法來指定這個登入驗證 Request 中要包含的「Scope (範圍)」。此方法會將所指定的 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();
Slack Bot 的 Scope
Slack's API provides different types of access tokens, each with their own set of permission scopes. Socialite is compatible with both of the following Slack access tokens types:
- Bot (prefixed with
xoxb-
) - User (prefixed with
xoxp-
)
By default, the slack
driver will generate a user
token and invoking the driver's user
method will return the user's details.
Bot tokens are primarily useful if your application will be sending notifications to external Slack workspaces that are owned by your application's users. To generate a bot token, invoke the asBotUser
method before redirecting the user to Slack for authentication:
1return Socialite::driver('slack')2 ->asBotUser()3 ->setScopes(['chat:write', 'chat:write.public', 'chat:write.customize'])4 ->redirect();
1return Socialite::driver('slack')2 ->asBotUser()3 ->setScopes(['chat:write', 'chat:write.public', 'chat:write.customize'])4 ->redirect();
In addition, you must invoke the asBotUser
method before invoking the user
method after Slack redirects the user back to your application after authentication:
1$user = Socialite::driver('slack')->asBotUser()->user();
1$user = Socialite::driver('slack')->asBotUser()->user();
When generating a bot token, the user
method will still return a Laravel\Socialite\Two\User
instance; however, only the token
property will be hydrated. This token may be stored in order to send notifications to the authenticated user's Slack workspaces.
可選的參數
有一些 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 狀態驗證。此方法適合用於在不使用 Cookie 的 Stateless API 工作階段中加入社群網站登入。
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('google')->stateless()->user();
1use Laravel\Socialite\Facades\Socialite;23return Socialite::driver('google')->stateless()->user();
Twitter OAuth 1.0 Driver 不支援 Stateless 的登入驗證。