Przewodnik migracji procesu poza zakresem (OOB)

Przegląd

16 lutego 2022 r. ogłosiliśmy plany zwiększenia bezpieczeństwa interakcji z Google OAuth przez używanie bezpieczniejszych przepływów OAuth. Z tego przewodnika dowiesz się, jakie zmiany i kroki są niezbędne, aby skutecznie przejść z przepływu OAuth poza pasmem (OOB) na obsługiwane alternatywy.

Jest to środek ochronny przed atakami phishingowymi i podszywaniem się pod aplikacje podczas interakcji z punktami końcowymi autoryzacji OAuth 2.0 Google.

Co to jest OOB?

OAuth out-of-band (OOB), zwany też opcją ręcznego kopiowania i wklejania, to starszy proces opracowany z myślą o obsłudze klientów natywnych, którzy nie mają identyfikatora URI przekierowania do akceptowania danych logowania po tym, jak użytkownik zatwierdzi prośbę o zgodę OAuth. Proces OOB stwarza ryzyko wyłudzania informacji na odległość, dlatego klienci muszą przejść na inną metodę, aby chronić się przed tą luką w zabezpieczeniach.

Proces OOB jest wycofywany w przypadku wszystkich typów klientów, czyli aplikacji internetowych, aplikacji na Androida, iOS, uniwersalnej platformy Windows (UWP), aplikacji Chrome, telewizorów i urządzeń z ograniczonymi możliwościami wprowadzania danych oraz aplikacji na komputery.

Najważniejsze daty związane z zgodnością

  • 28 lutego 2022 r. – zablokowanie nowego użycia OAuth w przypadku procesu OOB
  • 5 września 2022 r. – w przypadku niezgodnych żądań OAuth może być wyświetlany komunikat ostrzegawczy dla użytkowników.
  • 3 października 2022 r. – wycofanie przepływu OOB w przypadku klientów OAuth utworzonych przed 28 lutego 2022 r.
  • 31 stycznia 2023 r. – zablokowanie wszystkich dotychczasowych klientów (w tym klientów zwolnionych z tego obowiązku)

W przypadku żądań niezgodnych z zasadami będzie wyświetlany komunikat o błędzie dla użytkownika. Wiadomość będzie informować użytkowników, że aplikacja jest zablokowana, a jednocześnie będzie wyświetlać adres e-mail pomocy zarejestrowany na ekranie zgody OAuth w Konsoli interfejsów API Google.

Proces migracji składa się z 2 głównych kroków:
  1. Sprawdź, czy zmiana wpłynie na Twoje treści.
  2. Jeśli dotyczy Cię ten problem, przejdź na bezpieczniejszą alternatywę.

Sprawdź, czy zmiana wpłynie na Ciebie

Wycofanie dotyczy tylko aplikacji w wersji produkcyjnej (czyli aplikacji, których stan publikowania jest ustawiony na wersja produkcyjna). Proces będzie nadal działać w przypadku aplikacji ze stanem publikowania testów.

Sprawdź stan publikowania w sekcji OAuth Branding page Google Cloud Console i przejdź do następnego kroku, jeśli używasz przepływu OOB w projekcie o stanie publikowania „W wersji produkcyjnej”.

Jak sprawdzić, czy aplikacja korzysta z procesu OOB

Sprawdź kod aplikacji lub wychodzące wywołanie sieciowe (jeśli aplikacja korzysta z biblioteki OAuth), aby sprawdzić, czy żądanie autoryzacji OAuth Google wysyłane przez aplikację używa wartości identyfikatora URI przekierowania OOB.

Sprawdzanie kodu aplikacji

Sprawdź tę część kodu aplikacji, w której wywołujesz punkty końcowe autoryzacji protokołu OAuth Google, i określ, czy parametr redirect_uri ma jedną z tych wartości:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
Przykładowe żądanie przekierowania OOB będzie wyglądać tak:
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>

Sprawdzanie wychodzącego połączenia sieciowego

Metoda sprawdzania wywołań sieciowych zależy od typu klienta aplikacji.
Podczas sprawdzania wywołań sieciowych poszukaj żądań wysyłanych do punktów końcowych autoryzacji protokołu OAuth Google i sprawdź, czy parametr redirect_uri ma jedną z tych wartości:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
Przykładowe żądanie przekierowania OOB będzie wyglądać tak:
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>

Migracja do bezpieczniejszej alternatywy

Klienci mobilni (Android / iOS)

Jeśli stwierdzisz, że Twoja aplikacja korzysta z przepływu OOB z klientem OAuth na Androida lub iOS, przenieś ją na zalecane pakiety SDK (Android, iOS).

Pakiet SDK ułatwia dostęp do interfejsów API Google i obsługuje wszystkie wywołania punktów końcowych autoryzacji OAuth 2.0 Google.

Linki do dokumentacji poniżej zawierają informacje o tym, jak używać zalecanych pakietów SDK do uzyskiwania dostępu do interfejsów API Google bez używania adresu URI przekierowania OOB.

Dostęp do interfejsów API Google na Androidzie

Dostęp po stronie klienta

Poniższy przykład pokazuje, jak uzyskać dostęp do interfejsów API Google po stronie klienta na Androidzie za pomocą zalecanej biblioteki 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));

Przekaż authorizationResult do zdefiniowanej metody, aby zapisać treści w folderze na dysku użytkownika. Klasa authorizationResult ma metodę getAccessToken(), która zwraca token dostępu.

Dostęp po stronie serwera (offline)
Poniższy przykład pokazuje, jak uzyskać dostęp do interfejsów API Google po stronie serwera na Androidzie.
  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));

Obiekt authorizationResult ma metodę getServerAuthCode(), która zwraca kod autoryzacji, który możesz wysłać do backendu, aby uzyskać token dostępu i token odświeżania.

Dostęp do interfejsów API Google w aplikacji na iOS

Dostęp po stronie klienta

Poniższy przykład pokazuje, jak uzyskać dostęp do interfejsów API Google po stronie klienta na 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()
}

Użyj tokena dostępu do wywołania interfejsu API, dołączając go do nagłówka żądania REST lub gRPC (Authorization: Bearer ACCESS_TOKEN) albo używając autoryzatora pobierania (GTMFetcherAuthorizationProtocol) z biblioteką klienta interfejsów API Google dla języka Objective-C w przypadku REST.

Zapoznaj się z przewodnikiem po dostępie po stronie klienta, aby dowiedzieć się, jak uzyskać dostęp do interfejsów API Google po stronie klienta. o tym, jak uzyskać dostęp do interfejsów API Google po stronie klienta.

Dostęp po stronie serwera (offline)
Poniższy przykład pokazuje, jak uzyskać dostęp do interfejsów API Google po stronie serwera, aby obsługiwać klienta 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
}

Zapoznaj się z przewodnikiem po dostępie po stronie serwera, aby dowiedzieć się, jak uzyskiwać dostęp do interfejsów API Google po stronie serwera.

Klient aplikacji Chrome

Jeśli stwierdzisz, że Twoja aplikacja korzysta z procesu OOB na kliencie aplikacji Chrome, musisz przejść na interfejs Chrome Identity API.

Poniższy przykład pokazuje, jak uzyskać wszystkie kontakty użytkownika bez użycia adresu URI przekierowania 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)
    });
   });
 });
};

Więcej informacji o tym, jak uwierzytelniać użytkowników i wywoływać punkty końcowe Google za pomocą interfejsu Chrome Identity API, znajdziesz w  przewodniku po interfejsie Chrome Identity API.

Aplikacja internetowa

Jeśli stwierdzisz, że Twoja aplikacja internetowa korzysta z przepływu OOB, przenieś ją na jedną z naszych bibliotek klienta interfejsu Google API. Biblioteki klienta dla różnych języków programowania znajdziesz tutaj.

Biblioteki ułatwiają dostęp do interfejsów API Google i obsługują wszystkie wywołania punktów końcowych Google.

Dostęp po stronie serwera (offline)
Tryb dostępu po stronie serwera (offline) wymaga wykonania tych czynności:

Poniższy fragment kodu pokazuje przykład użycia interfejsu Google Drive API w NodeJS do wyświetlania plików użytkownika na Dysku Google po stronie serwera bez używania adresu URI przekierowania 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.
      });
    }
  }
}

Zapoznaj się z  przewodnikiem po aplikacjach internetowych po stronie serwera, aby dowiedzieć się, jak uzyskać dostęp do interfejsów API Google po stronie serwera.

Dostęp po stronie klienta

Poniższy fragment kodu w JavaScript pokazuje przykład użycia interfejsu Google API do uzyskiwania dostępu do wydarzeń w kalendarzu użytkownika po stronie klienta.


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

Zapoznaj się z  przewodnikiem po aplikacjach internetowych po stronie klienta , aby dowiedzieć się, jak uzyskać dostęp do interfejsów API Google po stronie klienta.

Klient na komputer

Jeśli stwierdzisz, że Twoja aplikacja korzysta z procesu OOB na komputerze, musisz przejść na proces adresu IP sprzężenia zwrotnego (localhost lub 127.0.0.1).