概要
2022 年 2 月 16 日、Google は、より安全な OAuth フローを使用して Google OAuth の操作をより安全にする計画を発表しました。このガイドでは、OAuth 帯域外(OOB)フローからサポートされている代替サービスに正常に移行するために必要な変更と手順について説明します。
これは Google の OAuth 2.0 認証エンドポイントとのインタラクションにおいて、フィッシングやアプリなりすましの攻撃を防ぐ手段です。
OOB とは
OAuth 帯域外(OOB)は手動コピー/貼り付けオプションとも呼ばれるレガシー フローで、ユーザーが OAuth 同意リクエストを承認した後に認証情報を受け取るリダイレクト URI を持たないネイティブ クライアントをサポートするために開発されました。OOB フローはリモート フィッシングのリスクをもたらし、クライアントはこの脆弱性から保護するために別の方法に移行する必要があります。OOB フローは、ウェブ アプリケーション、Android、iOS、ユニバーサル Windows プラットフォーム(UWP)、Chrome アプリ、テレビ、制限入力デバイス、デスクトップ アプリなど、すべての種類のクライアントで非推奨となっています。
主要なコンプライアンス日程
- 2022 年 2 月 28 日 - OOB フローにおける新しい OAuth の使用のブロック
- 2022 年 9 月 5 日 - 遵守していない OAuth リクエストに対して、ユーザー向けの警告メッセージが表示されることがあります。
- 2022 年 10 月 3 日 - 2022 年 2 月 28 日より前に作成された OAuth クライアントの OOB フローは非推奨になりました
- 2023 年 1 月 31 日 - 既存のすべてのクライアントがブロックされ、クライアントは除外されます。クライアントは、影響を受けたクライアントに送信されるメール メッセージの指示に従って、2023 年 1 月 31 日まで OOB フローを引き続き使用するよう 1 回限りの延長をリクエストできます。
1 か月前、つまり 2022 年 9 月 5 日に、OOB フローが完全に非推奨になると、ユーザー向けの警告メッセージが表示されることがあります。このメッセージは、Google API Console の OAuth 同意画面で登録したサポート メールが表示されている間、アプリがまもなくブロックされる可能性があることをユーザーに知らせます。
承認の呼び出しでクエリ パラメータを渡すことで、ユーザー向けの警告メッセージを確認し、抑制できます。次に例を示します。- アプリ内のコードに移動して、Google の OAuth 2.0 認証エンドポイントにリクエストを送信します。
-
適用日の値 2022-10-03 の
ack_oob_shutdown
パラメータをリダイレクト フロー リクエストに追加します。例:ack_oob_shutdown=2022-10-03
- 影響を受けているかどうかを確認します。
- 影響を受ける場合は、より安全な代替手段に移行してください。
影響を受けているかどうかの確認
このサポート終了は、本番環境用アプリ(公開ステータスが [本番環境] に設定されたアプリ)にのみ適用されます。フローは、公開ステータスのテストを行うアプリでも引き続き機能します。
Google API Console の OAuth Consent Screen pageで公開ステータスを確認します。公開ステータスが「本番環境」のプロジェクトで OOB フローを使用している場合は、次の手順に進みます。
アプリが OOB フローを使用しているかどうかを判断する方法
アプリのコードを調べるか、送信ネットワーク呼び出し(アプリが OAuth ライブラリを使用している場合)で、アプリが Google OAuth の承認リクエストで OOB リダイレクト URI 値を使用しているかどうかを確認します。
アプリケーション コードを調べる
redirect_uri
パラメータに次のいずれかの値があるかどうかを確認します。
redirect_uri=urn:ietf:wg:oauth:2.0:oob
redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
redirect_uri=oob
https://accounts.google.com/o/oauth2/v2/auth? response_type=code& scope=<SCOPES>& state=<STATE>& redirect_uri=urn:ietf:wg:oauth:2.0:oob& client_id=<CLIENT_ID>
発信ネットワーク通話を検査する
- ウェブ アプリケーション - Chrome でのネットワーク アクティビティを検査します
- Android - Network Inspector を使用してネットワーク トラフィックを検査します。
-
Chrome アプリ
- Chrome 拡張機能のページに移動します。
- 拡張機能ページの右上にある [デベロッパー モード] チェックボックスをオンにします。
- モニタリングする拡張機能を選択します
- 拡張機能ページの [ビューを検査] セクションで、[バックグラウンド ページ] リンクをクリックします。
- デベロッパー ツールのポップアップが開き、[ネットワーク] タブでネットワーク トラフィックをモニタリングできます。
- iOS - Instruments を使用して HTTP トラフィックを分析する
- Universal Windows Platform(UWP) - Visual Studio でネットワーク トラフィックを検査する
- デスクトップ アプリ - アプリが開発されているオペレーティング システムで利用可能なネットワーク キャプチャ ツールを使用します。
redirect_uri
パラメータに次のいずれかの値があるかどうかを確認します。
redirect_uri=urn:ietf:wg:oauth:2.0:oob
redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
redirect_uri=oob
https://accounts.google.com/o/oauth2/v2/auth? response_type=code& scope=<SCOPES>& state=<STATE>& redirect_uri=urn:ietf:wg:oauth:2.0:oob& client_id=<CLIENT_ID>
安全な代替システムへの移行
モバイル クライアント(Android / iOS)
Android または iOS の OAuth クライアント タイプで OOB フローを使用していると判断した場合は、Google ログイン モバイル SDK(Android、iOS)を使用するように移行する必要があります。
この SDK を利用すると、Google API へのアクセスが容易になり、Google の OAuth 2.0 認証エンドポイントへのすべての呼び出しを処理できます。
以下のドキュメントのリンクでは、Google ログイン SDK を使用して、OOB リダイレクト 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() }
アクセス トークンを使用して API を呼び出すには、REST または gRPC リクエストのヘッダーにアクセス トークンを含めるか(Authorization: Bearer ACCESS_TOKEN
)、フェッチャー認証者(GTMFetcherAuthorizationProtocol
)を Objective-C for REST 用の Google 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 アプリ クライアントで OOB フローを使用していると判断した場合は、Chrome Identity API を使用するように移行する必要があります。
次の例は、OOB リダイレクト 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 ガイドをご覧ください。
ウェブ アプリケーション
アプリがウェブ アプリケーションで OOB フローを使用していると判断した場合は、いずれかの Google API クライアント ライブラリを使用するように移行する必要があります。さまざまなプログラミング言語用のクライアント ライブラリについては、こちらをご覧ください。
このライブラリを使用すると、Google API へのアクセスや、Google エンドポイントへのすべての呼び出しを簡単に行うことができます。
サーバーサイド(オフライン)アクセス
- サーバーを起動し、一般公開されているエンドポイント(リダイレクト URI)を定義して、認証コードを受け取ります。
- Credentials page のリダイレクト URI を Credentials page
次のコード スニペットは、Google Drive API を使用して、OOB リダイレクト URI を使用せずにサーバー側でユーザーの Google ドライブ ファイルを一覧表示する NodeJS の例を示しています。
async function main() { const server = http.createServer(async function (req, res) { if (req.url.startsWith('/oauth2callback')) { let q = url.parse(req.url, true).query; if (q.error) { console.log('Error:' + q.error); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { // TODO(developer): Handle response / error. }); } } }
サーバー側から Google API にアクセスする方法については、サーバー側ウェブアプリ ガイドをご覧ください。
クライアントサイドのアクセス
次のコード スニペットは、JavaScript で、Google API を使用してクライアント側でユーザーのカレンダーの予定にアクセスする例を示しています。
// initTokenClient() initializes a new token client with your // web app's client ID and the scope you need access to const client = google.accounts.oauth2.initTokenClient({ client_id: 'YOUR_GOOGLE_CLIENT_ID', scope: 'https://www.googleapis.com/auth/calendar.readonly', // callback function to handle the token response callback: (tokenResponse) => { if (tokenResponse && tokenResponse.access_token) { gapi.client.setApiKey('YOUR_API_KEY'); gapi.client.load('calendar', 'v3', listUpcomingEvents); } }, }); function listUpcomingEvents() { gapi.client.calendar.events.list(...); }
クライアント側から Google API にアクセスする方法については、クライアント側ウェブアプリ ガイドをご覧ください。
デスクトップ クライアント
アプリがデスクトップ クライアントで OOB フローを使用していると判断した場合は、ループバック IP アドレス(localhost
または 127.0.0.1
)フローに移行する必要があります。