[JS] Google 第三方登入 API - GSI


Posted by vii120 on 2022-06-23

前言

最近想來試試網頁串 google 第三方登入的功能,發現官方文件上有一串敘述,簡單說只要目前串的是 Google Sign-in JavaScript libraryhttps://apis.google.com/js/platform.js )的話,就需要 migrate 到新的 library,目前的 library 在 2023/3/31 後就會淘汰,詳細可以參考這篇:Discontinuing Google Sign-In JavaScript Platform Library for web

在官方文件的選單裡已經分成兩種 web api,這篇主要會分享新版使用 Google 帳戶登入的 api(https://accounts.google.com/gsi/client

取得 client ID

使用 google 登入 api 需要先有一個 client ID:

  1. Google Cloud 新增一個專案(或用現有的專案)

  2. 選左邊的憑證 -> 建立憑證 -> OAuth 用戶端 ID

  3. 首次設定的話,會需要先設定 OAuth 同意畫面,點「設定同意畫面」按鈕 -> User Type 選擇外部,之後可以填寫必填欄位就好

  4. 設定好同意畫面後,預設的狀態會是「測試中」,只有「測試使用者」才有存取權限,所以要記得把自己的 mail 加進去

  5. 重新回到剛剛的「建立 OAuth 用戶端 ID」畫面,因為我想要用在網頁登入,所以選擇「網頁應用程式」

    我們會先在本機做測試,所以要把 localhost 或其他本地測試網址加到「已授權的 JavaScript 來源」,以 localhost 來說,要分別寫「 http://localhost 」和「 http://localhost:{port}

  6. 送出後就會拿到 client ID 了~

登入功能

首先在 html 內先引入 api script

<script src="https://accounts.google.com/gsi/client" async defer></script>

接著加入 google 登入按鈕 的程式碼,程式碼的部分可以選擇 html api 或 JS api ,以下使用 html api

<div
    id="g_id_onload"
    data-client_id="{YOUR_CLIENT_ID}"
    data-callback="handleCallback"
    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="pill"
    data-logo_alignment="left"
></div>

第一個 div #g_id_onload 主要是控制資料相關的屬性,參考 g_id_onload 參數

第二個 div .g_id_signin 是控制登入按鈕的顯示,參考 g_id_signin 參數

簡單介紹上面用到的幾個:data-client_id 是剛剛申請的 client ID;data-login_uridata-callback 二擇一使用,用來告訴 google 拿到憑證之後要做什麼,因為沒有後端的登入 endpoint,這邊先用 data-callback 來實作,我們寫一個 function handleCallback 來處理回傳的憑證,只要登入後有呼叫到這個 callback function 就表示成功登入了,印出憑證內容會得到 clientId, credentialselect_by

function handleCallback(response) {
    console.log(response);
}
// response
{
    "clientId": "726275...uie.apps.googleusercontent.com",
    "credential": "eyJhb...",
    "select_by": "btn"
}

其中 credential 是 base64 的 JWT Token,可以用解碼的方式拿到使用者資料,這邊用 stackoverflow 找到的 function 來執行

function parseJwt (token) {
   var base64Url = token.split('.')[1];
   var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
    return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
  }).join(''));

  return JSON.parse(jsonPayload);
};
function handleCallback(response) {
    const data = parseJwt(response.credential);
    console.log(data);
}

解碼後的資料如下:

// data
{
  "iss": "https://accounts.google.com", // The JWT's issuer
  "nbf":  161803398874,
  "aud": "314159265-pi.apps.googleusercontent.com", // Your server's client ID
  "sub": "3141592653589793238", // The unique ID of the user's Google Account
  "hd": "gmail.com", // If present, the host domain of the user's GSuite email address
  "email": "elisa.g.beckett@gmail.com", // The user's email address
  "email_verified": true, // true, if Google has verified the email address
  "azp": "314159265-pi.apps.googleusercontent.com",
  "name": "Elisa Beckett",
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/e2718281828459045235360uler",
  "given_name": "Eliza",
  "family_name": "Beckett",
  "iat": 1596474000, // Unix timestamp of the assertion's creation time
  "exp": 1596477600, // Unix timestamp of the assertion's expiration time
  "jti": "abc161803398874def"
}

這樣就完成基本的登入功能了~

如果要在正式環境使用,記得修改以下:

  • 到憑證裡「已授權的 JavaScript 來源」加入正式環境的 domain
  • 到 Oauth 同意畫面點「發布應用程式」,發布需要通過驗證,需要的內容可以參考官方所列

參考來源


#google #signin #gsi #API







Related Posts

淺層複製及深層複製

淺層複製及深層複製

Lidemy HTTP Challenge

Lidemy HTTP Challenge

我的第一堂 - 網路基礎概論

我的第一堂 - 網路基礎概論


Comments