回送 IP 位址流程遷移指南

總覽

我們在 2022 年 2 月 16 日 宣布計劃採用更安全的 OAuth 流程,藉此提高 Google OAuth 互動的安全性。本指南會說明必要變更及步驟,協助您順利從回送 IP 位址流程遷移至支援的替代服務。

我們希望藉由這項措施,在與 Google 的 OAuth 2.0 授權端點互動期間,防範網路釣魚和應用程式冒用攻擊。

什麼是回送 IP 位址流程?

回送 IP 位址流程支援使用回送 IP 位址或 localhost 做為重新導向 URI 的主機元件,在使用者核准 OAuth 同意要求後,憑證會傳送到目的地。如果應用程式出現中間人的惡意應用程式,在部分作業系統上存取相同的回送介面,可能會攔截來自授權伺服器對指定重新導向 URI 的回應,並藉此取得授權碼,這種攻擊很容易。

我們即將淘汰原生 iOS、Android 和 Chrome OAuth 用戶端類型的回送 IP 位址流程,但日後電腦版應用程式將繼續支援這個流程。

主要法規遵循日期

  • 2022 年 3 月 14 日 - 禁止新的 OAuth 用戶端使用回送 IP 位址流程
  • 2022 年 8 月 1 日 - 不符規定的 OAuth 要求可能會顯示向使用者顯示的警告訊息
  • 2022 年 8 月 31 日 - 針對 2022 年 3 月 14 日前建立的原生 Android、Chrome 應用程式和 iOS OAuth 用戶端,迴圈 IP 位址流程已遭到封鎖
  • 2022 年 10 月 21 日 - 所有現有用戶端 (包括豁免的用戶端) 都會遭到封鎖

不符規定的要求,系統會向使用者顯示錯誤訊息。這則訊息會向使用者說明應用程式遭到封鎖,並顯示您在 Google API 控制台中的 OAuth 同意畫面中註冊的支援電子郵件。

請完成遷移程序的兩個主要步驟:
  1. 判斷您是否受到影響。
  2. 如果受到影響,請改用支援的替代方案。

判斷您是否受到影響

查看您的 OAuth 用戶端 ID 類型

前往 Google API Console 的 Credentials page ,並在「OAuth 2.0 用戶端 ID」部分下方查看您的 OAuth 用戶端 ID 類型。可以是下列任一項目:網頁應用程式AndroidiOS通用 Windows 平台 (UWP)Chrome 應用程式電視與受限輸入裝置電腦版應用程式

如果您的用戶端類型是 Android、Chrome 應用程式或 iOS,且您正在使用回送 IP 位址流程,請繼續進行下一個步驟。

如果您在電腦版應用程式 OAuth 用戶端上使用回送 IP 位址流程,則系統將繼續支援使用該 OAuth 用戶端類型的情況,因此您無須採取任何行動。

如何判斷應用程式是否使用回送 IP 位址流程

檢查應用程式程式碼傳出網路呼叫 (如果應用程式使用 OAuth 程式庫),判斷應用程式是否使用回送重新導向 URI 值。

檢查應用程式程式碼

查看應用程式程式碼的相關部分,其中會呼叫 Google OAuth 授權端點,並判斷 redirect_uri 參數是否具有下列任一值:
  • redirect_uri=http://127.0.0.1:<port> 例如 redirect_uri=http://127.0.0.1:3000
  • redirect_uri=http://[::1]:<port> 例如 redirect_uri=http://[::1]:3000
  • redirect_uri=http://localhost:<port> 例如 redirect_uri=http://localhost:3000
回送 IP 位址重新導向流程要求的範例如下所示:
https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri=http://localhost:3000&
response_type=code&
scope=<SCOPES>&
state=<STATE>&
client_id=<CLIENT_ID>

檢查撥出網路通話

檢查網路呼叫的方法會因應用程式用戶端類型而異。
檢查網路呼叫時,請找出傳送至 Google OAuth 授權端點的要求,並判斷 redirect_uri 參數是否具有下列任一值:
  • redirect_uri=http://127.0.0.1:<port> 例如 redirect_uri=http://127.0.0.1:3000
  • redirect_uri=http://[::1]:<port> 例如 redirect_uri=http://[::1]:3000
  • redirect_uri=http://localhost:<port> 例如 redirect_uri=http://localhost:3000
繞回 IP 位址重新導向流程要求的範例如下所示:
https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri=http://localhost:3000&
response_type=code&
scope=<SCOPES>&
state=<STATE>&
client_id=<CLIENT_ID>

改用支援的替代方案

行動裝置用戶端 (Android / iOS)

如果您確定應用程式使用的是 Android 或 iOS OAuth 用戶端類型的回送 IP 位址流程,則應改用 Google 登入 Mobile SDK (AndroidiOS)。

這個 SDK 可讓您輕鬆存取 Google API,並處理對 Google OAuth 2.0 授權端點的所有呼叫。

透過下方的說明文件連結,即可瞭解如何在不使用回送 IP 位址重新導向 URI 的情況下,透過 Google 登入 SDK 存取 Google API。

在 Android 上存取 Google API

伺服器端 (離線) 存取
以下範例說明如何在 Android 伺服器端存取 Google API
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
  GoogleSignInAccount account = task.getResult(ApiException.class);
  
  // request a one-time authorization code that your server exchanges for an
  // access token and sometimes refresh token
  String authCode = account.getServerAuthCode();
  
  // Show signed-in UI
  updateUI(account);

  // TODO(developer): send code to server and exchange for access/refresh/ID tokens
} catch (ApiException e) {
  Log.w(TAG, "Sign-in failed", e);
  updateUI(null);
}

請參閱伺服器端存取權指南,瞭解如何從伺服器端存取 Google API。

在 iOS 應用程式中存取 Google API

用戶端存取權

以下範例說明如何在 iOS 用戶端存取 Google API

user.authentication.do { authentication, error in
  guard error == nil else { return }
  guard let authentication = authentication else { return }
  
  // Get the access token to attach it to a REST or gRPC request.
  let accessToken = authentication.accessToken
  
  // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
  // use with GTMAppAuth and the Google APIs client library.
  let authorizer = authentication.fetcherAuthorizer()
}

要使用存取權杖呼叫 API,可以使用 REST 或 gRPC 要求標頭 (Authorization: Bearer ACCESS_TOKEN) 加入存取權杖,也可以使用擷取工具授權器 (GTMFetcherAuthorizationProtocol) 搭配 REST-C 適用的 Google API 用戶端程式庫

請參閱用戶端存取權指南,瞭解如何在用戶端存取 Google API。瞭解如何在用戶端存取 Google API。

伺服器端 (離線) 存取
以下範例說明如何在伺服器端存取 Google API,以便支援 iOS 用戶端。
GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
  guard error == nil else { return }
  guard let user = user else { return }
  
  // request a one-time authorization code that your server exchanges for
  // an access token and refresh token
  let authCode = user.serverAuthCode
}

請參閱伺服器端存取權指南,瞭解如何從伺服器端存取 Google API。

Chrome 應用程式用戶端

如果您確定自己的應用程式使用 Chrome 應用程式用戶端的回送 IP 位址流程,則應改用 Chrome Identity API

以下範例說明如何在不使用回送 IP 位址重新導向 URI 的情況下取得所有使用者聯絡人。

window.onload = function() {
  document.querySelector('button').addEventListener('click', function() {

  
  // retrieve access token
  chrome.identity.getAuthToken({interactive: true}, function(token) {
  
  // ..........


  // the example below shows how to use a retrieved access token with an appropriate scope
  // to call the Google People API contactGroups.get endpoint

  fetch(
    'https://people.googleapis.com/v1/contactGroups/all?maxMembers=20&key=API_KEY',
    init)
    .then((response) => response.json())
    .then(function(data) {
      console.log(data)
    });
   });
 });
};

如要進一步瞭解如何存取驗證使用者身分,以及如何使用 Chrome Identity API 呼叫 Google 端點,請參閱 Chrome Identity API 指南