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

概要

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

この取り組みは、Google の OAuth 2.0 認可エンドポイントとのやり取りにおけるフィッシング攻撃やアプリのなりすまし攻撃を防ぐための対策です。

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

ループバック IP アドレスのフローでは、ユーザーが OAuth 同意リクエストを承認した後、認証情報が送信されるリダイレクト URI のホスト コンポーネントとして、ループバック IP アドレスまたは localhost を使用できます。このフローは中間者攻撃に対して脆弱で、悪意のあるアプリが一部のオペレーティング システムの同じループバック インターフェースにアクセスすると、認可サーバーから指定されたリダイレクト 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 タイプを表示します。ウェブアプリAndroidiOSUniversal Windows Platform(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 認可エンドポイントへのすべての呼び出しが処理されます。

ループバック 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)、または Objective-C for REST 用 Google API クライアント ライブラリでフェッチャー承認ツール(GTMFetcherAuthorizationProtocol)を使用します。

クライアントサイドで 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 ガイドをご覧ください。