跳轉至內容

Laravel Socialite

簡介

除了傳統的基於表單的身份驗證外,Laravel 還提供了一種簡單、便捷的方法,透過 Laravel Socialite 使用 OAuth 提供商進行身份驗證。Socialite 目前支援透過 Facebook、X、LinkedIn、Google、GitHub、GitLab、Bitbucket 和 Slack 進行身份驗證。

其他平臺的介面卡可透過社群驅動的 Socialite Providers 網站獲取。

安裝

要開始使用 Socialite,請使用 Composer 包管理器將該包新增到專案的依賴項中

1composer require laravel/socialite

升級 Socialite

升級到 Socialite 的新主版本時,請務必仔細閱讀 升級指南

配置

在使用 Socialite 之前,您需要為您應用所使用的 OAuth 提供商新增憑據。通常,這些憑據可以透過在您要進行身份驗證的服務儀表板中建立“開發者應用”來獲取。

這些憑據應放置在您應用的 config/services.php 配置檔案中,並根據您的應用所需的提供商,使用 facebookxlinkedin-openidgooglegithubgitlabbitbucketslackslack-openid 作為鍵。

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。

認證

路由

要使用 OAuth 提供商驗證使用者身份,您需要兩條路由:一條用於將使用者重定向到 OAuth 提供商,另一條用於在身份驗證後接收來自提供商的回撥。下面的示例路由演示了這兩條路由的實現

1use Laravel\Socialite\Socialite;
2 
3Route::get('/auth/redirect', function () {
4 return Socialite::driver('github')->redirect();
5});
6 
7Route::get('/auth/callback', function () {
8 $user = Socialite::driver('github')->user();
9 
10 // $user->token
11});

Socialite 門面提供的 redirect 方法負責將使用者重定向到 OAuth 提供商,而 user 方法則會檢查傳入的請求,並在使用者批准身份驗證請求後從提供商處檢索使用者資訊。

身份驗證與儲存

從 OAuth 提供商獲取使用者資訊後,您可以確定該使用者是否存在於您的應用資料庫中並 對使用者進行身份驗證。如果該使用者不存在於您的資料庫中,您通常會在資料庫中建立一個新記錄來代表該使用者。

1use App\Models\User;
2use Illuminate\Support\Facades\Auth;
3use Laravel\Socialite\Socialite;
4 
5Route::get('/auth/callback', function () {
6 $githubUser = Socialite::driver('github')->user();
7 
8 $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 ]);
16 
17 Auth::login($user);
18 
19 return redirect('/dashboard');
20});

有關特定 OAuth 提供商可提供哪些使用者資訊的更多資訊,請參閱 獲取使用者詳細資訊 的文件。

訪問範圍 (Access Scopes)

在重定向使用者之前,您可以使用 scopes 方法來指定身份驗證請求中應包含的“作用域 (scopes)”。此方法會將之前指定的所有作用域與您當前指定的作用域合併。

1use Laravel\Socialite\Socialite;
2 
3return Socialite::driver('github')
4 ->scopes(['read:user', 'public_repo'])
5 ->redirect();

您可以使用 setScopes 方法覆蓋身份驗證請求上所有現有的作用域。

1return Socialite::driver('github')
2 ->setScopes(['read:user', 'public_repo'])
3 ->redirect();

Slack 機器人作用域

Slack 的 API 提供了 不同型別的訪問令牌,每種都有其對應的 許可權作用域。Socialite 相容以下兩種 Slack 訪問令牌型別:

  • Bot(字首為 xoxb-
  • User(字首為 xoxp-

預設情況下,slack 驅動程式將生成一個 user 令牌,呼叫驅動程式的 user 方法將返回使用者的詳細資訊。

如果您希望應用向由應用使用者擁有的外部 Slack 工作區傳送通知,Bot 令牌非常有用。要生成 Bot 令牌,請在將使用者重定向到 Slack 進行身份驗證之前呼叫 asBotUser 方法。

1return Socialite::driver('slack')
2 ->asBotUser()
3 ->setScopes(['chat:write', 'chat:write.public', 'chat:write.customize'])
4 ->redirect();

此外,在 Slack 將使用者重定向回您的應用進行身份驗證後,您必須在呼叫 user 方法之前呼叫 asBotUser 方法。

1$user = Socialite::driver('slack')->asBotUser()->user();

生成 Bot 令牌時,user 方法仍會返回 Laravel\Socialite\Two\User 例項;但是,只有 token 屬性會被填充。此令牌可以儲存起來,以便 向已驗證使用者的 Slack 工作區傳送通知

可選引數

許多 OAuth 提供商支援重定向請求中的其他可選引數。要在請求中包含任何可選引數,請使用關聯陣列呼叫 with 方法。

1use Laravel\Socialite\Socialite;
2 
3return Socialite::driver('google')
4 ->with(['hd' => 'example.com'])
5 ->redirect();

使用 with 方法時,請注意不要傳遞任何保留關鍵字,例如 stateresponse_type

獲取使用者詳細資訊

在使用者被重定向回您的應用身份驗證回撥路由後,您可以使用 Socialite 的 user 方法檢索使用者的詳細資訊。user 方法返回的使用者物件提供了多種屬性和方法,您可以使用它們將使用者資訊儲存在自己的資料庫中。

根據您進行身份驗證的 OAuth 提供商是否支援 OAuth 1.0 或 OAuth 2.0,此物件上可能提供不同的屬性和方法。

1use Laravel\Socialite\Socialite;
2 
3Route::get('/auth/callback', function () {
4 $user = Socialite::driver('github')->user();
5 
6 // OAuth 2.0 providers...
7 $token = $user->token;
8 $refreshToken = $user->refreshToken;
9 $expiresIn = $user->expiresIn;
10 
11 // OAuth 1.0 providers...
12 $token = $user->token;
13 $tokenSecret = $user->tokenSecret;
14 
15 // All providers...
16 $user->getId();
17 $user->getNickname();
18 $user->getName();
19 $user->getEmail();
20 $user->getAvatar();
21});

從令牌獲取使用者詳細資訊

如果您已經擁有使用者的有效訪問令牌,則可以使用 Socialite 的 userFromToken 方法獲取他們的使用者詳細資訊。

1use Laravel\Socialite\Socialite;
2 
3$user = Socialite::driver('github')->userFromToken($token);

如果您透過 iOS 應用使用 Facebook Limited Login,Facebook 將返回 OIDC 令牌而不是訪問令牌。與訪問令牌一樣,OIDC 令牌可以提供給 userFromToken 方法以獲取使用者詳細資訊。

無狀態身份驗證 (Stateless Authentication)

stateless 方法可用於停用會話狀態驗證。這在將社交登入功能新增到不使用基於 Cookie 會話的無狀態 API 時非常有用。

1use Laravel\Socialite\Socialite;
2 
3return Socialite::driver('google')->stateless()->user();

測試

Laravel Socialite 提供了一種便捷的方法來測試 OAuth 身份驗證流程,而無需向 OAuth 提供商發出實際請求。fake 方法允許您模擬 OAuth 提供商的行為並定義應返回的使用者資料。

模擬重定向

要測試您的應用是否正確地將使用者重定向到 OAuth 提供商,您可以在請求重定向路由之前呼叫 fake 方法。這將導致 Socialite 返回一個指向模擬授權 URL 的重定向,而不是重定向到實際的 OAuth 提供商。

1use Laravel\Socialite\Socialite;
2 
3test('user is redirected to github', function () {
4 Socialite::fake('github');
5 
6 $response = $this->get('/auth/github/redirect');
7 
8 $response->assertRedirect();
9});

模擬回撥

要測試應用的重定向回撥路由,您可以呼叫 fake 方法並提供一個 User 例項,該例項將在應用請求從提供商處獲取使用者詳細資訊時返回。User 例項可以使用 map 方法建立。

1use Laravel\Socialite\Socialite;
2use Laravel\Socialite\Two\User;
3 
4test('user can login with github', function () {
5 Socialite::fake('github', (new User)->map([
6 'id' => 'github-123',
7 'name' => 'Jason Beggs',
8 'email' => '[email protected]',
9 ]));
10 
11 $response = $this->get('/auth/github/callback');
12 
13 $response->assertRedirect('/dashboard');
14 
15 $this->assertDatabaseHas('users', [
16 'name' => 'Jason Beggs',
17 'email' => '[email protected]',
18 'github_id' => 'github-123',
19 ]);
20});

預設情況下,User 例項還將包含一個 token 屬性。如果需要,您可以手動在 User 例項上指定其他屬性。

1$fakeUser = (new User)->map([
2 'id' => 'github-123',
3 'name' => 'Jason Beggs',
4 'email' => '[email protected]',
5])->setToken('fake-token')
6 ->setRefreshToken('fake-refresh-token')
7 ->setExpiresIn(3600)
8 ->setApprovedScopes(['read', 'write'])