Loopback IP Address flow Migration Guide

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 loopback IP address 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 the Loopback IP Address flow?

The loopback IP address flow supports the use of a loopback IP address or localhost as the host component of the redirect URI where credentials are sent to after a user approves an OAuth consent request. This flow is vulnerable to man in the middle attacks where a nefarious app, accessing the same loopback interface on some operating systems, may intercept the response from the authorization server to the given redirect URI and gain access to the authorization code.

The loopback IP address flow is being deprecated for the native iOS, Android, and Chrome OAuth client types but will continue to be supported on desktop apps.

Key compliance dates

  • March 14, 2022- new OAuth clients blocked from using the Loopback IP address flow
  • August 1, 2022- a user-facing warning message may be displayed to non-compliant OAuth requests
  • August 31, 2022- the Loopback IP address flow is blocked for native Android, Chrome app, and iOS OAuth clients created before March 14, 2022
  • October 21, 2022- all existing clients are blocked (including exempted clients)

A user-facing error message will be displayed for non-compliant requests. The message will convey to users that the app is blocked while displaying the support email that you have registered in the OAuth consent screen in Google API Console .

There are two main steps to complete to get through the migration process:
  1. Determine if you are affected.
  2. Migrate to a supported alternative if you are affected.

Determine if you are affected

Review your OAuth client ID type

Navigate to the Clients page of the Google Cloud Console and view your OAuth client ID type under the OAuth 2.0 Client IDssection. It will be any one of the following: Web application , Android , iOS , Universal Windows Platform (UWP) , Chrome app , TVs & Limited Input devices , Desktop app .

Proceed to the next step if your client type is Android, Chrome app, or iOS and you are using the loopback IP address flow.

You do not need to do anything related to this deprecation if you are using the loopback IP address flow on a Desktop app OAuth client as usage with that OAuth client type will continue to be supported.

How to determine if your app is using the loopback IP address 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 loopback redirect URI values.

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=http://127.0.0.1: <port> e.g. redirect_uri=http://127.0.0.1: 3000
  • redirect_uri=http://[::1]: <port> e.g. redirect_uri=http://[::1]: 3000
  • redirect_uri=http://localhost: <port> e.g. redirect_uri=http://localhost: 3000
A sample loopback IP address redirect flow request will look like the one below:
https://accounts.google.com/o/oauth2/v2/auth? redirect_uri=http://localhost: 3000 
&response_type=code&
scope= <SCOPES> 
&
state= <STATE> 
&
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=http://127.0.0.1: <port> e.g. redirect_uri=http://127.0.0.1: 3000
  • redirect_uri=http://[::1]: <port> e.g. redirect_uri=http://[::1]: 3000
  • redirect_uri=http://localhost: <port> e.g. redirect_uri=http://localhost: 3000
A sample loopback IP address redirect flow request will look like the one below:
https://accounts.google.com/o/oauth2/v2/auth? redirect_uri=http://localhost: 3000 
&response_type=code&
scope= <SCOPES> 
&
state= <STATE> 
&
client_id= <CLIENT_ID> 

Migrate to a supported alternative

Mobile Clients (Android / iOS)

If you determine that your app is using the loopback IP address flow with an Android or iOS OAuth client type, you should migrate to using the recommended 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 recommended SDKs to access Google APIs without using a loopback IP address redirect URI.

Access Google APIs on Android

Client-side access

The following example shows how to access Google APIs on the client side on Android using the recommended Google Identity Services Android Library.

  
 List 
   
 requestedScopes 
  
 = 
  
 Arrays 
 . 
 asList 
 ( 
 DriveScopes 
 . 
 DRIVE_APPDATA 
 ); 
  
 AuthorizationRequest 
  
 authorizationRequest 
  
 = 
  
 AuthorizationRequest 
 . 
 builder 
 (). 
 setRequestedScopes 
 ( 
 requestedScopes 
 ). 
 build 
 (); 
  
 Identity 
 . 
 getAuthorizationClient 
 ( 
 activity 
 ) 
  
 . 
 authorize 
 ( 
 authorizationRequest 
 ) 
  
 . 
 addOnSuccessListener 
 ( 
  
 authorizationResult 
  
 -> 
  
 { 
  
 if 
  
 ( 
 authorizationResult 
 . 
 hasResolution 
 ()) 
  
 { 
  
 // Access needs to be granted by the user 
  
 PendingIntent 
  
 pendingIntent 
  
 = 
  
 authorizationResult 
 . 
 getPendingIntent 
 (); 
  
 try 
  
 { 
  
 startIntentSenderForResult 
 ( 
 pendingIntent 
 . 
 getIntentSender 
 (), 
  
 REQUEST_AUTHORIZE 
 , 
  
 null 
 , 
  
 0 
 , 
  
 0 
 , 
  
 0 
 , 
  
 null 
 ); 
  
 } 
  
 catch 
  
 ( 
 IntentSender 
 . 
 SendIntentException 
  
 e 
 ) 
  
 { 
  
 Log 
 . 
 e 
 ( 
 TAG 
 , 
  
 "Couldn't start Authorization UI: " 
  
 + 
  
 e 
 . 
 getLocalizedMessage 
 ()); 
  
 } 
  
 } 
  
 else 
  
 { 
  
 // Access already granted, continue with user action 
  
 saveToDriveAppFolder 
 ( 
 authorizationResult 
 ); 
  
 } 
  
 }) 
  
 . 
 addOnFailureListener 
 ( 
 e 
  
 -> 
  
 Log 
 . 
 e 
 ( 
 TAG 
 , 
  
 "Failed to authorize" 
 , 
  
 e 
 )); 
 

Pass the authorizationResult to your defined method to save content to the user's drive folder. The authorizationResult has the getAccessToken() method that returns the access token.

Server-Side (offline) access
The following example shows how to access Google APIs on the server side on Android.
  
 List 
   
 requestedScopes 
  
 = 
  
 Arrays 
 . 
 asList 
 ( 
 DriveScopes 
 . 
 DRIVE_APPDATA 
 ); 
  
 AuthorizationRequest 
  
 authorizationRequest 
  
 = 
  
 AuthorizationRequest 
 . 
 builder 
 () 
  
  . 
 requestOfflineAccess 
 ( 
 webClientId 
 ) 
  
 . 
 setRequestedScopes 
 ( 
 requestedScopes 
 ) 
  
 . 
 build 
 (); 
  
 Identity 
 . 
 getAuthorizationClient 
 ( 
 activity 
 ) 
  
 . 
 authorize 
 ( 
 authorizationRequest 
 ) 
  
 . 
 addOnSuccessListener 
 ( 
  
 authorizationResult 
  
 -> 
  
 { 
  
 if 
  
 ( 
 authorizationResult 
 . 
 hasResolution 
 ()) 
  
 { 
  
 // Access needs to be granted by the user 
  
 PendingIntent 
  
 pendingIntent 
  
 = 
  
 authorizationResult 
 . 
 getPendingIntent 
 (); 
  
 try 
  
 { 
  
 startIntentSenderForResult 
 ( 
 pendingIntent 
 . 
 getIntentSender 
 (), 
  
 REQUEST_AUTHORIZE 
 , 
  
 null 
 , 
  
 0 
 , 
  
 0 
 , 
  
 0 
 , 
  
 null 
 ); 
  
 } 
  
 catch 
  
 ( 
 IntentSender 
 . 
 SendIntentException 
  
 e 
 ) 
  
 { 
  
 Log 
 . 
 e 
 ( 
 TAG 
 , 
  
 "Couldn't start Authorization UI: " 
  
 + 
  
 e 
 . 
 getLocalizedMessage 
 ()); 
  
 } 
  
 } 
  
 else 
  
 { 
  
  String 
  
 authCode 
  
 = 
  
 authorizationResult 
 . 
 getServerAuthCode 
 (); 
  
 } 
  
 }) 
  
 . 
 addOnFailureListener 
 ( 
 e 
  
 -> 
  
 Log 
 . 
 e 
 ( 
 TAG 
 , 
  
 "Failed to authorize" 
 , 
  
 e 
 )); 
 

The authorizationResult has the getServerAuthCode() method that returns the authorization code which you can send to your backend to obtain an access and refresh token.

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 loopback IP address 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 a loopback IP address 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.

Design a Mobile Site
View Site in Mobile | Classic
Share by: