網頁使用第三方登入服務-Google

寫在前面

  • Oauth 2.0 流程

    1. 客戶端提供其自身的信息,在資源所有者的允許下,向認證服務請求 Access Token。
    2. 認證服務驗證通過後,返回 Access Token 給客戶端。
    3. 客戶端使用 Access Token 向資源服務請求用戶數據。
    4. 資源服務驗證 Access Token 有效後,返回資源數據。
  • 角色
    客戶端 – 網頁/ App
    資源所有者 – 使用者
    認證服務 – 總管授權事務
    資源服務 – 提供訪問資源的api

參考-簡單易懂的 OAuth 2.0

摩登 OAuth 2.0:簡介

使用套件

google-api-php-client

1
composer require google/apiclient

註冊應用程式

截圖中的資訊為其他地方使用的範例,下方程式碼是後來重新整理出來的紀錄,兩者間會稍微有點出入,但原則上方向是一樣的。
以下開始:

由此申請

  • 開新專案
    開新專案
    設定專案名稱

  • 建立憑證



    *同意後選擇外部使用

  • 基本資訊

  • 建立OAuth ID
    我們這邊選擇網頁應用程式

  • 設定重新導向url
    設定重新導向url

  • 取得ID & 密碼
    ID & 密碼

  • 設定PHP認證

程式碼參考

方案一

由後端取得連結回傳給前端,前端提供入口供使用者點選進行授權認證。

  • 取得google 登入導向連結

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?php //>

    // 前一步驟下載下來的json檔
    $google_oauth_config = 'path/to/client_credentials.json';
    $state = $this->random_string(); // 可存在session 中,callback 的時候取出來比對是否相同,此function 回傳隨機字串

    $client = new Google_Client();

    // 取得用戶資訊(用戶在收到是否同意授權的時候會列出來)
    $client->addScope(Oauth2::USERINFO_EMAIL); // 要use Oauth2
    $client->addScope(Oauth2::USERINFO_PROFILE);

    $client->setAuthConfig($google_oauth_config);

    //設定 callback 網址,需和前面註冊的已授權的重新導向URI 相同
    $client->setRedirectUri('https://abc.com/member/google-login');

    $client->setState($state); // callback 時會同時帶回來讓我們比對

    // 取得連結網址回傳到前端,將此連結bind在google 登入的按鈕上
    $url = $client->createAuthUrl();

    return [
    'success' => true,
    'url' => $url
    ];
  • callback取得使用者資訊
    當使用者依照上一步驟的連結完成google 登入,授權給我們使用他的google 資料,
    我們會得到google 回傳的 code,再透過此code 向google 取得access token,以利取得使用者資訊。

* 此處method為GET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php //>

$google_oauth_config = 'path/to/client_credentials.json';

$client = new Google_Client();
$client->setAuthConfig($google_oauth_config);
$client->setRedirectUri(get_url(APP_ROOT . substr($this->path(), 1))); //如果沒有set 會一直回傳redirect_uri_mismatch 的錯誤


// 利用google 回傳的code 驗證使用者
$client->authenticate($_GET['code']);
$access_token = $client->getAccessToken();
if (!$access_token) {
echo ('error: login-failed');
}

// 透過Oauth service 取得 profile & email
$service = new Google_Service_Oauth2($client);

$userData = $service->userinfo->get();

// 將userData 印出來,視各專案需求使用
echo '<pre>';
print_r($userData);
  • 2023 更新
    此處有一個雷點,如果沒有設定redirectUri,會一直顯示錯誤,但不清楚為什麼這邊會需要設定跳轉網址,若有大師可以分享,歡迎來信。

方案二

前端引用google sdk(html api / js api),產生登入按鈕:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!doctype html>
<html>
<body>
<div id="g_id_onload"
data-client_id="{{ your_client_id }}"
data-login_uri="{{ redirect_url }}"
data-auto_prompt="false">
</div>
<div class="g_id_signin"
data-type="standard"
data-size="large"
data-theme="outline"
data-text="sign_in_with"
data-shape="rectangular"
data-logo_alignment="left">
</div>
<script src="https://accounts.google.com/gsi/client" async defer></script>
</body>
</html>
  • callback
    * 此處method 為POST
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php //>
    $google_oauth_config = 'path/to/client_credentials.json';

    $client = new Google_Client();
    $client->setAuthConfig($google_oauth_config);

    //將google 導過來的credential 驗證並取得資訊
    $userData = $client->verifyIdToken(_POST['credential']);

    // 將userData 印出來,視各專案需求使用
    echo '<pre>';
    print_r($userData);

這篇先記錄使用Google 作為第三方登入的筆記,後面還會有Line 及 Facebook 的部分。