OAuth 2.0 na potrzeby aplikacji internetowych po stronie klienta

Ten dokument wyjaśnia, jak zaimplementować autoryzację OAuth 2.0, aby uzyskać dostęp do interfejsów API Google z aplikacji internetowej w JavaScript. OAuth 2.0 umożliwia użytkownikom udostępnianie określonych danych aplikacji przy jednoczesnym zachowaniu poufności nazw, haseł i innych informacji. Aplikacja może na przykład używać OAuth 2.0, aby uzyskać od użytkowników uprawnienia do przechowywania plików na Dysku Google.

Ten przepływ OAuth 2.0 nazywa się przepływem niejawnego udzielenia uprawnień. Jest przeznaczony dla aplikacji, które uzyskują dostęp do interfejsów API tylko wtedy, gdy użytkownik jest w aplikacji. Te aplikacje nie mogą przechowywać informacji poufnych.

W ramach tego procesu aplikacja otwiera adres URL Google, który używa parametrów zapytania do identyfikacji aplikacji oraz typu dostępu do interfejsu API, którego aplikacja wymaga. Adres URL możesz otworzyć w bieżącym oknie przeglądarki lub w wyskakującym okienku. Użytkownik może uwierzytelnić się w Google i przyznać żądane uprawnienia. Google przekierowuje użytkownika z powrotem do aplikacji. Przekierowanie zawiera token dostępu, który aplikacja weryfikuje, a potem używa do wysyłania żądań do interfejsu API.

Biblioteka klienta interfejsów API Google i usługi Google Identity

Jeśli do autoryzowanych wywołań interfejsów Google używasz biblioteki klienta interfejsów API Google dla JavaScript, do obsługi procesu OAuth 2.0 użyj biblioteki JavaScript Google Identity Services. Zapoznaj się z modelem tokenów usług Google Identity Services, który jest oparty na procesie domyślnego udzielania uprawnień w protokole OAuth 2.0.

Wymagania wstępne

Włączanie interfejsów API w projekcie

Każda aplikacja, która wywołuje interfejsy API Google, musi włączyć te interfejsy w  API Console.

Aby włączyć interfejs API w projekcie:

  1. Open the API Library w  Google API Console.
  2. If prompted, select a project, or create a new one.
  3. API Library Wyświetla wszystkie dostępne interfejsy API pogrupowane według rodziny produktów i popularności. Jeśli interfejs API, który chcesz włączyć, nie jest widoczny na liście, wyszukaj go lub kliknij Wyświetl wszystkie w grupie produktów, do której należy.
  4. Wybierz interfejs API, który chcesz włączyć, a następnie kliknij przycisk Włącz.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

Tworzenie danych uwierzytelniających

Każda aplikacja, która używa OAuth 2.0 do uzyskiwania dostępu do interfejsów API Google, musi mieć poświadczenia autoryzacyjne, które identyfikują ją na serwerze OAuth 2.0 Google. Z tych instrukcji dowiesz się, jak utworzyć poświadczenia tożsamości do projektu. Twoje aplikacje mogą wtedy używać tych danych logowania do uzyskiwania dostępu do interfejsów API, które zostały włączone w tym projekcie.

  1. Go to the Credentials page.
  2. Kliknij Utwórz dane logowania > Identyfikator klienta OAuth.
  3. Wybierz typ aplikacji Aplikacja internetowa.
  4. Wypełnij formularz. Aplikacje, które używają JavaScriptu do autoryzowanych żądań interfejsu Google API, muszą określać autoryzowane źródła JavaScriptu. Źródła identyfikują domeny, z których aplikacja może wysyłać żądania do serwera OAuth 2.0. Te źródła muszą być zgodne z zasadami walidacji Google.

Określanie zakresów dostępu

Zakresy umożliwiają aplikacji żądanie dostępu tylko do zasobów, których potrzebuje, a także kontrolowanie przez użytkowników zakresu dostępu przyznawanego aplikacji. Dlatego może istnieć odwrotna zależność między liczbą żądanych zakresów uprawnień a prawdopodobieństwom uzyskania zgody użytkownika.

Zanim zaczniesz wdrażać autoryzację OAuth 2.0, zalecamy określenie zakresów, do których aplikacja będzie potrzebować uprawnień dostępu.

Dokument Zakresy interfejsu API OAuth 2.0 zawiera pełną listę zakresów, których możesz używać do uzyskiwania dostępu do interfejsów API Google.

Pobieranie tokenów dostępu OAuth 2.0

Te czynności pokazują, jak aplikacja wchodzi w interakcję z serwerem OAuth 2.0 Google, aby uzyskać zgodę użytkownika na wykonanie żądania interfejsu API w imieniu tego użytkownika. Aplikacja musi mieć tę zgodę, zanim będzie mogła wykonać żądanie interfejsu Google API, które wymaga autoryzacji użytkownika.

Krok 1. Przekierowanie na serwer OAuth 2.0 Google

Aby poprosić o dostęp do danych użytkownika, przekieruj go na serwer OAuth 2.0 Google.

Punkty końcowe OAuth 2.0

Wygeneruj adres URL, aby poprosić o dostęp do punktu końcowego OAuth 2.0 Google na stronie https://accounts.google.com/o/oauth2/v2/auth. Ten punkt końcowy jest dostępny przez HTTPS. Połączenia HTTP nie są obsługiwane.

Serwer autoryzacji Google obsługuje te parametry ciągu zapytania w przypadku aplikacji serwera WWW:

Parametry
client_id Wymagany

Identyfikator klienta Twojej aplikacji. Znajdziesz ją w sekcji API Console: Credentials page.

redirect_uri Wymagany

Określa, dokąd serwer API przekieruje użytkownika po zakończeniu przez niego procesu autoryzacji. Wartość musi dokładnie pasować do jednego z autoryzowanych identyfikatorów URI przekierowania dla klienta OAuth 2.0 skonfigurowanego w API Console Credentials page. Jeśli ta wartość nie pasuje do autoryzowanego identyfikatora URI przekierowania dla podanego identyfikatora client_id, pojawi się błąd redirect_uri_mismatch.

Pamiętaj, że schemat http lub https, wielkość liter i znak ukośnik w końcu („/”) muszą być takie same.

response_type Wymagany

Aplikacje JavaScript muszą ustawić wartość tego parametru na token. Ta wartość instruuje serwer autoryzacji Google, aby zwracał token dostępu jako parę name=value w identyfikatorze fragmentu identyfikatora URI (#), do którego użytkownik jest przekierowywany po zakończeniu procesu autoryzacji.

scope Wymagany

Oddzielona spacjami lista zakresów, które identyfikują zasoby, do których aplikacja może uzyskać dostęp w imieniu użytkownika. Te wartości informują o ekranie zgody, który Google wyświetla użytkownikowi.

Zakresy umożliwiają aplikacji żądanie dostępu tylko do zasobów, których potrzebuje, a także kontrolowanie przez użytkowników zakresu dostępu przyznawanego aplikacji. W związku z tym istnieje odwrotna zależność między liczbą żądanych zakresów uprawnień a prawdopodobieństwom uzyskania zgody użytkownika.

Zalecamy, aby aplikacja zawsze, gdy to możliwe, prosiła o dostęp do zakresów autoryzacji w kontekście. Wyświetlając prośby o dostęp do danych użytkownika w odpowiednim kontekście (stosując uwierzytelnianie stopniowe), pomagasz użytkownikom łatwiej zrozumieć, dlaczego Twoja aplikacja potrzebuje dostępu, o który prosi.

state Zalecane

Określa dowolną wartość ciągu znaków, której aplikacja używa do zachowania stanu między żądaniem autoryzacji a odpowiedzią serwera autoryzacji. Serwer zwraca dokładną wartość, którą wysyłasz jako parę name=value w identyfikatorze fragmentu adresu URL (#) redirect_uri, gdy użytkownik wyrazi zgodę na żądanie dostępu aplikacji lub odmówi jego udzielenia.

Parametru tego można używać do różnych celów, np. do kierowania użytkownika do odpowiedniego zasobu w aplikacji, wysyłania identyfikatorów jednorazowych i ograniczania fałszowania żądań między witrynami. Ponieważ wartość redirect_uri można odgadnąć, użycie wartości state może zwiększyć pewność, że połączenie przychodzące jest wynikiem żądania uwierzytelnienia. Jeśli wygenerujesz losowy ciąg znaków lub zakodujesz hasz pliku cookie lub inną wartość, która odzwierciedla stan klienta, możesz dodatkowo sprawdzić odpowiedź, aby upewnić się, że żądanie i odpowiedź pochodzą z tego samego przeglądarki. Zapewnia to ochronę przed atakami takimi jak fałszowanie żądań między witrynami. Przykład utworzenia i potwierdzenia tokena state znajdziesz w dokumentacji OpenID Connect.

include_granted_scopes Opcjonalny

Umożliwia aplikacjom korzystanie z uwierzytelniania stopniowego do żądania dostępu do dodatkowych zakresów w kontekście. Jeśli wartość tego parametru zostanie ustawiona na true, a prośba o autoryzację zostanie zaakceptowana, nowy token dostępu będzie obejmował również wszystkie zakresy, do których użytkownik wcześniej przyznał aplikacji dostęp. Przykłady znajdziesz w sekcji autoryzacja cząstkowa.

login_hint Opcjonalny

Jeśli aplikacja wie, który użytkownik próbuje się uwierzytelnić, może użyć tego parametru, aby przekazać wskazówkę serwerowi uwierzytelniania Google. Serwer używa tego podpowiedzi do uproszczenia procesu logowania, wypełniając wstępnie pole adresu e-mail w formularzu logowania lub wybierając odpowiednią sesję logowania wielokrotnego.

Ustaw wartość parametru jako adres e-mail lub identyfikator sub, który jest równoważny z identyfikatorem Google użytkownika.

prompt Opcjonalny

Posortowana alfabetycznie lista promptów oddzielonych spacjami, w których wielkość liter ma znaczenie. Jeśli nie określisz tego parametru, użytkownik zobaczy prośbę tylko przy pierwszym żądaniu dostępu przez Twój projekt. Więcej informacji znajdziesz w artykule Prośba o ponowne wyrażenie zgody.

Możliwe wartości to:

none Nie wyświetlaj żadnych ekranów uwierzytelniania ani ekranów zgody. Nie można go określać w połączeniu z innymi wartościami.
consent poprosić użytkownika o zgodę.
select_account Poproś użytkownika o wybranie konta.

Przykładowe przekierowanie do serwera autoryzacji Google

Poniżej znajduje się przykładowy adres URL z przecinkami wierszy i spacją dla czytelności.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

Po utworzeniu adresu URL żądania przekieruj użytkownika na niego.

Przykładowy kod JavaScript

Ten fragment kodu JavaScriptu pokazuje, jak zainicjować proces autoryzacji w JavaScript bez użycia biblioteki klienta interfejsów API Google dla JavaScriptu. Ponieważ ten punkt końcowy OAuth 2.0 nie obsługuje współdzielenia zasobów pomiędzy serwerami z różnych domen (CORS), fragment kodu tworzy formularz, który otwiera żądanie do tego punktu końcowego.

/*
 * Create form to request access token from Google's OAuth 2.0 server.
 */
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

  // Create <form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);

  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client_id': 'YOUR_CLIENT_ID',
                'redirect_uri': 'YOUR_REDIRECT_URI',
                'response_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly',
                'include_granted_scopes': 'true',
                'state': 'pass-through value'};

  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

Krok 2. Google prosi użytkownika o zgodę

Na tym etapie użytkownik decyduje, czy przyznać Twojej aplikacji wymagany dostęp. Na tym etapie Google wyświetla okno zgody, w którym podaje nazwę aplikacji i usługi interfejsu API Google, do której chce uzyskać dostęp, wraz z danymi autoryzującymi użytkownika oraz podsumowaniem zakresów dostępu. Użytkownik może wyrazić zgodę na przyznanie dostępu do co najmniej 1 zakresu żądanego przez Twoją aplikację lub odrzucić prośbę.

Na tym etapie aplikacja nie musi nic robić, ponieważ czeka na odpowiedź z serwera OAuth 2.0 Google, która wskazuje, czy przyznano dostęp. Odpowiedź na to pytanie znajdziesz w następnym kroku.

Błędy

Żądania do punktu końcowego autoryzacji OAuth 2.0 Google mogą wyświetlać komunikaty o błędach zamiast oczekiwanych procesów uwierzytelniania i autoryzacji. Poniżej znajdziesz listę typowych kodów błędów i sugerowanych rozwiązań.

admin_policy_enforced

Konto Google nie może autoryzować co najmniej 1 żądanego zakresu uprawnień z powodu zasad administratora Google Workspace. Więcej informacji o tym, jak administrator może ograniczyć dostęp do wszystkich zakresów lub zakresów poufnych i ograniczonych, dopóki nie zostanie wyraźnie przyznany dostęp do Twojego identyfikatora klienta OAuth, znajdziesz w artykule pomocy dla administratorów Google Workspace Control which third-party & internal apps access Google Workspace data.

disallowed_useragent

Punkt końcowy autoryzacji jest wyświetlany w ramach wbudowanego użytkownika-agenta, który jest niedozwolony przez zasady OAuth 2.0 Google.

Android

Deweloperzy aplikacji na Androida mogą zobaczyć ten komunikat o błędzie podczas otwierania żądań autoryzacji w android.webkit.WebView. Deweloperzy powinni zamiast tego używać bibliotek Androida, takich jak Logowanie przez Google na Androida czy AppAuth na Androida od OpenID Foundation.

Deweloperzy mogą napotkać ten błąd, gdy aplikacja na Androida otwiera ogólny link internetowy w osadzonym user-agent i użytkownik przechodzi na punkt końcowy autoryzacji OAuth 2 Google z Twojej witryny. Deweloperzy powinni zezwolić na otwieranie ogólnych linków w domyślnym obsłudze linków systemu operacyjnego, co obejmuje zarówno obsługę linków aplikacji na Androida, jak i domyślną aplikację przeglądarki. Biblioteka kart niestandardowych Androida jest też obsługiwaną opcją.

iOS

Deweloperzy iOS i macOS mogą napotkać ten błąd podczas otwierania próśb o autoryzację w WKWebView. Deweloperzy powinni zamiast tego używać bibliotek iOS, takich jak Google Sign-In na iOS czy AppAuth na iOS od OpenID Foundation.

Deweloperzy witryn mogą napotkać ten błąd, gdy aplikacja na iOS lub macOS otwiera ogólny link internetowy w osadzonym user-agent i użytkownik przechodzi do punktu autoryzacji OAuth 2.0 Google z Twojej witryny. Deweloperzy powinni zezwolić na otwieranie ogólnych linków w domyślnym obsłudze linków systemu operacyjnego, który obejmuje zarówno obsługę linków uniwersalnych, jak i domyślną aplikację przeglądarki. Biblioteka SFSafariViewController jest też obsługiwaną opcją.

org_internal

Identyfikator klienta OAuth w żądaniu należy do projektu, który ogranicza dostęp do kont Google w określonej organizacji Google Cloud. Więcej informacji o tej opcji konfiguracji znajdziesz w sekcji Typ użytkownika w artykule pomocy Konfigurowanie ekranu zgody OAuth.

invalid_client

Źródło, z którego wysłano żądanie, nie jest autoryzowane dla tego klienta. Zobacz: origin_mismatch.

invalid_grant

Gdy używasz autoryzacji stopniowej, token może wygasnąć lub zostać unieważniony. Użytkownik musi się ponownie uwierzytelnić i wyrazić zgodę na uzyskanie nowych tokenów. Jeśli ten błąd będzie się powtarzał, sprawdź, czy aplikacja jest prawidłowo skonfigurowana i czy używasz w żądaniu prawidłowych tokenów i parametrów. W przeciwnym razie konto użytkownika mogło zostać usunięte lub wyłączone.

origin_mismatch

Schemat, domena lub port kodu JavaScript, z którego pochodzi żądanie autoryzacji, mogą nie pasować do autoryzowanego identyfikatora URI źródła JavaScript zarejestrowanego dla identyfikatora klienta OAuth. Sprawdź autoryzowane źródła JavaScriptu w  Google API Console Credentials page.

redirect_uri_mismatch

Wartość redirect_uri przekazana w żądaniu autoryzacji nie odpowiada autoryzowanemu identyfikatorowi URI przekierowania dla identyfikatora klienta OAuth. Sprawdź autoryzowane identyfikatory URI przekierowania w sekcji Google API Console Credentials page.

Schemat, domena lub port kodu JavaScript, z którego pochodzi żądanie autoryzacji, mogą nie pasować do autoryzowanego identyfikatora URI źródła JavaScript zarejestrowanego dla identyfikatora klienta OAuth. Sprawdź autoryzowane źródła JavaScriptu w sekcji Google API Console Credentials page.

Parametr redirect_uri może odnosić się do przesyłania poza pasmem (OOB) w ramach protokołu OAuth, które zostało wycofane i nie jest już obsługiwane. Aby zaktualizować integrację, zapoznaj się z przewodnikiem po migracji.

invalid_request

Coś poszło nie tak z Twoją prośbą. Może to wynikać z kilku powodów:

  • żądanie jest nieprawidłowo sformatowane;
  • Brak wymaganych parametrów w prośbie
  • Żądanie używa metody autoryzacji, której Google nie obsługuje. Sprawdź, czy integracja OAuth używa zalecanej metody integracji

Krok 3. Przetwórz odpowiedź serwera OAuth 2.0

Punkty końcowe OAuth 2.0

Serwer OAuth 2.0 wysyła odpowiedź do redirect_uri podanego w żądaniu tokena dostępu.

Jeśli użytkownik zatwierdzi żądanie, odpowiedź będzie zawierać token dostępu. Jeśli użytkownik nie zaakceptuje prośby, odpowiedź będzie zawierać komunikat o błędzie. Token dostępu lub komunikat o błędzie jest zwracany w haśle fragmentu identyfikatora URI przekierowania, jak pokazano poniżej:

  • Odpowiedź tokena dostępu:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

    Oprócz parametru access_token zawiera on też parametr token_type, który jest zawsze ustawiony na wartość Bearer, oraz parametr expires_in, który określa czas ważności tokenu w sekundach. Jeśli parametr state został określony w żądaniu tokena dostępu, jego wartość jest też uwzględniana w odpowiedzi.

  • Odpowiedź błędu:
    https://oauth2.example.com/callback#error=access_denied

Przykładowa odpowiedź serwera OAuth 2.0

Możesz przetestować ten proces, klikając ten przykładowy adres URL, który prosi o dostęp tylko do odczytu w celu wyświetlania metadanych plików na Dysku Google oraz dostęp tylko do odczytu w celu wyświetlania wydarzeń w Kalendarzu Google:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly%20https%3A//www.googleapis.com/auth/calendar.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

Po zakończeniu procesu OAuth 2.0 zostaniesz przekierowany na stronę http://localhost/oauth2callback. Ten adres URL spowoduje błąd 404 NOT FOUND, chyba że na Twoim komputerze lokalnym znajduje się plik o tym adresie. Następny krok zawiera więcej informacji o danych zwracanych w identyfikatorze URI, gdy użytkownik zostanie przekierowany z powrotem do aplikacji.

Krok 4. Sprawdź, jakie zakresy przyznali użytkownicy

Gdy żądasz dostępu do wielu zakresów naraz, użytkownicy mogą nie przyznać dostępu do wszystkich zakresów, o które prosi Twoja aplikacja. Aplikacja powinna zawsze sprawdzać, jakie zakresy zostały przyznane przez użytkownika, i w przypadku odmowy przyznania zakresu wyłączać odpowiednie funkcje. Więcej informacji znajdziesz w artykule Zarządzanie szczegółowymi uprawnieniami.

Punkty końcowe OAuth 2.0

Aby sprawdzić, czy użytkownik przyznał aplikacji dostęp do określonego zakresu, sprawdź pole scope w odpowiedzi na żądanie tokena dostępu. Zakresy dostępu przyznawane przez token dostępu w postaci listy ciągów znaków oddzielonych spacjami, w których rozróżniane są wielkość liter.

Na przykład ta przykładowa odpowiedź na żądanie tokena dostępu wskazuje, że użytkownik przyznał Twojej aplikacji uprawnienia do odczytu aktywności na Dysku i do wydarzeń w Kalendarzu:

  {
    "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
    "expires_in": 3920,
    "token_type": "Bearer",
    "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
    "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
  }

Wywoływanie interfejsów API Google

Punkty końcowe OAuth 2.0

Gdy aplikacja uzyska token dostępu, możesz używać tego tokena do wywoływania interfejsów API Google w imieniu danego konta użytkownika, jeśli przyznano uprawnienia dostępu wymagane przez interfejs API. Aby to zrobić, dodaj token dostępu do żądania do interfejsu API, podając parametr zapytania access_token lub wartość nagłówka HTTP Authorization Bearer. Jeśli to możliwe, zalecamy użycie nagłówka HTTP, ponieważ ciągi znaków zapytania są zwykle widoczne w dziennikach serwera. W większości przypadków do konfigurowania wywołań interfejsów API Google możesz użyć biblioteki klienta (np. podczas wywołania interfejsu Drive API).

Możesz wypróbować wszystkie interfejsy API Google i wyświetlić ich zakresy na stronie OAuth 2.0 Playground.

Przykłady żądań HTTP GET

Wywołanie punktu końcowego drive.files (interfejsu Drive Files API) za pomocą nagłówka HTTP Authorization: Bearer może wyglądać tak: Pamiętaj, że musisz podać własny token dostępu:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Oto wywołanie tego samego interfejsu API dla uwierzytelnionego użytkownika za pomocą parametru ciągu zapytania access_token:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

curl przykładu

Te polecenia możesz przetestować za pomocą aplikacji wiersza poleceń curl. Oto przykład użycia opcji nagłówka HTTP (preferowana):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

Możesz też użyć parametru ciągu zapytania:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

Przykładowy kod JavaScript

Ten fragment kodu pokazuje, jak za pomocą CORS (udostępnianie zasobów między domenami) wysłać żądanie do interfejsu Google API. W tym przykładzie nie używamy biblioteki klienta interfejsów API Google dla JavaScriptu. Nawet jeśli nie używasz biblioteki klienta, przewodnik po obsłudze CORS w dokumentacji tej biblioteki może Ci pomóc lepiej zrozumieć te żądania.

W tym fragmencie kodu zmienna access_token reprezentuje token uzyskany w celu wysyłania żądań do interfejsu API w imieniu autoryzowanego użytkownika. Pełny przykład pokazuje, jak zapisać ten token w pamięci lokalnej przeglądarki i odzyskać go podczas wysyłania żądania do interfejsu API.

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/drive/v3/about?fields=user&' +
    'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
  console.log(xhr.response);
};
xhr.send(null);

Pełny przykład

Punkty końcowe OAuth 2.0

Ten przykładowy kod pokazuje, jak ukończyć proces OAuth 2.0 w JavaScript bez używania biblioteki klienta interfejsów Google API dla JavaScriptu. Kod jest przeznaczony do strony HTML, na której wyświetla się przycisk umożliwiający wypróbowanie żądania interfejsu API. Gdy klikniesz przycisk, kod sprawdzi, czy strona zapisała token dostępu do interfejsu API w pamięci lokalnej przeglądarki. Jeśli tak, wykonuje żądanie interfejsu API. W przeciwnym razie rozpocznie przepływ OAuth 2.0.

W przypadku protokołu OAuth 2.0 strona wykonuje te czynności:

  1. Przekierowuje użytkownika do serwera OAuth 2.0 Google, który prosi o dostęp do zakresów https://www.googleapis.com/auth/drive.metadata.readonlyhttps://www.googleapis.com/auth/calendar.readonly.
  2. Po przyznaniu (lub odmowie przyznania) dostępu do co najmniej jednego żądanego zakresu użytkownik jest przekierowywany na stronę pierwotną, która zinterpretuje token dostępu z łańcucha identyfikatora fragmentu.
  3. Strona sprawdza, do których zakresów użytkownik przyznał dostęp aplikacji.
  4. Jeśli użytkownik przyznał dostęp do żądanych zakresów, strona używa tokena dostępu do przesłania przykładowego żądania interfejsu API.

    Żądanie interfejsu API wywołuje metodę about.get interfejsu Drive API, aby pobrać informacje o koncie Dysku Google autoryzowanego użytkownika.

  5. Jeśli żądanie zostanie wykonane pomyślnie, odpowiedź interfejsu API zostanie zarejestrowana w konsoli debugowania przeglądarki.

Możesz cofnąć dostęp aplikacji na stronie Uprawnienia na koncie Google. Aplikacja będzie widoczna jako Demo OAuth 2.0 dla interfejsu Google Docs API.

Aby uruchomić ten kod lokalnie, musisz ustawić wartości zmiennych YOUR_CLIENT_ID i YOUR_REDIRECT_URI odpowiadające Twoim danym autoryzacyjnym. Zmienna YOUR_REDIRECT_URI powinna być ustawiona na ten sam URL, pod którym wyświetlana jest strona. Wartość musi dokładnie pasować do jednego z autoryzowanych identyfikatorów URI przekierowania dla klienta OAuth 2.0 skonfigurowanego w API Console Credentials page. Jeśli ta wartość nie pasuje do autoryzowanego identyfikatora URI, pojawi się błąd redirect_uri_mismatch. Twój projekt musi też mieć włączony odpowiedni interfejs API do obsługi tej prośby.

<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var fragmentString = location.hash.substring(1);
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0 && params['state']) {
    if (params['state'] == localStorage.getItem('state')) {
      localStorage.setItem('oauth2-test-params', JSON.stringify(params) );

      trySampleRequest();
    } else {
      console.log('State mismatch. Possible CSRF attack');
    }
  }

  // Function to generate a random state value
  function generateCryptoRandomState() {
    const randomValues = new Uint32Array(2);
    window.crypto.getRandomValues(randomValues);

    // Encode as UTF-8
    const utf8Encoder = new TextEncoder();
    const utf8Array = utf8Encoder.encode(
      String.fromCharCode.apply(null, randomValues)
    );

    // Base64 encode the UTF-8 data
    return btoa(String.fromCharCode.apply(null, utf8Array))
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=+$/, '');
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) { 
      // User authorized the request. Now, check which scopes were granted.
      if (params['scope'].includes('https://www.googleapis.com/auth/drive.metadata.readonly')) {
        // User authorized read-only Drive activity permission.
        // Calling the APIs, etc.
        var xhr = new XMLHttpRequest();
        xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
        xhr.onreadystatechange = function (e) {
          if (xhr.readyState === 4 && xhr.status === 200) {
            console.log(xhr.response);
          } else if (xhr.readyState === 4 && xhr.status === 401) {
            // Token invalid, so prompt for user permission.
            oauth2SignIn();
          }
        };
        xhr.send(null);
      }
      else {
        // User didn't authorize read-only Drive activity permission.
        // Update UX and application accordingly
        console.log('User did not authorize read-only Drive activity permission.');
      }

      // Check if user authorized Calendar read permission.
      if (params['scope'].includes('https://www.googleapis.com/auth/calendar.readonly')) {
        // User authorized Calendar read permission.
        // Calling the APIs, etc.
        console.log('User authorized Calendar read permission.');
      }
      else {
        // User didn't authorize Calendar read permission.
        // Update UX and application accordingly
        console.log('User did not authorize Calendar read permission.');
      } 
    } else {
      oauth2SignIn();
    }
  }

  /*
   * Create form to request access token from Google's OAuth 2.0 server.
   */
  function oauth2SignIn() {
    // create random state value and store in local storage
    var state = generateCryptoRandomState();
    localStorage.setItem('state', state);

    // Google's OAuth 2.0 endpoint for requesting an access token
    var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly',
                  'state': state,
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

Reguły weryfikacji źródła JavaScript

Aby pomóc deweloperom w zapewnieniu bezpieczeństwa ich aplikacji, Google stosuje do źródeł kodu JavaScript te reguły sprawdzania. Źródła kodu JavaScript muszą być zgodne z tymi zasadami. Definicje domeny, hosta i schematu wymienione poniżej znajdziesz w sekcji 3 dokumentu RFC 3986.

Reguły weryfikacji
Schemat

Źródła kodu JavaScript muszą używać protokołu HTTPS, a nie zwykłego HTTP. Identyfikatory URI localhost (w tym identyfikatory URI adresów IP localhost) są wyłączone z tego wymogu.

Osoba prowadząca

Hostami nie mogą być zwykłe adresy IP. Z tej reguły wyłączone są adresy IP lokalnego hosta.

Domena
  • Domeny najwyższego poziomu (TLD) hosta muszą należeć do listy domen publicznych.
  • Domeny hosta nie mogą mieć wartości “googleusercontent.com”.
  • Źródła kodu JavaScript nie mogą zawierać domen skróconych adresów URL (np. goo.gl), chyba że domena należy do aplikacji.
  • Informacje o użytkowniku

    Źródła skryptu JavaScript nie mogą zawierać podelementu userinfo.

    Ścieżka

    Źródła kodu JavaScript nie mogą zawierać elementu ścieżki.

    Zapytanie

    Źródła kodu JavaScript nie mogą zawierać komponentu zapytania.

    Fragment

    Źródła kodu JavaScript nie mogą zawierać komponentu fragmentu.

    Znaki Punkty początkowe JavaScript nie mogą zawierać niektórych znaków, w tym:
    • Symbole wieloznaczne ('*')
    • Niedrukowalne znaki ASCII
    • Nieprawidłowe kodowanie procentów (dowolne kodowanie procentów, które nie jest zgodne z formatem kodowania adresów URL, czyli nie zawiera znaku procenta i 2 cyfr szesnastkowych)
    • znaki puste (zakodowany znak NULL, np. %00, %C0%80)

    Autoryzacja przyrostowa

    W protokole OAuth 2.0 aplikacja prosi o autoryzację dostępu do zasobów, które są identyfikowane przez zakresy. W ramach najlepszej praktyki dotyczącej komfortu użytkowników należy poprosić o autoryzację zasobów w chwili, gdy są one potrzebne. Aby umożliwić tę praktykę, serwer autoryzacji Google obsługuje autoryzację przyrostową. Ta funkcja umożliwia żądanie zakresów w miarę potrzeby, a jeśli użytkownik przyzna uprawnienia do nowego zakresu, zwraca kod autoryzacji, który można wymienić na token zawierający wszystkie zakresy przyznane przez użytkownika projektowi.

    Na przykład aplikacja, która umożliwia użytkownikom odsłuchiwanie fragmentów utworów muzycznych i tworzenie miksów, może potrzebować bardzo niewielu zasobów w momencie logowania się, być może tylko nazwy logującej się osoby. Zapisanie gotowego miksu wymaga jednak dostępu do Dysku Google. Większość osób uznałaby za naturalne, że aplikacja poprosi o dostęp do Dysku Google tylko wtedy, gdy będzie go potrzebować.

    W tym przypadku podczas logowania aplikacja może poprosić o uprawnienia openidprofile, aby przeprowadzić podstawowe logowanie, a potem poprosić o uprawnienia https://www.googleapis.com/auth/drive.file w momencie wysłania pierwszego żądania, aby zaoszczędzić czas.

    W przypadku tokena dostępu uzyskanego z autoryzacji stopniowej obowiązują te reguły:

    • Token może służyć do uzyskiwania dostępu do zasobów odpowiadających zakresom włączonym do nowej, połączonej autoryzacji.
    • Gdy użyjesz tokena odświeżania do autoryzacji połączonej, aby uzyskać token dostępu, token dostępu będzie reprezentować autoryzację połączoną i może być użyty do dowolnej wartościscope zawartej w odpowiedzi.
    • Połączona autoryzacja obejmuje wszystkie zakresy dostępu przyznane przez użytkownika projektowi interfejsu API, nawet jeśli prośby o te uprawnienia zostały wysłane z różnych klientów. Jeśli na przykład użytkownik przyznał dostęp do jednego zakresu za pomocą klienta aplikacji na komputer, a następnie przyznał inny zakres do tej samej aplikacji za pomocą klienta mobilnego, połączone upoważnienie będzie obejmować oba zakresy.
    • Jeśli cofniesz token reprezentujący autoryzację łączoną, dostęp do wszystkich zakresów autoryzacji w imieniu powiązanego użytkownika zostanie cofnięta jednocześnie.

    Przykłady kodu poniżej pokazują, jak dodać zakresy do dotychczasowego tokena dostępu. Dzięki temu nie musisz zarządzać wieloma tokenami dostępu.

    Punkty końcowe OAuth 2.0

    Aby dodać zakresy do istniejącego tokena dostępu, dodaj parametr include_granted_scopes do żądania wysyłanego na serwer OAuth 2.0 Google.

    Poniżej znajdziesz fragment kodu, który pokazuje, jak to zrobić. Fragment kodu zakłada, że zakresy, dla których token dostępu jest ważny, są przechowywane w pamięci lokalnej przeglądarki. (Kod pełnego przykładu przechowuje listę zakresów, w których token dostępu jest ważny, ustawiając właściwość oauth2-test-params.scope w pamięci lokalnej przeglądarki.)

    Fragment kodu porównuje zakresy, w których token dostępu jest ważny, z zakresem, którego chcesz użyć w konkretnym zapytaniu. Jeśli token dostępu nie obejmuje tego zakresu, rozpoczyna się przepływ OAuth 2.0. Funkcja oauth2SignIn jest taka sama jak w kroku 2 (i jest podana później w pełnym przykładzie).

    var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    Unieważnianie tokena

    W niektórych przypadkach użytkownik może chcieć cofnąć dostęp aplikacji. Użytkownik może cofnąć dostęp, otwierając Ustawienia konta. Więcej informacji znajdziesz w sekcji Usuwanie dostępu strony lub aplikacji do Twojego konta w dokumentacji pomocy Strony internetowe i aplikacje innych firm z dostępem do Twojego konta.

    Aplikacja może też automatycznie cofnąć przyznany dostęp. Automatyczne odwoływanie jest ważne w przypadkach, gdy użytkownik zrezygnuje z subskrypcji, usunie aplikację lub zasoby interfejsu API wymagane przez aplikację ulegną znacznym zmianom. Innymi słowy, część procesu usuwania może obejmować żądanie interfejsu API, aby usunąć uprawnienia wcześniej przyznane aplikacji.

    Punkty końcowe OAuth 2.0

    Aby programowo unieważnić token, aplikacja wysyła żądanie do interfejsu https://oauth2.googleapis.com/revoke, dołączając token jako parametr:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    Token może być tokenem dostępu lub tokenem odświeżania. Jeśli token jest tokenem dostępu i ma odpowiadający mu token odświeżania, token odświeżania zostanie również cofnięty.

    Jeśli odwołanie zostało przetworzone, kod stanu HTTP odpowiedzi to 200. W przypadku błędów zwracany jest kod stanu HTTP 400 oraz kod błędu.

    Ten fragment kodu JavaScriptu pokazuje, jak cofnąć token w JavaScriptzie bez używania biblioteki klienta interfejsów Google API dla JavaScriptu. Ponieważ punkt końcowy Google OAuth 2.0 do odwoływania tokenów nie obsługuje udostępniania zasobów między domenami (CORS), kod tworzy formularz i przesyła go do punktu końcowego zamiast używać metody XMLHttpRequest() do przesyłania żądania.

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }

    Wdrażanie Ochrony wszystkich kont

    Dodatkowym krokiem, który należy wykonać, aby chronić konta użytkowników, jest wdrożenie ochrony na wielu kontach za pomocą usługi Google Cross-Account Protection. Ta usługa umożliwia subskrybowanie powiadomień o zdarzeniach związanych z bezpieczeństwem, które dostarczają aplikacji informacji o ważnych zmianach na koncie użytkownika. Następnie możesz podjąć odpowiednie działania w zależności od tego, jak chcesz reagować na zdarzenia.

    Przykłady typów zdarzeń wysyłanych do Twojej aplikacji przez usługę ochrony na wielu kontach:

    • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
    • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
    • https://schemas.openid.net/secevent/risc/event-type/account-disabled

    Więcej informacji o wdrażaniu ochrony wszystkich kont oraz pełną listę dostępnych zdarzeń znajdziesz na stronie Ochrona kont użytkowników za pomocą ochrony wszystkich kont .