今天要完成的是 Google 登入。
在開始實作之前,先了解整個 Google Login 的流程,以及 Google Cloud Console 中 Web、Android、iOS 三種 OAuth Client 分別扮演什麼角色。
Google 登入流程如下:
[ React Native APP ]
│
▼
Google Login
│
▼
Google 回傳 idToken
│
▼
後端驗證 idToken
│
▼
建立 / 更新 User
│
▼
發放 Access Token、Refresh Token
│
▼
後續 API 都使用自己的 Token
Google 登入成功後,Google 並不會直接替你的系統完成登入,而是回傳一組 idToken,用來證明使用者已經通過 Google 身份驗證。
前端收到 idToken 後,再交由後端驗證是否合法,以及是否確實簽發給自己的應用程式。驗證成功後,後端才會建立使用者資料,並發放自己的 Access Token 與 Refresh Token。
不過在開始實作之前,還需要先讓 Google 知道是哪一個應用程式要使用這個登入功能。
畢竟任何人都可以開發 App,如果沒有事先註冊,Google 就無法判斷目前發起登入請求的是不是你的應用程式。
因此第一步,就是到 Google Cloud Console 建立 OAuth Client。
建立 OAuth Client 時,可以看到很多不同的平台類型,不過 React Native 專案主要會用到下面三種:
| OAuth Client | 用途 |
|---|---|
| Web | React Native 初始化 Google Sign-In、後端驗證 idToken |
| Android | 驗證 Android App 的 Package Name 與 SHA-1 |
| iOS | 驗證 iOS App 的 Bundle ID,並處理登入完成後返回 App |
雖然會建立三種 OAuth Client,但實際上 React Native 程式中真正需要設定的只有 Web Client ID。
Android 與 iOS Client 則是提供 Google 驗證目前發起登入請求的 App 是否就是你註冊的應用程式,因此不需要在 App 另外指定。
接下來,就分別介紹三種 OAuth Client 的用途,以及建立時需要注意的設定。
第一次實作 Google 登入時,我很好奇 React Native 明明是 Android 和 iOS App,為什麼還要建立一個 Web OAuth Client?
後來才發現它們的用途其實不同。
Android 與 iOS Client 用來識別 App 身份,讓 Google 確認目前發起登入請求的,就是你註冊的應用程式;而真正負責 Google Login 流程的,則是 Web Client。
Google 登入成功後,會根據這組 Web Client ID 簽發 idToken。後端收到 idToken 後,也會確認它是否確實簽發給自己的 Web Client,因此前端初始化 Google Sign-In,以及後端驗證 idToken,都會使用同一組 Web Client ID。
這個 Project 我使用 @react-native-google-signin/google-signin 套件還進行 Google 登入:
import { GoogleSignin } from '@react-native-google-signin/google-signin';
GoogleSignin.configure({
webClientId: '123456789012-webidexample.apps.googleusercontent.com',
offlineAccess: true,
});
建立 Web OAuth Client 時,主要會看到兩個設定:
這個欄位用來限制哪些網站可以發起 OAuth 登入,因此只有 Web 應用才會使用。
React Native 登入流程透過原生 Google Sign-In SDK 完成,因此可以直接留空。
這個欄位用來設定 OAuth Flow 完成後,要將使用者重新導向到哪一個網址。
本文使用的是 React Native 原生 Google Sign-In,不會使用到 OAuth Redirect Flow,因此建立 Web OAuth Client 時也不需要填寫。
如果之後有實作 Web 版登入,或採用需要 Redirect 的 OAuth 流程,再依照實際需求新增即可。
Android OAuth Client 的用途是讓 Google 驗證目前發起登入請求的 Android App,是否就是你在 Google Cloud Console 註冊的應用程式。
Google 主要會檢查兩個資訊:
只有兩者都符合時,Google 才會允許這個 App 發起 Google 登入。

Package Name 是 Android App 的唯一識別名稱,在 Android 專案中通常就是 defaultConfig 內的 applicationId:
defaultConfig {
applicationId "com.tracewalk"
}
將這個值填入 Google Cloud Console 即可。
除了 Package Name,Google 還會透過 App 的簽章確認目前發起登入請求的 APK 是否就是你註冊的應用程式,因此還需要提供 SHA-1 憑證指紋。
開發階段可以直接使用 Debug Keystore,執行:
keytool -list -v \
-alias androiddebugkey \
-keystore ~/.android/debug.keystore \
-storepass android \
-keypass android
執行後會看到:
SHA1: 2A:3B:4C:5D:...
將這串 SHA-1 加入 Google Cloud Console 即可。
開發時通常只需要加入 Debug SHA-1,就能正常登入;如果之後發布到 Google Play,或更換了簽章憑證,也記得將新的 SHA-1 一併加入 Google Cloud Console,否則 Google 登入可能會失敗。
這邊就不詳細說明了,可以參考我之前整理的文章:
iOS OAuth Client 與 Android 一樣,都是用來驗證 App 身份。
不同的是,iOS 不使用 SHA-1,而是透過 Bundle ID 與 URL Scheme 完成設定。

Bundle ID 是 iOS App 的唯一識別名稱,需要和 Xcode 專案中的 Bundle Identifier 保持一致。

Google 登入時使用者會暫時離開 App,跳到 Google App 或 Safari 完成身份驗證。
登入完成後,需要重新回到原本的 App,因此 iOS 必須註冊一個 URL Scheme,讓 Google 能夠重新開啟你的 App,並將登入結果交回 Google Sign-In SDK。
建立 iOS OAuth Client 時,Google 會自動產生一組 Reversed Client ID。
例如:
Client ID
1234567890-abcdef.apps.googleusercontent.com
對應的 Reversed Client ID:
com.googleusercontent.apps.1234567890-abcdef
接著在 Xcode,或 React Native 的 ios/Info.plist 中加入 CFBundleURLSchemes:
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.xxxxxxxxxxxxx-xxxxxxxxx</string>
</array>
</dict>
</array>
設定完成後,Google 登入成功時,就會透過這個 URL Scheme 重新開啟 App,並將登入結果交回 Google Sign-In SDK。
Google Login 雖然只是一個登入功能,但實際上需要三種不同的 OAuth Client 互相配合,理解了登入流程與這三種 OAuth Client 的分工後,接下來就可以開始實作 React Native 的 Google 登入功能。
不過 Google 登入的部分今天已經結束,明天開始要建立後端開發環境了。