Guida alla migrazione del flusso fuori banda (OOB)

Panoramica

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

Questo impegno è una misura di protezione contro gli attacchi di phishing e di furto d'identità delle app durante le interazioni con gli endpoint di autorizzazione OAuth 2.0 di Google.

Che cos'è l'OOB?

OAuth out-of-band (OOB), noto anche come opzione di copia e incolla manuale, è un flusso legacy sviluppato per supportare i client installati che non dispongono di 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 è in fase di ritiro per tutti i tipi di applicazioni, ovvero applicazioni web, Android, iOS, Universal Windows Platform (UWP), app di Chrome, TV e dispositivi di input limitato, app desktop.

Date chiave per la conformità

  • 28 febbraio 2022: blocco del nuovo utilizzo di OAuth per il flusso OOB
  • 5 settembre 2022: potrebbe essere visualizzato un messaggio di avviso rivolto agli utenti per le richieste OAuth non conformi
  • 3 ottobre 2022: il flusso OOB è stato ritirato per i client OAuth creati prima del 28 febbraio 2022
  • 31 gennaio 2023: tutti i client esistenti vengono 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 Google Cloud.

Per completare la procedura di migrazione, devi seguire due passaggi principali:

  1. Determina se il problema ti riguarda.
  2. Se l'impatto ti riguarda, esegui la migrazione a un'alternativa più sicura.

Determina se il problema ti riguarda

Questo ritiro è applicabile solo alle app di produzione (ovvero alle app con stato di pubblicazione impostato su In produzione). Il flusso continuerà a funzionare per le app con lo stato di pubblicazione Test in corso.

Controlla lo stato di pubblicazione nella pagina Branding OAuth della console Google Cloud e vai al passaggio successivo se utilizzi il flusso OOB in un progetto con lo 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 l'app utilizzi una libreria OAuth) per determinare se la richiesta di autorizzazione Google OAuth effettuata dall'app utilizza un valore URI di reindirizzamento OOB.

Esamina il codice dell'applicazione

Esamina la sezione del codice dell'applicazione in cui effettui chiamate 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

Di seguito è riportato un esempio di richiesta di flusso di reindirizzamento 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>

Ispeziona la chiamata di rete in uscita

Il metodo per ispezionare le chiamate di rete varia a seconda del tipo di applicazione.

Durante l'ispezione delle chiamate di rete, cerca le richieste inviate agli endpoint di autorizzazione OAuth di Google 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

Di seguito è riportato un esempio di richiesta di flusso di reindirizzamento 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>

Esegui la migrazione a un'alternativa sicura

Client mobile (Android e iOS)

Se stabilisci che la tua app utilizza il flusso OOB con un tipo di applicazione OAuth Android o iOS, devi eseguire la migrazione per utilizzare gli SDK consigliati (Android, iOS).

L'SDK ti aiuta ad accedere alle API di Google e gestisce tutte le chiamate agli endpoint di autorizzazione OAuth 2.0 di Google.

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

Accedi alle API di Google su Android

Accesso lato client

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

List<Scopes> 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 l'oggetto 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)

Il seguente esempio mostra come accedere alle API di Google lato server su Android.

List<Scopes> 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 tuo backend per ottenere un token di accesso e un token di aggiornamento.

Accedi alle API di Google in un'app per iOS

Accesso lato client

L'esempio seguente mostra come accedere alle API di Google sul 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 <var>ACCESS_TOKEN</var>) o utilizzando l'autorizzatore del recuperatore (GTMFetcherAuthorizationProtocol) con la libreria client delle API di Google per Objective-C per REST.

Consulta la guida all'accesso 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 sul 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 stabilisci che la tua app utilizza il flusso OOB sul client dell'app di Chrome, devi eseguire la migrazione all'utilizzo dell'API Chrome Identity.

L'esempio seguente mostra come ottenere tutti i contatti utente senza l'utilizzo di 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 following example 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)
    });
   });
 });
};

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

Applicazione web

Se stabilisci che la tua app utilizza il flusso OOB per un'applicazione web, devi eseguire la migrazione per utilizzare una delle nostre librerie client dell'API di Google. Consulta l'elenco delle librerie client delle API di Google per i diversi linguaggi di programmazione.

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

Accesso lato server (offline)

La modalità di accesso lato server (offline) richiede di eseguire questi passaggi :

  • Configura un server e definisci un endpoint accessibile pubblicamente (l'URI di reindirizzamento) per ricevere il codice di autorizzazione.
  • Configura l'URI di reindirizzamento nella pagina Client della console Google Cloud.

Il seguente snippet di codice mostra un esempio di NodeJS che utilizza l'API Google Drive per elencare i file di 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 alle app web lato server su come accedere alle API di Google dal lato server.

Accesso lato client

Il seguente snippet di codice, in JavaScript, mostra un esempio di utilizzo dell'API di Google per accedere agli eventi nel calendario dell'utente sul 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 stabilisci che la tua app utilizza il flusso OOB su un client desktop, devi eseguire la migrazione al flusso degli indirizzi IP di loopback (localhost o 127.0.0.1).