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ą bezpośrednio udziału w tym procesie. Ten scenariusz jest czasami nazywany „2-etapowym OAuth” lub „2LO”. (Powiązany termin „trzyetapowa autoryzacja OAuth” odnosi się do scenariuszy, w których aplikacja wywołuje interfejsy API Google w imieniu użytkowników końcowych, a czasem wymaga zgody użytkownika).

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

Administratorzy domen Google Workspace mogą też przyznawać kontom usługi uprawnienia do dostępu do danych użytkowników w całej domenie w imieniu użytkowników w domenie.

W tym dokumencie opisano, jak aplikacja może ukończyć proces OAuth 2.0 serwer-serwer za pomocą biblioteki klienta interfejsów API Google (zalecane) lub HTTP.

Omówienie

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ż dostęp do całej domeny na konto usługi.

Następnie aplikacja przygotowuje się do autoryzowanego wywoływania interfejsu API, używając danych logowania na konto usługi do żądania tokena dostępu od serwera uwierzytelniania OAuth 2.0.

Aplikacja może używać 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 publicznych i prywatnych. 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 aplikacja działa w Google Compute Engine, konto usługi jest również konfigurowane automatycznie podczas tworzenia projektu, ale musisz określić zakresy, do których aplikacja musi mieć dostęp podczas tworzenia instancji Google Compute Engine. Więcej informacji znajdziesz w artykule Przygotowywanie instancji do korzystania z kont usługi.

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

First, create a service account:

  1. Open the Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. Click  Create service account.
  4. Under Service account details, type a name, ID, and description for the service account, then click Create and continue.
  5. Optional: Under Grant this service account access to project, select the IAM roles to grant to the service account.
  6. Click Continue.
  7. Optional: Under Grant users access to this service account, add the users or groups that are allowed to use and manage the service account.
  8. Click Done.

Next, create a service account key:

  1. Click the email address for the service account you created.
  2. Click the Keys tab.
  3. In the Add key drop-down list, select Create new key.
  4. Click Create.

Your new public/private key pair is generated and downloaded to your machine; it serves as the only copy of the private key. You are responsible for storing it securely. If you lose this key pair, you will need to generate a new one.

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

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

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

Za pomocą konta Google Workspace administrator Workspace w organizacji może autoryzować aplikację do uzyskiwania dostępu do danych użytkowników Workspace w imieniu użytkowników w domenie Google Workspace. Na przykład aplikacja, która używa interfejsu Calendar API do dodawania wydarzeń do kalendarzy wszystkich użytkowników w domenie Google Workspace, korzystałaby z konta usługi, aby uzyskać dostęp do interfejsu Calendar API w imieniu użytkowników. Autoryzowanie konta usługi do uzyskiwania dostępu do danych w imieniu użytkowników w domenie jest czasami nazywane „przekazaniem uprawnień w całej domenie” do konta usługi.

Aby delegować uprawnienia w całej domenie 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 panelu 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 sekcji Service accounts page.
  5. W polu Zakresy OAuth (rozdzielone przecinkami) wpisz listę zakresów, do których aplikacja ma mieć dostęp. Jeśli na przykład aplikacja potrzebuje w całej domenie pełnego dostępu 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.

Twoja aplikacja ma teraz uprawnienia do wywoływania interfejsów API jako użytkownicy w domenie Workspace (aby „udawać” użytkowników). Gdy przygotowujesz się do wykonania tych wywołań interfejsu API, musisz wyraźnie określić użytkownika, którego chcesz podszyć.

Przygotowanie do wywołania interfejsu API w ramach delegowania

Java

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

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

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

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

Przypisywanie uprawnień w całej domenie

Jeśli masz dostęp do konta usługi w obrębie całej domeny i chcesz podszyć się pod konto użytkownika, podaj adres e-mail tego konta za pomocą metody createDelegated obiektu GoogleCredential. Przykład:

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

Powyższy kod wywołuje metodę createDelegated() obiektu GoogleCredential. Argument metody createDelegated() musi być użytkownikiem należącym do Twojego konta Workspace. Twój kod przesyłający żądanie będzie używać tych danych logowania do wywoływania interfejsów API Google za pomocą konta usługi.

Python

Po uzyskaniu adresu e-mail klienta i klucza prywatnego z  API Consolewykonaj te czynności w bibliotece klienta interfejsów API Google dla języka Python:

  1. Utwórz obiekt Credentials na podstawie danych logowania konta usługi i zakresów, do których aplikacja musi mieć dostęp. 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 opracowujesz aplikację w Google Cloud Platform, możesz zamiast tego użyć domyślnych danych logowania aplikacji, co może uprościć proces.

  2. Przypisywanie uprawnień w całej domenie

    Jeśli masz dostęp do konta usługi w całej domenie i chcesz podszyć się pod konto użytkownika, użyj metody with_subject obiektu ServiceAccountCredentials. Na przykład:

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

Do wywoływania interfejsów API Google w aplikacji używaj obiektu Credentials.

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 jako „jot”), który zawiera nagłówek, zbiór deklaracji i podpis.
  2. Poproś o token dostępu na serwerze autoryzacji Google OAuth 2.0.
  3. Obsługa odpowiedzi JSON zwracanej przez serwer autoryzacji.

W kolejnych sekcjach znajdziesz instrukcje wykonywania tych czynności.

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

Gdy wygaśnie token dostępu, aplikacja wygeneruje kolejny token JWT, podpisze go i poprosi o kolejny token dostępu.

Aplikacja serwera używa tokena JWT, aby poprosić o token od serwera autoryzacji Google, a następnie używa tego tokena do wywołania punktu końcowego interfejsu Google API. Żaden użytkownik końcowy nie jest zaangażowany.

W pozostałej części tej sekcji opisujemy szczegółowo tworzenie tokena JWT, jego podpisywanie, tworzenie żądania tokena dostępu i obsługę 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 za pomocą kodowania Base64url. To kodowanie zapewnia odporność na zmiany kodowania spowodowane powtarzającymi się operacjami kodowania. Nagłówek, zbiór roszczeń i podpis są łączone ze sobą za pomocą znaku kropki (.).

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

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

Podstawowy ciąg znaków podpisu:

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

Nagłówek składa się z 3 pol, które wskazują algorytm podpisywania, format oświadczenia oraz [identyfikator klucza konta usługi](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys) użytego do podpisania JWT. Algorytm i format są wymagane, a każde pole ma tylko jedną wartość. Wraz z wprowadzaniem kolejnych algorytmów i formatów nagłówek ten będzie się odpowiednio zmieniał. Identyfikator klucza jest opcjonalny. Jeśli podany zostanie nieprawidłowy identyfikator klucza, GCP spróbuje użyć wszystkich kluczy powiązanych z kontem usługi, aby zweryfikować token, a następnie odrzuci go, jeśli nie znajdzie ważnego klucza. Google zastrzega sobie prawo do odrzucania tokenów z nieprawidłowymi identyfikatorami kluczy w przyszłości.

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

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

Reprezentacja w formacie Base64url wygląda tak:

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
Tworzenie zbioru deklaracji JWT

Zbiór deklaracji JWT zawiera informacje o tym, w tym o uprawnieniach, o które prosi (zakresy), o docelowym obiekcie tokena, jego wydawcy, czasie jego wydania oraz o czasie jego ważności. Większość pól jest wymaganych. Podobnie jak nagłówek JWT, zbiór deklaracji JWT jest obiektem JSON i służy do obliczania podpisu.

Wymagane roszczenia

Wymagane dane w zbiorze danych JWT przedstawiamy poniżej. Mogą one pojawiać się w dowolnej kolejności w zbiorze roszczeń.

Nazwa Opis
iss Adres e-mail konta usługi.
scope Oddzielona spacjami lista uprawnień, których żąda aplikacja.
aud Opis docelowego odbiorcy stwierdzenia. Podczas wysyłania żądania tokena dostępu ta wartość jest zawsze https://oauth2.googleapis.com/token.
exp Czas wygaśnięcia oświadczenia podany w sekundach od godziny 00:00:00 UTC 1 stycznia 1970 r. Ta wartość ma maksymalnie 1 godzinę po wydaniu.
iat Czas wydania oświadczenia 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 niektórych przypadkach aplikacja może działać w imieniu konkretnego użytkownika w organizacji, korzystając z przekazywania dostępu w całej domenie. Aby aplikacja mogła udawać użytkownika, musi mieć do tego uprawnienia. Zwykle przyznaje je 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 przyzna aplikacji delegowany dostęp do zasobu, uwzględnij adres e-mail użytkownika w zbiorze deklaracji JWT jako wartość pola sub.

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

Jeśli aplikacja nie ma uprawnień do podszywania się pod użytkownika, odpowiedź na żądanie tokena dostępu, które zawiera pole sub, będzie zawierać błąd.

Poniżej znajduje się przykład zestawu danych JWT, który zawiera 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 roszczeń JWT

Podobnie jak nagłówek JWT, zbiór deklaracji JWT powinien być serializowany w formacie UTF-8 i zakodowany w formacie Base64url. Poniżej znajduje się przykład reprezentacji w formacie JSON zbioru 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 do 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 Google do autoryzacji OAuth 2.0 jest algorytm RSA z wykorzystaniem algorytmu haszowania SHA-256. Jest on wyrażony jako RS256 w polu alg nagłówka JWT.

Podpisz reprezentacje UTF-8 za pomocą SHA256withRSA (znanej też jako RSASSA-PKCS1-V1_5-SIGN z funkcją skrótu SHA-256) za pomocą klucza prywatnego uzyskanego z  Google API Console. Dane wyjściowe będą miały postać tablicy bajtów.

Podpis musi być zakodowany w formacie Base64url. Nagłówek, zbiór roszczeń i podpis są łączone ze sobą za pomocą znaku kropki (.). Wynikiem jest token JWT. Powinno ono wyglądać tak (przerwy między wierszami zostały dodane w celu ułatwienia odczytu):

{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, który jest gotowy do przesłania:

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

Przesyłanie żądania tokena 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 to żądanie POST w protokole HTTPS, a treść jest zakodowana w adresie URL. Adres URL:

https://oauth2.googleapis.com/token

W żądaniu POST w protokole HTTPS wymagane są te parametry:

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

Oto surowy zrzut żądania HTTPS POST używanego 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

Oto to samo żądanie z użyciem parametru 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 internetowy 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ład odpowiedzi:

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

Tokenów dostępu można używać ponownie w okresie określonym przez wartość parametru expires_in.

Wywoływanie interfejsów API Google

Java

Aby wywołać interfejsy API Google, użyj obiektu GoogleCredential. Aby to zrobić:

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać, za pomocą obiektu GoogleCredential. Na przykład:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. Wysyłać żądania do usługi interfejsu API za pomocą interfejsu udostępnionego 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ływać interfejsy API Google za pomocą autoryzowanego obiektu Credentials, wykonaj te czynności:

  1. Utwórz obiekt usługi dla interfejsu API, który chcesz wywołać. Obiekt usługi tworzysz, wywołując funkcję build z nazwą i wersją interfejsu API oraz autoryzowanym obiektem Credentials. Aby na przykład wywołać wersję 1beta3 interfejsu Cloud SQL Administration API:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Wysyłać żądania do usługi interfejsu API za pomocą interfejsu udostępnionego 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żesz go użyć do wywoływania interfejsów API Google w imieniu danego konta usługi lub konta użytkownika, jeśli przyznano uprawnienia 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

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ść parametru 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

Pole error Pole error_description Znaczenie Rozwiązanie
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.

Upewnij się, że konto usługi ma uprawnienia na stronie Przekazywanie dostępu w całej domenie w konsoli administracyjnej dla użytkownika w twierdzeniu (polu) sub.

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

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 za pomocą adresu e-mail klienta, a nie identyfikatora klienta (liczbowego). W konsoli administracyjnej na stronie Przekazywanie dostępu w całej domenie usuń klienta i dodaj go ponownie, podając jego identyfikator numeryczny.
access_denied (dowolna wartość) Jeśli używasz delegowania uprawnień w całej domenie, co najmniej 1 z żądanych zakresów nie jest autoryzowany w konsoli administracyjnej.

Upewnij się, że konto usługi ma uprawnienia na stronie Przekazywanie dostępu w całej domenie w konsoli administracyjnej dla użytkownika w elemencie sub (pole) i że obejmuje ona wszystkie zakresy, o które prosisz w elemencie scope w pliku JWT.

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

admin_policy_enforced (dowolna wartość) Konto Google nie może autoryzować co najmniej 1 wymaganego zakresu 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 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 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 albo źle skonfigurowany.

Szczegóły znajdziesz w opisie błędu.

Upewnij się, że token JWT jest prawidłowy i zawiera prawidłowe oświadczenia.

Sprawdź, czy klient OAuth i konto usługi są prawidłowo skonfigurowane oraz czy używasz prawidłowego adresu e-mail.

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

invalid_grant Not a valid email. Użytkownik nie istnieje. Sprawdź, czy adres e-mail w pliku sub claim (pole) 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 lokalny czas systemowy jest nieprawidłowy. Może się to też zdarzyć, jeśli wartość exp jest o więcej niż 65 minut w przyszłości od wartości iat, lub jeśli wartość exp jest niższa od wartości iat.

Upewnij się, że zegar w systemie, w którym generowany jest JWT, wskazuje prawidłową godzinę. W razie potrzeby zsynchronizuj czas z serwerem NTP Google.

invalid_grant Invalid JWT Signature.

Oświadczenie JWT jest podpisane kluczem prywatnym, który nie jest powiązany z kontem usługi zidentyfikowanym przez adres e-mail klienta, lub klucz, który został użyty, został usunięty, wyłączony lub wygasł.

Innym powodem może być nieprawidłowe zakodowanie oświadczenia JWT – musi ono być zakodowane w formacie Base64 bez znaków nowej linii ani znaków wypełnienia.

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

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

invalid_scope Invalid OAuth scope or ID token audience provided. Żadne zakresy nie zostały zażądane (pusta lista zakresów) lub jeden z żądanych zakresów nie istnieje (czyli jest nieprawidłowy).

Upewnij się, że w pliku JWT jest wypełnione pole scope, i porównaj zakresy, które zawiera, z dokumentowanymi zakresami 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ć rozdzielana spacjami, a nie przecinkami.

disabled_client The OAuth client was disabled. Klucz używany do podpisywania oświadczenia JWT jest wyłączony.

Otwórz stronę Google API Consolei w sekcji Administracja > Konta usługi włącz konto usługi zawierające „identyfikator klucza” używany do podpisywania oświadczenia.

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.

Użyj konta usługi organizacji do uwierzytelnienia. Potwierdź konfigurację typu użytkownika w 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 JWT bezpośrednio jako tokena bezwzględnego, a nie tokena dostępu OAuth 2.0. Jeśli to możliwe, możesz uniknąć wysyłania żądania sieci do serwera autoryzacji Google przed wykonaniem wywołania interfejsu API.

Jeśli interfejs API, do którego chcesz się odwołać, ma definicję usługi opublikowaną w repertuarze interfejsów Google w GitHub, możesz wykonywać autoryzowane wywołania interfejsu API, używając tokena JWT zamiast tokena dostępu. Aby to zrobić:

  1. Utwórz konto usługi, jak opisano powyżej. Zachowaj plik JSON otrzymany podczas tworzenia konta.
  2. Za pomocą dowolnej standardowej biblioteki JWT, takiej jak ta dostępna na stronie jwt.io, utwórz token JWT z nagłówkiem i ładunkiem podobnym do tego:
    {
      "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 ją w polu private_key_id w pliku JSON konta usługi.
    • W polach isssub wpisz adres e-mail konta usługi. Znajdziesz ją w polu client_email w pliku JSON konta usługi.
    • W polu aud określ punkt końcowy interfejsu API. Przykład: https://SERVICE.googleapis.com/.
    • W polu iat podaj bieżący czas Unixa, a w polu exp – czas dokładnie 3600 sekund później, kiedy token JWT wygaśnie.

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

Na przykład:

Java

Korzystając z biblioteki google-api-java-clientjava-jwt:

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

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

Za pomocą pakietu 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 noszącego:
    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 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 .