Out-Of-Band (OOB) flow Migration Guide

Stay organized with collections Save and categorize content based on your preferences.

Overview

On February 16 2022, we announced plans to make Google OAuth interactions safer by using more secure OAuth flows. This guide helps you to understand the necessary changes and steps to successfully migrate from the OAuth out-of-band (OOB) flow to supported alternatives.

This effort is a protective measure against phishing and app impersonation attacks during interactions with Google's OAuth 2.0 authorization endpoints.

What is OOB?

OAuth out-of-band (OOB), also referred to as the manual copy/paste option, is a legacy flow developed to support native clients which do not have a redirect URI to accept the credentials after a user approves an OAuth consent request. The OOB flow poses a remote phishing risk and clients must migrate to an alternative method to protect against this vulnerability.

The OOB flow is being deprecated for all client types i.e. Web applications, Android, iOS, Universal Windows Platform (UWP), Chrome apps, TVs & limited-input devices, Desktop apps.

Key compliance dates

  • February 28, 2022 - new OAuth usage blocked for the OOB flow
  • September 5, 2022 - a user-facing warning message may be displayed to non-compliant OAuth requests
  • October 3, 2022 - the OOB flow is deprecated for OAuth clients created before February 28, 2022

A user-facing warning message may be displayed for non-compliant requests one month before, i.e. September 5, 2022, the OOB flow is fully deprecated. The message will convey to the users that the app may be blocked soon while displaying the support email that you have registered in the OAuth consent screen in Google API Console.

You can acknowledge the user-facing warning message and suppress it by passing a query parameter in the authorization call as shown below:
  • Go to the code in your app where you send requests to Google's OAuth 2.0 Authorization Endpoint.
  • Add an ack_oob_shutdown parameter with a value of the enforcement date: 2022-10-03 to your redirect flow request. Example:
    ack_oob_shutdown=2022-10-03
There are two main steps to complete the migration process:
  1. Determine if you are affected.
  2. Migrate to a more secure alternative if you are affected.

Determine if you are affected

This deprecation is only applicable to production apps (i.e apps with publishing status set to In Production. The flow will continue to work for apps with the Testing publishing status.

Review your publishing status in the OAuth Consent Screen page of the Google API Console and proceed to the next step if you are using the OOB flow in a project with an "In Production" publishing status.

How to determine if your app is using the OOB flow

Inspect your app code or the outgoing network call (in case your app is using an OAuth library) to determine if the Google OAuth authorization request your app is making is using an OOB redirect URI value.

Inspect your application code

Review the section of your application code where you are making calls to the Google OAuth authorization endpoints and determine if the redirect_uri parameter has any of the following values:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
A sample OOB redirect flow request will look like the one below:
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>

Inspect outgoing network call

The method for inspecting network calls will vary depending on your application client type.
While inspecting network calls, look for requests sent to the Google OAuth authorization endpoints and determine if the redirect_uri parameter has any of the following values:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
A sample OOB redirect flow request will look like the one below:
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>

Migrate to a secure alternative

Mobile Clients (Android / iOS)

If you determine that your app is using the OOB flow with an Android or iOS OAuth client type, you should migrate to using our Google Sign-In mobile SDKs (Android, iOS).

The SDK makes it easy to access Google APIs and handles all the calls to Google's OAuth 2.0 authorization endpoints.

The documentation links below provides information on how to use the Google Sign-In SDKs to access Google APIs without using an OOB redirect URI.

Access Google APIs on Android

Server-Side (offline) access
The example below shows how to access Google APIs on the server side on Android.
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);
}

Review the server-side access guide on how to access Google APIs from the server side.

Access Google APIs in an iOS App

Client-side access

The example below shows how to access Google APIs on the client side on iOS.

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()
}

Use the access token to call the API, by either including the access token in the header of a REST or gRPC request (Authorization: Bearer ACCESS_TOKEN), or by using the fetcher authorizer (GTMFetcherAuthorizationProtocol) with the Google APIs client library for Objective-C for REST.

Review the client-side access guide on how to access Google APIs on the client side. on how to access Google APIs on the client side.

Server-side (offline) access
The example below shows how to access Google APIs on the server side to support an iOS client.
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
}

Review the server-side access guide on how to access Google APIs from the server side.

Chrome App Client

If you determine that your app is using the OOB flow on the Chrome app client, you should migrate to using the Chrome Identity API.

The example below shows how to get all user contacts without the use of an OOB redirect 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)
    });
   });
 });
};

Review the Chrome Identity API guide for more information on how to access authenticate users and call Google endpoints with the Chrome Identity API.

Web Application

If you determine that your app is using the OOB flow for a web application, you should migrate to using one of our Google API client libraries. Client libraries for different programming languages are listed here.

The libraries make it easy to access Google APIs and handle all the calls to the Google endpoints.

Server-side (offline) access
The server-side (offline) access mode requires you to do the following :
  • Stand up a server and define a publicly accessible endpoint (the redirect URI) to receive the authorization code.
  • Configure the redirect URI in the Credentials page of the Google API Console

The below code snippet shows a NodeJS example of using the Google Drive API to list a user's Google Drive files on the server-side without using an OOB redirect URI.

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.
      });
    }
  }
}

Review the server-side web app guide on how to access Google APIs from the server side.

Client-Side access

The below code snippet, in JavaScript, shows an example of using the Google API to access user's calendar events on the client side.


// 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(...);
}

Review the client-side web app guide on how to access Google APIs from the client side.

Desktop client

If you determine that your app is using the OOB flow on a desktop client, you should migrate to using the loopback IP address (localhost or 127.0.0.1) flow.