Guida alla migrazione del flusso fuori banda (OOB)

Panoramica

Il 16 febbraio 2022 abbiamo annunciato i piani per rendere più sicure le interazioni OAuth di Google utilizzando flussi OAuth più sicuri. Questa guida ti aiuta a comprendere le modifiche necessarie e i passaggi per eseguire la migrazione dal flusso OAuth out-of-band (OOB) alle alternative supportate.

Questo sforzo è una misura protettiva contro gli attacchi di phishing e impersonificazione di app durante le interazioni con gli endpoint di autorizzazione OAuth 2.0 di Google.

Che cos'è OOB?

OAuth out-of-band (OOB), detto anche opzione di copia/incolla manuale, è un flusso legacy sviluppato per supportare i client nativi che non hanno un URI di reindirizzamento per accettare le credenziali dopo che un utente approva una richiesta di consenso OAuth. Il flusso OOB comporta un rischio di phishing remoto e i client devono eseguire la migrazione a un metodo alternativo per proteggersi da questa vulnerabilità.

Il flusso OOB verrà ritirato per tutti i tipi di client, ovvero applicazioni web, Android, iOS, Universal Windows Platform (UWP), app di Chrome, TV e dispositivi con input limitato, app desktop.

Date chiave per la conformità

  • 28 febbraio 2022: nuovo utilizzo di OAuth bloccato per il flusso OOB
  • 5 settembre 2022: agli utenti potrebbe essere visualizzato un messaggio di avviso per le richieste OAuth non conformi
  • 3 ottobre 2022: il flusso OOB è ritirato per i client OAuth creati prima del 28 febbraio 2022
  • 31 gennaio 2023: tutti i client esistenti sono bloccati (inclusi i client esenti)

Per le richieste non conformi verrà visualizzato un messaggio di errore rivolto agli utenti. Il messaggio comunicherà agli utenti che l'app è bloccata e mostrerà l'email di assistenza che hai registrato nella schermata per il consenso OAuth nella console API di Google.

La procedura di migrazione si articola in due passaggi principali:
  1. Determinare se sei interessato.
  2. Se sei interessato, esegui la migrazione a un'alternativa più sicura.

Determinare se sei interessato

Il ritiro è applicabile solo alle app di produzione (ovvero le app con stato di pubblicazione impostato su In produzione. Il flusso continuerà a funzionare per le app con lo stato di pubblicazione dei test.

Controlla lo stato di pubblicazione in OAuth Branding page di Google Cloud Console e procedi al passaggio successivo se utilizzi il flusso OOB in un progetto con stato di pubblicazione "In produzione".

Come determinare se la tua app utilizza il flusso OOB

Ispeziona il codice dell'app o la chiamata di rete in uscita (nel caso in cui la tua app utilizzi una libreria OAuth) per determinare se la richiesta di autorizzazione OAuth di Google effettuata dalla tua app utilizza un valore URI di reindirizzamento OOB.

Ispezionare il codice dell'applicazione

Esamina la sezione del codice dell'applicazione in cui effettui chiamate agli endpoint di autorizzazione Google OAuth e determina se il parametro redirect_uri ha uno dei seguenti valori:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
Una richiesta di flusso di reindirizzamento OOB di esempio sarà simile alla seguente:
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>

Ispezionare la chiamata di rete in uscita

Il metodo per esaminare le chiamate di rete varia a seconda del tipo di client dell'applicazione.
Durante l'ispezione delle chiamate di rete, cerca le richieste inviate agli endpoint di autorizzazione di Google OAuth e determina se il parametro redirect_uri ha uno dei seguenti valori:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
Una richiesta di flusso di reindirizzamento OOB di esempio sarà simile alla seguente:
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>

Esegui la migrazione a un'alternativa sicura

Client mobile (Android / iOS)

Se determini che la tua app utilizza il flusso OOB con un tipo di client OAuth Android o iOS, devi eseguire la migrazione all'utilizzo degli SDK consigliati (Android, iOS).

L'SDK semplifica l'accesso alle API di Google e gestisce tutte le chiamate agli endpoint di autorizzazione OAuth 2.0 di Google.

I link alla documentazione riportati di seguito forniscono informazioni su come utilizzare gli SDK consigliati per accedere alle API di Google senza utilizzare un URI di reindirizzamento OOB.

Accedere alle API di Google su Android

Accesso lato client

L'esempio seguente mostra come accedere alle API di Google sul lato client su Android utilizzando la libreria Android dei servizi di identità Google consigliata.

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

Passa authorizationResult al metodo definito per salvare i contenuti nella cartella Drive dell'utente. authorizationResult ha il metodo getAccessToken() che restituisce il token di accesso.

Accesso lato server (offline)
L'esempio seguente mostra come accedere alle API di Google sul lato server su 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));

authorizationResult ha il metodo getServerAuthCode() che restituisce il codice di autorizzazione che puoi inviare al backend per ottenere un token di accesso e di aggiornamento.

Accedere alle API di Google in un'app per iOS

Accesso lato client

L'esempio seguente mostra come accedere alle API di Google lato client su 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()
}

Utilizza il token di accesso per chiamare l'API includendolo nell'intestazione di una richiesta REST o gRPC (Authorization: Bearer ACCESS_TOKEN) o utilizzando l'autorizzatore fetcher (GTMFetcherAuthorizationProtocol) con la libreria client delle API di Google per Objective-C per REST.

Consulta la guida all'accesso lato client per scoprire come accedere alle API di Google lato client. su come accedere alle API di Google lato client.

Accesso lato server (offline)
L'esempio seguente mostra come accedere alle API di Google lato server per supportare un client 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
}

Consulta la guida all'accesso lato server su come accedere alle API di Google dal lato server.

Client app di Chrome

Se determini che la tua app utilizza il flusso OOB sul client app Chrome, devi eseguire la migrazione all'utilizzo dell' API Chrome Identity.

L'esempio seguente mostra come ottenere tutti i contatti utente senza utilizzare un URI di reindirizzamento OOB.

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

Consulta la guida all'API Chrome Identity per saperne di più su come accedere agli utenti autenticati e chiamare gli endpoint Google con l'API Chrome Identity.

Applicazione web

Se determini che la tua app utilizza il flusso OOB per un'applicazione web, devi eseguire la migrazione a una delle nostre librerie client delle API di Google. Le librerie client per diversi linguaggi di programmazione sono elencate qui.

Le librerie semplificano l'accesso alle API di Google e la gestione di tutte le chiamate agli endpoint Google.

Accesso lato server (offline)
La modalità di accesso lato server (offline) richiede di eseguire le seguenti operazioni:
  • Configura un server e definisci un endpoint accessibile pubblicamente (l'URI di reindirizzamento) per ricevere il codice di autorizzazione.
  • Configura l' URI di reindirizzamento in Clients page di Google Cloud Console

Il seguente snippet di codice mostra un esempio di NodeJS di utilizzo dell'API Google Drive per elencare i file Google Drive di un utente sul lato server senza utilizzare un URI di reindirizzamento OOB.

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

Consulta la guida all'app web lato server su come accedere alle API di Google dal lato server.

Accesso lato client

Lo snippet di codice riportato di seguito, in JavaScript, mostra un esempio di utilizzo dell'API Google per accedere agli eventi di calendario dell'utente lato client.


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

Consulta la guida alle app web lato client su come accedere alle API di Google dal lato client.

Client desktop

Se determini che la tua app utilizza il flusso Fuori banda su un client desktop, devi eseguire la migrazione all'utilizzo del flusso dell'indirizzo IP di loopback (localhost o 127.0.0.1).