ループバック IP アドレスフローの移行ガイド

概要

2022 年 2 月 16 日、Google は、よりセキュアな OAuth フローを使用して Google OAuth インタラクションの安全性を強化する計画を 発表しました。このガイドでは、ループバック IP アドレスフローからサポートされている代替方法への移行を成功させるために必要な変更と手順について説明します。

この取り組みは、Google の OAuth 2.0 認可エンドポイントとのやり取りにおける、フィッシングやアプリのなりすまし攻撃から保護するための手段です。

ループバック IP アドレスのフローとは

ループバック IP アドレスフローでは、ループバック IP アドレスまたは localhost をリダイレクト URI のホスト コンポーネントとして使用できます。リダイレクト URI では、ユーザーが OAuth 同意リクエストを承認した後に、認証情報が送信されます。このフローは中間者攻撃に対して脆弱です。悪意のあるアプリが、一部のオペレーティング システムで同じループバック インターフェースにアクセスした場合、認証サーバーから特定のリダイレクト URI への応答をインターセプトして、認証コードにアクセスするおそれがあります。

ループバック IP アドレスフローは、iOS、Android、Chrome のネイティブ OAuth クライアント タイプではサポートが終了しますが、デスクトップ アプリでは引き続きサポートされます。

主なコンプライアンス日程

  • 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 Console の OAuth 同意画面で登録したサポート用メールアドレスを表示している間、アプリがブロックされていることをユーザーに伝えます。

移行プロセスを完了するには、主に次の 2 つの手順を行います。
  1. 影響を受けているかどうかを判断してください。
  2. 該当する場合は、サポートされている方法に移行してください。

影響の有無を判断する

OAuth クライアント ID のタイプを確認する

Google API Console の Credentials page に移動し、[OAuth 2.0 クライアント ID] セクションで OAuth クライアント ID のタイプを表示します。[ウェブ アプリケーション]、[Android]、[iOS]、[ユニバーサル Windows プラットフォーム(UWP)]、[Chrome アプリ]、[テレビと制限付きの入力デバイス]、[デスクトップ アプリ] のいずれかが表示されます。

クライアント タイプが Android、Chrome アプリ、iOS のいずれかで、ループバック IP アドレスフローを使用している場合は、次の手順に進みます。

デスクトップ アプリの OAuth クライアントでループバック IP アドレス フローを使用している場合は、このサポート終了に関連する操作は不要です。この OAuth クライアント タイプでも引き続きサポートされます。

アプリがループバック IP アドレスフローを使用しているかどうかを判断する方法

アプリコードまたは送信ネットワーク呼び出し(アプリが OAuth ライブラリを使用している場合)で、アプリが実行している Google 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 ログイン モバイル SDK(AndroidiOS)を使用するように移行する必要があります。

この SDK を使用すると、Google API に簡単にアクセスでき、Google の OAuth 2.0 認可エンドポイントへのすべての呼び出しが処理されます。

以下のドキュメント リンクでは、Google ログイン SDK を使用して、ループバック IP アドレスのリダイレクト URI を使用せずに 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()
}

REST または gRPC リクエストのヘッダーにアクセス トークンを含めるか、 Fetch API 用の Google API クライアント ライブラリでフェッチャー承認者(GTMFetcherAuthorizationProtocol)を使用して、アクセス トークンを使用して API を呼び出します。

クライアント側で Google API にアクセスする方法については、クライアント側アクセスガイドをご覧ください。クライアント側での Google API へのアクセス方法についてご確認ください。

サーバーサイド(オフライン)アクセス
以下の例は、iOS クライアントをサポートするためにサーバー側で Google API にアクセスする方法を示しています。
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 ガイドをご覧ください。