Używanie protokołu OAuth 2.0 w aplikacjach międzyserwerowych

System Google OAuth 2.0 obsługuje interakcję między serwerami, na przykład między aplikacją internetową a usługą Google. W tym scenariuszu potrzebujesz konta usługi, które należy do Twojej aplikacji, a nie do użytkownika. Aplikacja wywołuje interfejsy API Google w imieniu konta usługi, więc użytkownicy nie biorą w tym bezpośrednio udziału. Ten scenariusz jest czasami nazywany „OAuth z 2 etapami” lub „2LO”. (Powiązany termin „trzyetapowa autoryzacja OAuth” odnosi się do sytuacji, w których aplikacja wywołuje interfejsy API Google w imieniu użytkowników końcowych i w których czasami wymagana jest zgoda użytkownika).

Zazwyczaj aplikacja używa konta usługi, gdy korzysta z interfejsów API Google do pracy z własnymi danymi, a nie z danymi użytkownika. Na przykład aplikacja, która używa Google Cloud Datastore do utrwalania danych, używa konta usługi do uwierzytelniania wywołań interfejsu Google Cloud Datastore API.

Administratorzy domeny Google Workspace mogą też przyznawać kontom usługi uprawnienia w całej domenie, aby miały dostęp do danych użytkowników w domenie w ich imieniu.

W tym dokumencie opisujemy, jak aplikacja może przeprowadzić procedurę OAuth 2.0 w trybie serwer-serwer, korzystając z biblioteki klienta interfejsów API Google (zalecane) lub protokołu HTTP.

Przegląd

Aby obsługiwać interakcje między serwerami, najpierw utwórz konto usługi dla swojego projektu w API Console. Jeśli chcesz uzyskać dostęp do danych użytkowników na koncie Google Workspace, przekaż konto usługi uprawnienia w obrębie całej domeny.

Następnie aplikacja przygotowuje się do wykonywania autoryzowanych wywołań interfejsu API, używając danych logowania konta usługi do wysyłania żądań tokena dostępu do serwera autoryzacji OAuth 2.0.

Na koniec aplikacja może użyć tokena dostępu do wywoływania interfejsów API Google.

Tworzę konto usługi

Dane logowania konta usługi obejmują wygenerowany adres e-mail, który jest unikalny, oraz co najmniej 1 parę kluczy publicznego i prywatnego. Jeśli przekazywanie dostępu w całej domenie jest włączone, identyfikator klienta jest również częścią danych logowania konta usługi.

Jeśli Twoja aplikacja działa w Google App Engine, konto usługi jest konfigurowane automatycznie podczas tworzenia projektu.

Jeśli Twoja aplikacja działa w Google Compute Engine, konto usługi jest też konfigurowane automatycznie podczas tworzenia projektu, ale podczas tworzenia instancji Google Compute Engine musisz określić zakresy, do których Twoja aplikacja potrzebuje dostępu. Więcej informacji znajdziesz w artykule Przygotowywanie instancji do korzystania z kont usługi.

Jeśli Twoja aplikacja nie działa w Google App Engine ani Google Compute Engine, musisz uzyskać te dane logowania w  Google API Console. Aby wygenerować dane logowania konta usługi lub wyświetlić wygenerowane już publiczne dane logowania:

Najpierw utwórz konto usługi:

  1. Otwórz Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. Kliknij Utwórz konto usługi .
  4. W obszarze Szczegóły konta usługi wpisz nazwę, identyfikator i opis konta usługi, a następnie kliknij Utwórz i kontynuuj .
  5. Opcjonalnie: w obszarze Przyznaj temu kontu usługi dostęp do projektu wybierz role uprawnień, które chcesz przyznać kontu usługi.
  6. Kliknij Kontynuuj .
  7. Opcjonalnie: w obszarze Przyznaj użytkownikom dostęp do tego konta usługi dodaj użytkowników lub grupy, które mogą używać konta usługi i zarządzać nim.
  8. Kliknij Gotowe .

Następnie utwórz klucz konta usługi:

  1. Kliknij adres e-mail utworzonego konta usługi.
  2. Kliknij kartę Klucze .
  3. Z listy rozwijanej Dodaj klucz wybierz opcję Utwórz nowy klucz .
  4. Kliknij Utwórz .

Twoja nowa para kluczy publiczny/prywatny jest generowana i pobierana na twój komputer; służy jako jedyna kopia klucza prywatnego. Jesteś odpowiedzialny za bezpieczne przechowywanie. Jeśli zgubisz tę parę kluczy, będziesz musiał wygenerować nową.

W każdej chwili możesz wrócić do sekcji API Console, aby wyświetlić adres e-mail, odciski kluczy publicznych i inne informacje lub wygenerować dodatkowe pary kluczy publiczny/prywatny. Więcej informacji o danych logowania konta usługi w  API Consoleznajdziesz w pliku pomocy w sekcji API ConsoleKonta usługi.

Zanotuj adres e-mail konta usługi i zapisz plik klucza prywatnego konta usługi w lokalizacji dostępnej dla aplikacji. Aplikacja potrzebuje ich do wykonywania autoryzowanych wywołań interfejsu API.

Przekazywanie kontu usługi uprawnień do całej domeny

Administrator Workspace w organizacji może autoryzować aplikację, aby uzyskiwała dostęp do danych użytkowników Workspace w imieniu użytkowników w domenie Google Workspace. Na przykład aplikacja, która używa interfejsu Google Calendar API do dodawania wydarzeń do kalendarzy wszystkich użytkowników w domenie Google Workspace, używa konta usługi, aby uzyskiwać dostęp do interfejsu Google Calendar API w imieniu użytkowników. Przyznanie kontu usługi dostępu do danych w imieniu użytkowników w domenie jest czasami określane jako „przekazywanie kontu usługi uprawnień do całej domeny”.

Aby przekazać uprawnienia w obrębie całej domeny na konto usługi, superadministrator domeny Google Workspace musi wykonać te czynności:

  1. W konsoli administracyjnej domeny Google Workspace kliknij Menu główne  Bezpieczeństwo > Dostęp do danych i kontrola nad nimi > Dostęp do interfejsów API.
  2. W okienku Przekazywanie dostępu w całej domenie kliknij Zarządzaj przekazywaniem dostępu w całej domenie.
  3. Kliknij Dodaj domenę.
  4. W polu Identyfikator klienta wpisz identyfikator klienta konta usługi. Identyfikator klienta konta usługi znajdziesz w  Service accounts page.
  5. W polu Zakresy OAuth (rozdzielone przecinkami) wpisz listę zakresów, do których Twoja aplikacja powinna mieć dostęp. Jeśli na przykład aplikacja potrzebuje pełnego dostępu w całej domenie do interfejsów Google Drive API i Google Calendar API, wpisz: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. Kliknij Autoryzuj.

Aplikacja ma teraz uprawnienia do wywoływania interfejsów API jako użytkownicy w domenie Workspace (do „podszywania się” pod użytkowników). Gdy przygotowujesz się do wykonania tych wywołań interfejsu API z uprawnieniami delegowanymi, musisz wyraźnie określić użytkownika, którego chcesz naśladować.

Przygotowywanie się do wywołania interfejsu API w imieniu użytkownika

Java

Po uzyskaniu adresu e-mail klienta i klucza prywatnego z  API Consoleużyj biblioteki Google Auth Library for Java, aby utworzyć obiekt GoogleCredentials na podstawie danych logowania konta usługi i zakresów, do których Twoja aplikacja potrzebuje dostępu. Na przykład:

import com.google.auth.oauth2.GoogleCredentials;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

Jeśli tworzysz aplikację na platformie Google Cloud Platform, możesz zamiast tego użyć domyślnych danych logowania aplikacji, co może uprościć ten proces.

Przekazywanie uprawnień w całej domenie

Jeśli konto usługi ma przekazany dostęp w obrębie całej domeny i chcesz przyjąć tożsamość konta użytkownika, podaj adres e-mail tego konta za pomocą metody createDelegated obiektu GoogleCredentials. Na przykład:

GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("workspace-user@example.com");

Powyższy kod używa obiektu GoogleCredentials do wywołania metody createDelegated(). Argumentem metody createDelegated() musi być użytkownik należący do Twojego konta Workspace. Kod wysyłający żądanie będzie używać tych danych logowania do wywoływania interfejsów API Google przy użyciu konta usługi.

Python

Po uzyskaniu adresu e-mail klienta i klucza prywatnego z  API Consolewykonaj te czynności, korzystając z biblioteki klienta interfejsu API Google dla języka Python:

  1. Utwórz obiekt Credentials na podstawie danych logowania konta usługi i zakresów, do których Twoja aplikacja potrzebuje dostępu. Na przykład:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    Jeśli tworzysz aplikację na platformie Google Cloud Platform, możesz zamiast tego użyć domyślnych danych logowania aplikacji, co może uprościć ten proces.

  2. Przekazywanie uprawnień w całej domenie

    Jeśli masz przekazany dostęp do całej domeny na konto usługi i chcesz przyjąć tożsamość konta użytkownika, użyj metody with_subject istniejącego obiektu ServiceAccountCredentials. Na przykład:

    delegated_credentials = credentials.with_subject('user@example.org')

Używaj obiektu Credentials do wywoływania interfejsów API Google w aplikacji.

HTTP/REST

Po uzyskaniu identyfikatora klienta i klucza prywatnego z  API Consoleaplikacja musi wykonać te czynności:

  1. Utwórz token sieciowy JSON (JWT, wymawiany „dżot”), który zawiera nagłówek, zbiór deklaracji i podpis.
  2. Poproś serwer autoryzacji Google OAuth 2.0 o token dostępu.
  3. Obsłuż odpowiedź JSON zwracaną przez serwer autoryzacji.

W kolejnych sekcjach znajdziesz informacje o tym, jak wykonać te czynności.

Jeśli odpowiedź zawiera token dostępu, możesz go użyć do wywołania interfejsu API Google. (Jeśli odpowiedź nie zawiera tokena dostępu, token JWT i żądanie tokena mogą być nieprawidłowo sformułowane lub konto usługi może nie mieć uprawnień dostępu do żądanych zakresów).

Gdy token dostępu wygasa, aplikacja generuje kolejny token JWT, podpisuje go i wysyła żądanie kolejnego tokena dostępu.

Aplikacja serwera używa tokena JWT do wysyłania żądań tokena do serwera autoryzacji Google, a następnie używa tokena do wywoływania punktu końcowego interfejsu API Google. Nie jest zaangażowany żaden użytkownik.

W pozostałej części tej sekcji opisujemy szczegóły tworzenia i podpisywania tokena JWT, tworzenia żądania tokena dostępu oraz obsługi odpowiedzi.

Tworzenie tokena JWT

Token JWT składa się z 3 części: nagłówka, zbioru deklaracji i podpisu. Nagłówek i zbiór deklaracji to obiekty JSON. Te obiekty JSON są serializowane do bajtów UTF-8, a następnie kodowane przy użyciu kodowania Base64url. To kodowanie zapewnia odporność na zmiany kodowania spowodowane powtarzającymi się operacjami kodowania. Nagłówek, zbiór deklaracji i podpis są łączone za pomocą znaku kropki (.).

Token JWT składa się z tych elementów:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

Ciąg bazowy podpisu wygląda tak:

{Base64url encoded header}.{Base64url encoded claim set}
Tworzenie nagłówka JWT

Nagłówek składa się z 3 pól, które wskazują algorytm podpisywania, format asercji i [identyfikator klucza konta usługi](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys), który został użyty do podpisania tokena JWT. Algorytm i format są obowiązkowe, a każde pole ma tylko jedną wartość. W miarę wprowadzania kolejnych algorytmów i formatów ten nagłówek będzie się odpowiednio zmieniać. Identyfikator klucza jest opcjonalny. Jeśli podano nieprawidłowy identyfikator klucza, GCP spróbuje użyć wszystkich kluczy powiązanych z kontem usługi, aby zweryfikować token, i odrzuci go, jeśli nie znajdzie prawidłowego klucza. Google zastrzega sobie prawo do odrzucania w przyszłości tokenów z nieprawidłowymi identyfikatorami kluczy.

Konta usługi korzystają z algorytmu RSA SHA-256 i formatu tokena JWT. W rezultacie reprezentacja JSON nagłówka wygląda tak:

{"alg":"RS256","typ":"JWT", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}

Reprezentacja Base64url tego ciągu wygląda tak:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
Tworzenie zbioru deklaracji JWT

Zbiór deklaracji JWT zawiera informacje o tokenie JWT, w tym o żądanych uprawnieniach (zakresach), celu tokena, wystawcy, czasie wydania tokena i jego okresie ważności. Większość pól jest obowiązkowa. Podobnie jak nagłówek JWT, zbiór deklaracji JWT jest obiektem JSON i jest używany do obliczania podpisu.

Wymagane roszczenia

Poniżej znajdziesz wymagane dane w zbiorze danych JWT. Mogą one występować w dowolnej kolejności w zestawie roszczeń.

Nazwa Opis
iss Adres e-mail konta usługi.
scope Lista uprawnień, których żąda aplikacja, oddzielonych spacjami.
aud Opis docelowego odbiorcy asercji. Podczas wysyłania prośby o token dostępu ta wartość jest zawsze równa https://oauth2.googleapis.com/token.
exp Czas wygaśnięcia asercji podany w sekundach od godziny 00:00:00 czasu UTC 1 stycznia 1970 r. Maksymalna wartość to 1 godzina od czasu wydania.
iat Czas wydania asercji podany w sekundach od 00:00:00 UTC, 1 stycznia 1970 r.

Poniżej przedstawiono reprezentację JSON wymaganych pól w zbiorze deklaracji JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Dodatkowe roszczenia

W przypadku niektórych firm aplikacja może używać przekazywania dostępu w całej domenie, aby działać w imieniu konkretnego użytkownika w organizacji. Zanim aplikacja będzie mogła podszywać się pod użytkownika, musi otrzymać uprawnienie do tego typu podszywania się. Zwykle zajmuje się tym superadministrator. Więcej informacji znajdziesz w artykule Kontrola dostępu do interfejsów API przy użyciu przekazywania dostępu w całej domenie.

Aby uzyskać token dostępu, który przyznaje aplikacji przekazywany dostęp do zasobu, w zbiorze deklaracji JWT podaj adres e-mail użytkownika jako wartość pola sub.

Nazwa Opis
sub Adres e-mail użytkownika, w imieniu którego aplikacja prosi o delegowany dostęp.

Jeśli aplikacja nie ma uprawnień do odgrywania roli użytkownika, odpowiedź na żądanie tokena dostępu zawierające pole sub będzie błędem.

Przykład zbioru danych JWT zawierającego pole sub:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Kodowanie zbioru deklaracji JWT

Podobnie jak nagłówek JWT, zestaw deklaracji JWT powinien być serializowany do formatu UTF-8 i kodowany w formacie Base64url-safe. Poniżej znajdziesz przykład reprezentacji JSON zestawu roszczeń JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Obliczanie podpisu

Podpis internetowy JSON (JWS) to specyfikacja, która określa mechanizm generowania podpisu dla tokena JWT. Dane wejściowe podpisu to tablica bajtów zawierająca te treści:

{Base64url encoded header}.{Base64url encoded claim set}

Podczas obliczania podpisu należy użyć algorytmu podpisywania w nagłówku JWT. Jedynym algorytmem podpisywania obsługiwanym przez serwer autoryzacji Google OAuth 2.0 jest RSA z algorytmem haszowania SHA-256. Jest to wyrażone jako RS256 w polu alg w nagłówku tokena JWT.

Podpisz reprezentację danych wejściowych w kodowaniu UTF-8 za pomocą algorytmu SHA256withRSA (znanego też jako RSASSA-PKCS1-V1_5-SIGN z funkcją skrótu SHA-256) przy użyciu klucza prywatnego uzyskanego z  Google API Console. Dane wyjściowe będą tablicą bajtów.

Podpis musi być następnie zakodowany w formacie Base64url. Nagłówek, zestaw deklaracji i podpis są łączone za pomocą znaku kropki (.). Wynikiem jest JWT. Powinien on wyglądać tak (podziały wierszy dodane dla przejrzystości):

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

Poniżej znajdziesz przykład tokena JWT przed zakodowaniem w formacie Base64url:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

Oto przykład podpisanego tokena JWT gotowego do przesłania:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

Wysyłanie prośby o token dostępu

Po wygenerowaniu podpisanego tokena JWT aplikacja może go użyć do wysłania żądania tokena dostępu. To żądanie tokena dostępu jest żądaniem HTTPS POST, a jego treść jest zakodowana w formacie URL. Adres URL jest widoczny poniżej:

https://oauth2.googleapis.com/token

Żądanie HTTPS POST musi zawierać te parametry:

Nazwa Opis
grant_type Użyj tego ciągu znaków, w razie potrzeby zakodowanego w formacie URL:urn:ietf:params:oauth:grant-type:jwt-bearer
assertion Token JWT, w tym podpis.

Poniżej znajdziesz surowy zrzut żądania HTTPS POST użytego w żądaniu tokena dostępu:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

Poniżej znajdziesz to samo żądanie z użyciem curl:

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

Obsługa odpowiedzi

Jeśli token JWT i żądanie tokena dostępu są prawidłowo sformułowane, a konto usługi ma uprawnienia do wykonania operacji, odpowiedź JSON z serwera autoryzacji zawiera token dostępu. Oto przykładowa odpowiedź:

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

Tokeny dostępu można ponownie wykorzystywać w okresie określonym przez wartość expires_in.

Wywoływanie interfejsów API Google

Java

Aby wywołać interfejsy API Google, użyj obiektu GoogleCredentials, wykonując te czynności:

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać, używając obiektu GoogleCredentials. Na przykład:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credentials).build();
  2. Wysyłaj żądania do usługi API za pomocą interfejsu udostępnianego przez obiekt usługi. Aby na przykład wyświetlić listę instancji baz danych Cloud SQL w projekcie exciting-example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Aby wywołać interfejsy API Google, użyj autoryzowanego obiektu Credentials, wykonując te czynności:

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Obiekt usługi tworzy się przez wywołanie funkcji build z nazwą i wersją interfejsu API oraz autoryzowanym obiektem Credentials. Na przykład, aby wywołać wersję 1beta3 interfejsu Cloud SQL Administration API:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Wysyłaj żądania do usługi API za pomocą interfejsu udostępnianego przez obiekt usługi. Aby na przykład wyświetlić listę instancji baz danych Cloud SQL w projekcie exciting-example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

Gdy aplikacja uzyska token dostępu, może go używać do wywoływania interfejsu API Google w imieniu danego konta usługi lub konta użytkownika, jeśli przyznano zakresy dostępu wymagane przez interfejs API. Aby to zrobić, dołącz token dostępu do żądania wysyłanego do interfejsu API, uwzględniając parametr zapytania access_token lub wartość nagłówka HTTP AuthorizationBearer. W miarę możliwości preferowany jest nagłówek HTTP, ponieważ ciągi zapytań są zwykle widoczne w logach serwera. W większości przypadków możesz użyć biblioteki klienta, aby skonfigurować wywołania interfejsów API Google (np. podczas wywoływania interfejsu Drive Files API).

Wszystkie interfejsy API Google i ich zakresy możesz wypróbować w OAuth 2.0 Playground.

Przykłady żądań HTTP GET

Wywołanie punktu końcowego drive.files (interfejs 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

Możesz przetestować te polecenia za pomocą aplikacji wiersza poleceń curl. Oto przykład, w którym użyto opcji nagłówka HTTP (preferowanej):

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

Możesz też wybrać opcję parametru ciągu zapytania:

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

Wygaśnięcie tokenów dostępu

Tokeny dostępu wydawane przez serwer autoryzacji Google OAuth 2.0 wygasają po upływie czasu określonego przez wartość expires_in. Gdy token dostępu wygaśnie, aplikacja powinna wygenerować kolejny token JWT, podpisać go i poprosić o kolejny token dostępu.

Kody błędów JWT

error pole error_description pole Znaczenie Jak rozwiązać problem
unauthorized_client Unauthorized client or scope in request. Jeśli próbujesz użyć przekazywania dostępu w całej domenie, konto usługi nie jest autoryzowane w konsoli administracyjnej domeny użytkownika.

Sprawdź, czy konto usługi jest autoryzowane na stronie Przekazywanie dostępu w całej domenie w konsoli administracyjnej dla użytkownika w roszczeniu (polu) sub.

Zwykle zajmuje to kilka minut, ale zastosowanie autoryzacji na wszystkich kontach użytkowników na Twoim koncie Google może potrwać do 24 godzin.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. Konto usługi zostało autoryzowane w konsoli administracyjnej przy użyciu adresu e-mail klienta zamiast identyfikatora klienta (liczbowego). Na stronie Przekazywanie dostępu w całej domenie w konsoli administracyjnej usuń klienta i dodaj go ponownie, podając identyfikator numeryczny.
access_denied (dowolna wartość) Jeśli używasz przekazywania dostępu w całej domenie, co najmniej 1 z żądanych zakresów nie jest autoryzowany w konsoli administracyjnej.

Sprawdź, czy konto usługi jest autoryzowane na stronie Przekazywanie dostępu w całej domenie w konsoli administracyjnej dla użytkownika w deklaracji sub (pole) i czy zawiera wszystkie zakresy, o które prosisz w deklaracji scope w JWT.

Zwykle zajmuje to kilka minut, ale zastosowanie autoryzacji na wszystkich kontach użytkowników na Twoim koncie Google może potrwać do 24 godzin.

admin_policy_enforced (dowolna wartość) Konto Google nie może autoryzować co najmniej jednego z zakresów, o które prosisz, ze względu na zasady administratora Google Workspace.

Więcej informacji o tym, jak administrator może ograniczyć dostęp do wszystkich zakresów lub zakresów wrażliwych i ograniczonych, dopóki nie zostanie on wyraźnie przyznany identyfikatorowi klienta OAuth, znajdziesz w artykule pomocy dla administratorów Google Workspace Określanie, które aplikacje innych firm i aplikacje wewnętrzne mają dostęp do danych Google Workspace.

invalid_client (dowolna wartość)

Klient OAuth lub token JWT jest nieprawidłowy lub niepoprawnie skonfigurowany.

Szczegółowe informacje znajdziesz w opisie błędu.

Sprawdź, czy token JWT jest prawidłowy i zawiera poprawne deklaracje.

Sprawdź, czy klient OAuth i konto usługi są poprawnie skonfigurowane i czy używasz właściwego adresu e-mail.

Sprawdź, czy token JWT jest prawidłowy i czy został wydany dla identyfikatora klienta w żądaniu.

deleted_client (dowolna wartość)

Klient OAuth używany do wysyłania żądania został usunięty. Usuwanie może odbywać się ręcznie lub automatycznie w przypadku nieużywanych klientów . Usuniętych klientów można przywrócić w ciągu 30 dni od usunięcia. Więcej informacji

Użyj identyfikatora klienta, który jest nadal aktywny.

invalid_grant Not a valid email. Użytkownik nie istnieje. Sprawdź, czy adres e-mail w sub (polu) jest prawidłowy.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

Zwykle oznacza to, że czas systemowy na urządzeniu lokalnym jest nieprawidłowy. Może się to też zdarzyć, jeśli wartość exp jest o ponad 65 minut późniejsza niż wartość iat lub jeśli wartość exp jest mniejsza niż wartość iat.

Sprawdź, czy zegar w systemie, w którym generowany jest JWT, jest prawidłowy. W razie potrzeby zsynchronizuj czas z protokołem NTP Google.

invalid_grant Invalid JWT Signature.

Asercja JWT jest podpisana kluczem prywatnym, który nie jest powiązany z kontem usługi zidentyfikowanym przez adres e-mail klienta, lub użyty klucz został usunięty, wyłączony lub utracił ważność.

Alternatywnie asercja JWT może być nieprawidłowo zakodowana – musi być zakodowana w standardzie Base64, bez znaków nowego wiersza ani znaków równości dopełniających.

Zdekoduj zestaw roszczeń JWT i sprawdź, czy klucz, którym podpisano potwierdzenie, jest powiązany z kontem usługi.

Spróbuj użyć biblioteki OAuth udostępnionej przez Google, aby mieć pewność, że token JWT jest generowany prawidłowo.

invalid_scope Invalid OAuth scope or ID token audience provided. Nie zażądano żadnych zakresów (pusta lista zakresów) lub jeden z zażądanych zakresów nie istnieje (jest nieprawidłowy).

Sprawdź, czy roszczenie scope (pole) JWT jest wypełnione, i porównaj zakresy, które zawiera, z zakresami udokumentowanymi dla interfejsów API, których chcesz używać, aby upewnić się, że nie ma błędów ani literówek.

Pamiętaj, że lista zakresów w deklaracji scope musi być rozdzielona spacjami, a nie przecinkami.

disabled_client The OAuth client was disabled. Klucz użyty do podpisania asercji JWT jest wyłączony.

Otwórz Google API Consolei w sekcji Administracja > Konta usługi włącz konto usługi, które zawiera „Identyfikator klucza” użyty do podpisania asercji.

org_internal This client is restricted to users within its organization. Identyfikator klienta OAuth w żądaniu jest częścią projektu, który ogranicza dostęp do kont Google w określonej organizacji Google Cloud.

Uwierzytelnij się za pomocą konta usługi w organizacji. Potwierdź konfigurację typu użytkownika w przypadku aplikacji OAuth.

Dodatek: autoryzacja za pomocą konta usługi bez OAuth

W przypadku niektórych interfejsów API Google możesz wykonywać autoryzowane wywołania interfejsu API, używając podpisanego tokena JWT bezpośrednio jako tokena dostępu, a nie tokena dostępu OAuth 2.0. Jeśli jest to możliwe, możesz uniknąć wysyłania żądania sieciowego do serwera autoryzacji Google przed wykonaniem wywołania interfejsu API.

Jeśli interfejs API, którego chcesz użyć, ma definicję usługi opublikowaną w repozytorium interfejsów API Google w GitHub, możesz wykonywać autoryzowane wywołania interfejsu API za pomocą tokena JWT zamiast tokena dostępu. Aby to zrobić:

  1. Utwórz konto usługi zgodnie z opisem powyżej. Pamiętaj, aby zachować plik JSON, który otrzymasz podczas tworzenia konta.
  2. Korzystając z dowolnej standardowej biblioteki JWT, np. tej dostępnej na stronie jwt.io, utwórz token JWT z nagłówkiem i ładunkiem podobnym do tego w przykładzie poniżej:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • W polu kid w nagłówku podaj identyfikator klucza prywatnego konta usługi. Znajdziesz go w polu private_key_id pliku JSON konta usługi.
    • W polach isssub podaj adres e-mail konta usługi. Tę wartość znajdziesz w polu client_email pliku JSON konta usługi.
    • W polu aud podaj punkt końcowy interfejsu API. Na przykład: https://SERVICE.googleapis.com/.
    • W polu iat podaj bieżący czas w formacie Unix, a w polu exp podaj czas dokładnie 3600 sekund później, kiedy token JWT wygaśnie.

Podpisz token JWT za pomocą algorytmu RSA-256 przy użyciu klucza prywatnego znajdującego się w pliku JSON konta usługi.

Na przykład:

Java

Używanie google-auth-library-javajava-jwt:

import com.google.auth.oauth2.ServiceAccountCredentials;
...
GoogleCredentials credentials =
        GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = ((ServiceAccountCredentials) credentials).getPrivateKey();
String privateKeyId = ((ServiceAccountCredentials) credentials).getPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

Używanie PyJWT:

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. Wywołaj interfejs API, używając podpisanego tokena JWT jako tokena dostępu:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com

Wdrażanie Ochrony wszystkich kont

Dodatkowym krokiem, który należy podjąć w celu ochrony kont użytkowników, jest wdrożenie ochrony międzykontowej za pomocą usługi ochrony międzykontowej Google. 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. Na podstawie tych informacji możesz podejmować działania w zależności od tego, jak chcesz reagować na zdarzenia.

Oto kilka przykładów typów zdarzeń wysyłanych do Twojej aplikacji przez usługę ochrony kont Google:

  • 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 i pełną listę dostępnych zdarzeń znajdziesz na stronie Ochrona kont użytkowników za pomocą ochrony wszystkich kont .