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.
- Determinare se sei interessato.
- 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
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
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
- Applicazione web - esamina l'attività di rete su Chrome
- Android - ispeziona il traffico di rete con Network Inspector
-
App Chrome
- Vai alla pagina delle estensioni di Chrome.
- Seleziona la casella di controllo Modalità sviluppatore nell'angolo in alto a destra della pagina delle estensioni.
- Seleziona l'estensione che vuoi monitorare
- Fai clic sul link pagina di sfondo nella sezione Ispeziona visualizzazioni della pagina dell'estensione.
- Si aprirà un popup Strumenti per sviluppatori in cui potrai monitorare il traffico di rete nella scheda Rete
- iOS - Analisi del traffico HTTP con Instruments
- Universal Windows Platform (UWP) - Inspect network traffic in Visual Studio
- App desktop - utilizza uno strumento di acquisizione di rete disponibile per il sistema operativo per cui è stata sviluppata l'app
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
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.
ListrequestedScopes = 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.ListrequestedScopes = 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)
- 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
).