Ochrona kont użytkowników za pomocą Ochrony wszystkich kont

Jeśli Twoja aplikacja umożliwia użytkownikom logowanie się na konta za pomocą Google, możesz zwiększyć bezpieczeństwo kont tych użytkowników, odbierając powiadomienia o zdarzeniach związanych z bezpieczeństwem dostarczane przez usługę Ochrona wszystkich kont i reagując na nie.

Te powiadomienia informują o poważnych zmianach na kontach Google użytkowników, które często mogą mieć wpływ na bezpieczeństwo ich kont w Twojej aplikacji. Jeśli na przykład konto Google użytkownika zostanie przejęte, może to doprowadzić do naruszenia bezpieczeństwa jego konta w Twojej aplikacji przez odzyskanie konta e-mail lub użycie logowania jednokrotnego.

Aby pomóc Ci zmniejszyć potencjalne ryzyko związane z takimi zdarzeniami, Google wysyła do Twojej usługi obiekty nazywane tokenami zdarzeń związanych z bezpieczeństwem. Te tokeny zawierają bardzo mało informacji – tylko typ zdarzenia związanego z bezpieczeństwem, czas jego wystąpienia i identyfikator użytkownika, którego dotyczy – ale możesz ich użyć, aby podjąć odpowiednie działania. Jeśli na przykład konto Google użytkownika zostanie przejęte, możesz tymczasowo wyłączyć funkcję Zaloguj się przez Google dla tego użytkownika i uniemożliwić wysyłanie e-maili dotyczących odzyskiwania konta na adres Gmail użytkownika.

Ochrona wszystkich kont jest oparta na standardzie RISC opracowanym przez OpenID Foundation.

Przegląd

Aby korzystać z Ochrony wszystkich kont w aplikacji lub usłudze, musisz wykonać te czynności:

  1. Skonfiguruj projekt w Konsoli interfejsów API.

  2. Utwórz punkt końcowy odbiornika zdarzeń, do którego Google będzie wysyłać tokeny zdarzeń związanych z bezpieczeństwem. Ten punkt końcowy odpowiada za sprawdzanie poprawności otrzymywanych tokenów, a następnie reagowanie na zdarzenia związane z bezpieczeństwem w wybrany przez Ciebie sposób.

  3. Zarejestruj swój punkt końcowy w Google, aby zacząć otrzymywać tokeny zdarzeń związanych z bezpieczeństwem.

Warunek wstępny

Tokeny zdarzeń związanych z bezpieczeństwem otrzymujesz tylko w przypadku użytkowników Google, którzy zezwolili Twojej usłudze na dostęp do informacji o ich profilu lub adresów e-mail. To uprawnienie uzyskasz, prosząc o zakresy profile lub email. Nowsze pakiety SDK Zaloguj się przez Google lub starsze pakiety SDK Logowanie przez Google domyślnie żądają tych zakresów, ale jeśli nie używasz ustawień domyślnych lub uzyskujesz dostęp bezpośrednio do punktu końcowego OpenID Connect Google, upewnij się, że żądasz co najmniej jednego z tych zakresów.

Konfigurowanie projektu w Konsoli interfejsów API

Zanim zaczniesz otrzymywać tokeny zdarzeń związanych z bezpieczeństwem, musisz utworzyć konto usługi i włączyć interfejs RISC API w projekcie w Konsoli interfejsów API. Musisz użyć tego samego projektu w Konsoli interfejsów API, którego używasz do uzyskiwania dostępu do usług Google, takich jak logowanie przez Google, w swojej aplikacji.

Aby utworzyć konto usługi:

  1. Otwórz stronę Dane logowania w konsoli interfejsów API. Gdy pojawi się prośba, wybierz projekt w Konsoli interfejsów API, którego używasz do uzyskiwania dostępu do usług Google w aplikacji.

  2. Kliknij Utwórz dane logowania > Konto usługi.

  3. Utwórz nowe konto usługi z rolą Administrator konfiguracji RISC (roles/riscconfigs.admin), postępując zgodnie z tymi instrukcjami.

  4. (Opcjonalnie) Jeśli Twoja organizacja Google Cloud zezwala na tworzenie kluczy kont usługi i planujesz podpisywać tokeny JWT lokalnie, utwórz klucz dla nowo utworzonego konta usługi. Wybierz typ klucza JSON, a następnie kliknij Utwórz. Po utworzeniu klucza pobierzesz plik JSON zawierający dane logowania do konta usługi. Zapisz ten plik w bezpiecznym miejscu, ale też dostępnym dla punktu końcowego odbiornika zdarzeń.

Na stronie Dane logowania projektu zanotuj też identyfikatory klienta, których używasz do funkcji Zaloguj się przez Google lub Logowanie przez Google (starsza wersja). Zwykle masz identyfikator klienta dla każdej obsługiwanej platformy. Te identyfikatory klienta będą potrzebne do weryfikacji tokenów zdarzeń związanych z bezpieczeństwem, jak opisano w następnej sekcji.

Aby włączyć interfejs RISC API:

  1. Otwórz stronę RISC API w Konsoli interfejsów API. Sprawdź, czy projekt, którego używasz do uzyskiwania dostępu do usług Google, jest nadal wybrany.

  2. Przeczytaj Warunki RISC i upewnij się, że rozumiesz wymagania.

    Jeśli włączasz interfejs API w projekcie należącym do organizacji, upewnij się, że masz uprawnienia do powiązania organizacji z Warunkami RISC.

  3. Kliknij Włącz tylko wtedy, gdy akceptujesz warunki RISC.

Tworzenie punktu końcowego odbiornika zdarzeń

Aby otrzymywać od Google powiadomienia o zdarzeniach związanych z bezpieczeństwem, utwórz punkt końcowy HTTPS, który obsługuje żądania HTTPS POST. Po zarejestrowaniu tego punktu końcowego (patrz poniżej) Google zacznie wysyłać do niego kryptograficznie podpisane ciągi znaków, zwane tokenami zdarzeń związanych z bezpieczeństwem. Tokeny zdarzeń związanych z bezpieczeństwem to podpisane tokeny JWT, które zawierają informacje o pojedynczym zdarzeniu związanym z bezpieczeństwem.

W przypadku każdego tokena zdarzenia związanego z bezpieczeństwem, który otrzymasz w punkcie końcowym, najpierw sprawdź i zdekoduj token, a następnie obsłuż zdarzenie związane z bezpieczeństwem w sposób odpowiedni dla Twojej usługi. Aby zapobiec złośliwym atakom, koniecznie sprawdź token zdarzenia przed jego zdekodowaniem. W sekcjach poniżej opisujemy te zadania:

1. Dekodowanie i weryfikowanie tokena zdarzenia związanego z bezpieczeństwem

Tokeny zdarzeń związanych z bezpieczeństwem są szczególnym rodzajem tokenów JWT, więc do ich dekodowania i weryfikowania możesz używać dowolnej biblioteki JWT, np. jednej z wymienionych na stronie jwt.io. Niezależnie od tego, której biblioteki używasz, kod weryfikacji tokena musi:

  1. Pobierz identyfikator wydawcy ochrony wszystkich kont (issuer) i identyfikator URI certyfikatu klucza podpisu (jwks_uri) z dokumentu konfiguracji RISC Google, który znajdziesz na stronie https://accounts.google.com/.well-known/risc-configuration.
  2. Za pomocą wybranej biblioteki JWT pobierz identyfikator klucza podpisywania z nagłówka tokena zdarzenia związanego z bezpieczeństwem.
  3. Z dokumentu certyfikatu klucza podpisywania Google pobierz klucz publiczny z identyfikatorem klucza uzyskanym w poprzednim kroku. Jeśli dokument nie zawiera klucza z identyfikatorem, którego szukasz, prawdopodobnie token zdarzenia związanego z bezpieczeństwem jest nieprawidłowy, a punkt końcowy powinien zwrócić błąd HTTP 400.
  4. Za pomocą wybranej biblioteki JWT sprawdź te elementy:
    • Token zdarzenia związanego z bezpieczeństwem jest podpisany kluczem publicznym uzyskanym w poprzednim kroku.
    • Deklaracja aud tokena jest jednym z identyfikatorów klienta Twoich aplikacji.
    • Twierdzenie iss tokena jest zgodne z identyfikatorem wydawcy uzyskanym z dokumentu opisującego RISC Discovery. Pamiętaj, że nie musisz sprawdzać daty ważności tokena (exp), ponieważ tokeny zdarzeń związanych z bezpieczeństwem reprezentują zdarzenia historyczne i jako takie nie wygasają.

Na przykład:

Java

Korzystanie z java-jwt i jwks-rsa-java:

public DecodedJWT validateSecurityEventToken(String token) {
    DecodedJWT jwt = null;
    try {
        // In a real implementation, get these values from
        // https://accounts.google.com/.well-known/risc-configuration
        String issuer = "accounts.google.com";
        String jwksUri = "https://www.googleapis.com/oauth2/v3/certs";

        // Get the ID of the key used to sign the token.
        DecodedJWT unverifiedJwt = JWT.decode(token);
        String keyId = unverifiedJwt.getKeyId();

        // Get the public key from Google.
        JwkProvider googleCerts = new UrlJwkProvider(new URL(jwksUri), null, null);
        PublicKey publicKey = googleCerts.get(keyId).getPublicKey();

        // Verify and decode the token.
        Algorithm rsa = Algorithm.RSA256((RSAPublicKey) publicKey, null);
        JWTVerifier verifier = JWT.require(rsa)
                .withIssuer(issuer)
                // Get your apps' client IDs from the API console:
                // https://console.developers.google.com/apis/credentials?project=_
                .withAudience("123456789-abcedfgh.apps.googleusercontent.com",
                              "123456789-ijklmnop.apps.googleusercontent.com",
                              "123456789-qrstuvwx.apps.googleusercontent.com")
                .acceptLeeway(Long.MAX_VALUE)  // Don't check for expiration.
                .build();
        jwt = verifier.verify(token);
    } catch (JwkException e) {
        // Key not found. Return HTTP 400.
    } catch (InvalidClaimException e) {

    } catch (JWTDecodeException exception) {
        // Malformed token. Return HTTP 400.
    } catch (MalformedURLException e) {
        // Invalid JWKS URI.
    }
    return jwt;
}

Python

import json
import jwt       # pip install pyjwt
import requests  # pip install requests

def validate_security_token(token, client_ids):
    # Get Google's RISC configuration.
    risc_config_uri = 'https://accounts.google.com/.well-known/risc-configuration'
    risc_config = requests.get(risc_config_uri).json()

    # Get the public key used to sign the token.
    google_certs = requests.get(risc_config['jwks_uri']).json()
    jwt_header = jwt.get_unverified_header(token)
    key_id = jwt_header['kid']
    public_key = None
    for key in google_certs['keys']:
        if key['kid'] == key_id:
            public_key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(key))
    if not public_key:
        raise Exception('Public key certificate not found.')
        # In this situation, return HTTP 400

    # Decode the token, validating its signature, audience, and issuer.
    try:
        token_data = jwt.decode(token, public_key, algorithms='RS256',
                                options={'verify_exp': False},
                                audience=client_ids, issuer=risc_config['issuer'])
    except:
        raise
        # Validation failed. Return HTTP 400.
    return token_data

# Get your apps' client IDs from the API console:
# https://console.developers.google.com/apis/credentials?project=_
client_ids = ['123456789-abcedfgh.apps.googleusercontent.com',
              '123456789-ijklmnop.apps.googleusercontent.com',
              '123456789-qrstuvwx.apps.googleusercontent.com']
token_data = validate_security_token(token, client_ids)

Jeśli token jest prawidłowy i został pomyślnie zdekodowany, zwróć stan HTTP 202. Następnie zajmij się zdarzeniem związanym z bezpieczeństwem wskazanym przez token.

2. Obsługa zdarzeń związanych z bezpieczeństwem

Po zdekodowaniu token zdarzenia związanego z bezpieczeństwem wygląda tak jak w tym przykładzie:

{
  "iss": "https://accounts.google.com/",
  "aud": "123456789-abcedfgh.apps.googleusercontent.com",
  "iat": 1508184845,
  "jti": "756E69717565206964656E746966696572",
  "events": {
    "https://schemas.openid.net/secevent/risc/event-type/account-disabled": {
      "subject": {
        "subject_type": "iss-sub",
        "iss": "https://accounts.google.com/",
        "sub": "7375626A656374"
      },
      "reason": "hijacking"
    }
  }
}

Twierdzenia iss i aud wskazują wystawcę tokena (Google) i jego zamierzonego odbiorcę (Twoją usługę). Te oświadczenia zostały zweryfikowane w poprzednim kroku.

Twierdzenie jti to ciąg znaków, który identyfikuje pojedyncze zdarzenie związane z bezpieczeństwem i jest unikalny dla strumienia. Możesz używać tego identyfikatora do śledzenia otrzymanych zdarzeń związanych z bezpieczeństwem.

Twierdzenie events zawiera informacje o zdarzeniu związanym z bezpieczeństwem, które reprezentuje token. To oświadczenie jest mapowaniem identyfikatora typu zdarzenia na oświadczenie subject, które określa użytkownika, którego dotyczy to zdarzenie, oraz wszelkie dodatkowe szczegóły dotyczące zdarzenia, które mogą być dostępne.

Deklaracja subject identyfikuje konkretnego użytkownika za pomocą unikalnego identyfikatora konta Google (sub). Ten identyfikator konta Google jest taki sam jak identyfikator (sub) zawarty w tokenach identyfikacji JWT wydawanych przez nowszą bibliotekę Zaloguj się przez Google (JavaScript, HTML), starszą bibliotekę Logowanie przez Google lub OpenID Connect. Jeśli pole subject_type roszczenia ma wartość id_token_claims, może ono również zawierać pole email z adresem e-mail użytkownika.

Użyj informacji z deklaracji events, aby podjąć odpowiednie działania w przypadku danego typu zdarzenia na koncie określonego użytkownika.

Identyfikatory tokenów OAuth

W przypadku zdarzeń OAuth dotyczących poszczególnych tokenów typ identyfikatora token subject zawiera te pola:

  • token_type: obsługiwana jest tylko wartość refresh_token.

  • token_identifier_alg: możliwe wartości znajdziesz w tabeli poniżej.

  • token: patrz tabela poniżej.

token_identifier_alg token
prefix Pierwsze 16 znaków tokena.
hash_base64_sha512_sha512 Podwójny skrót tokena przy użyciu SHA-512.

Jeśli integrujesz się z tymi zdarzeniami, zalecamy indeksowanie tokenów na podstawie tych możliwych wartości, aby zapewnić szybkie dopasowanie po otrzymaniu zdarzenia.

Obsługiwane rodzaje zdarzeń

Ochrona wszystkich kont obsługuje te typy zdarzeń związanych z bezpieczeństwem:

Typ zdarzenia Atrybuty Jak odpowiedzieć
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked Wymagane: ponownie zabezpiecz konto użytkownika, kończąc jego aktualnie otwarte sesje.
https://schemas.openid.net/secevent/oauth/event-type/tokens-revoked

Wymagane: jeśli token jest przeznaczony do logowania się przez Google, zakończ obecnie otwarte sesje użytkownika. Możesz też zasugerować użytkownikowi skonfigurowanie alternatywnej metody logowania.

Sugerowane: jeśli token służy do uzyskiwania dostępu do innych interfejsów API Google, usuń wszystkie przechowywane tokeny OAuth użytkownika.

https://schemas.openid.net/secevent/oauth/event-type/token-revoked Identyfikatory tokenów znajdziesz w sekcji Identyfikatory tokenów OAuth.

Wymagane: jeśli przechowujesz odpowiedni token odświeżania, usuń go i poproś użytkownika o ponowne wyrażenie zgody, gdy następnym razem będzie potrzebny token dostępu.

https://schemas.openid.net/secevent/risc/event-type/account-disabled reason=hijacking,
reason=bulk-account

Wymagane: jeśli konto zostało wyłączone z powodu hijacking, ponownie zabezpiecz konto użytkownika, kończąc jego aktualnie otwarte sesje.

Sugerowane: jeśli konto zostało wyłączone z powodu bulk-account, przeanalizuj aktywność użytkownika w Twojej usłudze i określ odpowiednie działania.

Sugerowane: jeśli nie podano powodu, wyłącz Logowanie przez Google dla użytkownika i wyłącz odzyskiwanie konta przy użyciu adresu e-mail powiązanego z kontem Google użytkownika (zwykle, ale nie zawsze, jest to konto Gmail). Zaproponuj użytkownikowi alternatywną metodę logowania.

https://schemas.openid.net/secevent/risc/event-type/account-enabled Sugerowane: ponownie włącz logowanie przez Google dla użytkownika i ponownie włącz odzyskiwanie konta za pomocą adresu e-mail konta Google użytkownika.
https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required Sugerowane: zwracaj uwagę na podejrzaną aktywność w usłudze i podejmuj odpowiednie działania.
https://schemas.openid.net/secevent/risc/event-type/verification state=state Sugerowane: zapisz, że otrzymano token testowy.

Zduplikowane i pominięte zdarzenia

Ochrona wszystkich kont będzie próbowała ponownie dostarczyć zdarzenia, które według niej nie zostały dostarczone. Dlatego czasami możesz otrzymać to samo zdarzenie kilka razy. Jeśli może to spowodować powtarzanie działań, które są uciążliwe dla użytkowników, rozważ użycie deklaracji jti (która jest unikalnym identyfikatorem zdarzenia) do usuwania duplikatów zdarzeń. Istnieją narzędzia zewnętrzne, takie jak Google Cloud Dataflow, które mogą pomóc w wykonaniu przepływu danych de-dup.

Pamiętaj, że zdarzenia są dostarczane z ograniczoną liczbą ponownych prób, więc jeśli odbiornik nie działa przez dłuższy czas, możesz trwale utracić niektóre zdarzenia.

Rejestrowanie odbiornika

Aby zacząć otrzymywać zdarzenia związane z bezpieczeństwem, zarejestruj punkt końcowy odbiorcy za pomocą interfejsu RISC API. Wywołania interfejsu RISC API muszą zawierać token autoryzacji.

Będziesz otrzymywać zdarzenia związane z bezpieczeństwem tylko w przypadku użytkowników Twojej aplikacji, dlatego musisz mieć skonfigurowany ekran zgody OAuth w projekcie GCP, aby wykonać opisane poniżej czynności.

1. Generowanie tokena autoryzacji

Token autoryzacji dla interfejsu RISC API możesz wygenerować za pomocą Google Cloud CLI (gcloud) z przyjęciem tożsamości konta usługi (zalecane, gdy wymuszane jest użycie iam.disableServiceAccountKeyCreation lub w przypadku jednorazowej konfiguracji interfejsu wiersza poleceń) lub przez podpisanie JWT lokalnie za pomocą klucza prywatnego konta usługi.

Opcja A. Wygeneruj krótkotrwały token dostępu za pomocą gcloud (klucz JSON nie jest wymagany)

Jeśli Twoje konto użytkownika ma rolę Twórca tokenów konta usługi (roles/iam.serviceAccountTokenCreator) na koncie usługi, możesz wygenerować krótkotrwały token dostępu OAuth 2.0 z wymaganym zakresem konfiguracji RISC bezpośrednio z terminala:

AUTH_TOKEN=$(gcloud auth print-access-token \
  --impersonate-service-account=SERVICE_ACCOUNT_EMAIL \
  --scopes=https://www.googleapis.com/auth/risc.configuration.readwrite,https://www.googleapis.com/auth/risc.verify,https://www.googleapis.com/auth/risc.status.readwrite)

Więcej informacji o dostępnych zakresach protokołu OAuth 2.0 dla interfejsu RISC API znajdziesz w artykule Zakresy tokenów dostępu.

Opcja B. Tworzenie podpisanego samodzielnie tokena JWT za pomocą klucza konta usługi

Możesz też wygenerować token autoryzacji lokalnie bez konieczności przesyłania danych przez sieć. W tym celu utwórz token JWT z tymi oświadczeniami:

{
  "iss": SERVICE_ACCOUNT_EMAIL,
  "sub": SERVICE_ACCOUNT_EMAIL,
  "aud": "https://risc.googleapis.com/google.identity.risc.v1beta.RiscManagementService",
  "iat": CURRENT_TIME,
  "exp": CURRENT_TIME + 3600
}

Podpisz token JWT za pomocą klucza prywatnego konta usługi, który znajdziesz w pliku JSON pobranym podczas tworzenia klucza konta usługi.

Na przykład:

Java

Za pomocą java-jwt i biblioteki uwierzytelniania Google:

public static String makeBearerToken() {
    String token = null;
    try {
        // Get signing key and client email address.
        FileInputStream is = new FileInputStream("your-service-account-credentials.json");
        ServiceAccountCredentials credentials =
               (ServiceAccountCredentials) GoogleCredentials.fromStream(is);
        PrivateKey privateKey = credentials.getPrivateKey();
        String keyId = credentials.getPrivateKeyId();
        String clientEmail = credentials.getClientEmail();

        // Token must expire in exactly one hour.
        Date issuedAt = new Date();
        Date expiresAt = new Date(issuedAt.getTime() + 3600000);

        // Create signed token.
        Algorithm rsaKey = Algorithm.RSA256(null, (RSAPrivateKey) privateKey);
        token = JWT.create()
                .withIssuer(clientEmail)
                .withSubject(clientEmail)
                .withAudience("https://risc.googleapis.com/google.identity.risc.v1beta.RiscManagementService")
                .withIssuedAt(issuedAt)
                .withExpiresAt(expiresAt)
                .withKeyId(keyId)
                .sign(rsaKey);
    } catch (ClassCastException e) {
        // Credentials file doesn't contain a service account key.
    } catch (IOException e) {
        // Credentials file couldn't be loaded.
    }
    return token;
}

Python

import json
import time

import jwt  # pip install pyjwt

def make_bearer_token(credentials_file):
    with open(credentials_file) as service_json:
        service_account = json.load(service_json)
        issuer = service_account['client_email']
        subject = service_account['client_email']
        private_key_id = service_account['private_key_id']
        private_key = service_account['private_key']
    issued_at = int(time.time())
    expires_at = issued_at + 3600
    payload = {'iss': issuer,
               'sub': subject,
               'aud': 'https://risc.googleapis.com/google.identity.risc.v1beta.RiscManagementService',
               'iat': issued_at,
               'exp': expires_at}
    encoded = jwt.encode(payload, private_key, algorithm='RS256',
                         headers={'kid': private_key_id})
    return encoded

auth_token = make_bearer_token('your-service-account-credentials.json')

Ten token autoryzacji może być używany do wywoływania interfejsu RISC API przez godzinę. Gdy token wygaśnie, wygeneruj nowy, aby nadal wywoływać interfejs API RISC.

2. Wywoływanie interfejsu API konfiguracji strumienia RISC

Mając token autoryzacji, możesz użyć interfejsu RISC API do skonfigurowania strumienia zdarzeń związanych z bezpieczeństwem w projekcie, w tym do zarejestrowania punktu końcowego odbiorcy.

Aby to zrobić, wyślij żądanie HTTPS POST na adres https://risc.googleapis.com/v1beta/stream:update, podając punkt końcowy odbiorcy i typy zdarzeń związanych z bezpieczeństwem, które Cię interesują:

POST /v1beta/stream:update HTTP/1.1
Host: risc.googleapis.com
Authorization: Bearer AUTH_TOKEN

{
  "delivery": {
    "delivery_method":
      "https://schemas.openid.net/secevent/risc/delivery-method/push",
    "url": RECEIVER_ENDPOINT
  },
  "events_requested": [
    SECURITY_EVENT_TYPES
  ]
}

Na przykład:

Java

public static void configureEventStream(final String receiverEndpoint,
                                        final List<String> eventsRequested,
                                        String authToken) throws IOException {
    ObjectMapper jsonMapper = new ObjectMapper();
    String streamConfig = jsonMapper.writeValueAsString(new Object() {
        public Object delivery = new Object() {
            public String delivery_method =
                    "https://schemas.openid.net/secevent/risc/delivery-method/push";
            public String url = receiverEndpoint;
        };
        public List<String> events_requested = eventsRequested;
    });

    HttpPost updateRequest = new HttpPost("https://risc.googleapis.com/v1beta/stream:update");
    updateRequest.addHeader("Content-Type", "application/json");
    updateRequest.addHeader("Authorization", "Bearer " + authToken);
    updateRequest.setEntity(new StringEntity(streamConfig));

    HttpResponse updateResponse = new DefaultHttpClient().execute(updateRequest);
    Header[] responseContentTypeHeaders = updateResponse.getHeaders("Content-Type");
    StatusLine responseStatus = updateResponse.getStatusLine();
    int statusCode = responseStatus.getStatusCode();
    HttpEntity entity = updateResponse.getEntity();
    // Now handle response
}

// ...

configureEventStream(
        "https://your-service.example.com/security-event-receiver",
        Arrays.asList(
                "https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required",
                "https://schemas.openid.net/secevent/risc/event-type/account-disabled"),
        authToken);

Python

import requests

def configure_event_stream(auth_token, receiver_endpoint, events_requested):
    stream_update_endpoint = 'https://risc.googleapis.com/v1beta/stream:update'
    headers = {'Authorization': 'Bearer {}'.format(auth_token)}
    stream_cfg = {'delivery': {'delivery_method': 'https://schemas.openid.net/secevent/risc/delivery-method/push',
                               'url': receiver_endpoint},
                  'events_requested': events_requested}
    response = requests.post(stream_update_endpoint, json=stream_cfg, headers=headers)
    response.raise_for_status()  # Raise exception for unsuccessful requests

configure_event_stream(auth_token, 'https://your-service.example.com/security-event-receiver',
                       ['https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required',
                        'https://schemas.openid.net/secevent/risc/event-type/account-disabled'])

Jeśli żądanie zwróci kod HTTP 200, strumień zdarzeń został skonfigurowany prawidłowo i punkt końcowy odbiorcy powinien zacząć otrzymywać tokeny zdarzeń związanych z bezpieczeństwem. W następnej sekcji opisano, jak przetestować konfigurację strumienia i punkt końcowy, aby sprawdzić, czy wszystko działa prawidłowo.

pobierać i aktualizować bieżącą konfigurację strumienia,

Jeśli w przyszłości zechcesz zmodyfikować konfigurację strumienia, możesz to zrobić, wysyłając autoryzowane żądanie GET do https://risc.googleapis.com/v1beta/stream, aby uzyskać bieżącą konfigurację strumienia, zmodyfikować treść odpowiedzi, a następnie wysłać zmodyfikowaną konfigurację z powrotem do https://risc.googleapis.com/v1beta/stream:update, jak opisano powyżej.

Zatrzymywanie i wznawianie strumienia zdarzeń

Jeśli kiedykolwiek będziesz potrzebować zatrzymać strumień zdarzeń z Google, wyślij autoryzowane żądanie POST do https://risc.googleapis.com/v1beta/stream/status:update z { "status": "disabled" } w treści żądania. Gdy strumień jest wyłączony, Google nie wysyła zdarzeń do Twojego punktu końcowego i nie buforuje zdarzeń związanych z bezpieczeństwem, gdy wystąpią. Aby ponownie włączyć strumień zdarzeń, wyślij żądanie POST { "status": "enabled" } do tego samego punktu końcowego.

3. Opcjonalnie: przetestuj konfigurację strumienia

Możesz sprawdzić, czy konfiguracja strumienia i punkt końcowy odbiornika działają prawidłowo, wysyłając token weryfikacyjny przez strumień zdarzeń. Ten token może zawierać unikalny ciąg znaków, którego możesz użyć do sprawdzenia, czy token został odebrany w punkcie końcowym. Aby korzystać z tego procesu, podczas rejestrowania odbiorcy zasubskrybuj typ zdarzenia https://schemas.openid.net/secevent/risc/event-type/verification.

Aby poprosić o token weryfikacji, wyślij autoryzowane żądanie HTTPS POST na adres https://risc.googleapis.com/v1beta/stream:verify. W treści żądania określ ciąg znaków identyfikujący:

{
  "state": "ANYTHING"
}

Na przykład:

Java

public static void testEventStream(final String stateString,
                                   String authToken) throws IOException {
    ObjectMapper jsonMapper = new ObjectMapper();
    String json = jsonMapper.writeValueAsString(new Object() {
        public String state = stateString;
    });

    HttpPost updateRequest = new HttpPost("https://risc.googleapis.com/v1beta/stream:verify");
    updateRequest.addHeader("Content-Type", "application/json");
    updateRequest.addHeader("Authorization", "Bearer " + authToken);
    updateRequest.setEntity(new StringEntity(json));

    HttpResponse updateResponse = new DefaultHttpClient().execute(updateRequest);
    Header[] responseContentTypeHeaders = updateResponse.getHeaders("Content-Type");
    StatusLine responseStatus = updateResponse.getStatusLine();
    int statusCode = responseStatus.getStatusCode();
    HttpEntity entity = updateResponse.getEntity();
    // Now handle response
}

// ...

testEventStream("Test token requested at " + new Date().toString(), authToken);

Python

import requests
import time

def test_event_stream(auth_token, nonce):
    stream_verify_endpoint = 'https://risc.googleapis.com/v1beta/stream:verify'
    headers = {'Authorization': 'Bearer {}'.format(auth_token)}
    state = {'state': nonce}
    response = requests.post(stream_verify_endpoint, json=state, headers=headers)
    response.raise_for_status()  # Raise exception for unsuccessful requests

test_event_stream(auth_token, 'Test token requested at {}'.format(time.ctime()))

Jeśli żądanie się powiedzie, token weryfikacyjny zostanie wysłany do zarejestrowanego przez Ciebie punktu końcowego. Jeśli na przykład Twój punkt końcowy obsługuje tokeny weryfikacyjne, po prostu je rejestrując, możesz sprawdzić logi, aby potwierdzić, że token został odebrany.

Informacje o kodach błędów

Interfejs RISC API może zwracać te błędy:

Kod błędu Komunikat o błędzie Sugerowane działania
400 Konfiguracja strumienia musi zawierać pole $fieldname. Żądanie wysłane do punktu końcowego https://risc.googleapis.com/v1beta/stream:update jest nieprawidłowe lub nie można go przeanalizować. Uwzględnij w żądaniu parametr $fieldname.
401 Brak autoryzacji. Autoryzacja nie powiodła się. Sprawdź, czy do żądania dołączono token autoryzacji oraz czy token jest prawidłowy i nie utracił ważności.
403 Punkt końcowy dostawy musi być adresem URL HTTPS. Punkt końcowy dostawy (czyli punkt końcowy, do którego mają być dostarczane zdarzenia RISC) musi być punktem HTTPS. Nie wysyłamy zdarzeń RISC na adresy URL HTTP.
403 Istniejąca konfiguracja strumienia nie ma metody dostarczania zgodnej ze specyfikacją RISC. Projekt Google Cloud musi już mieć konfigurację RISC. Jeśli używasz Firebase i masz włączone logowanie przez Google, Firebase będzie zarządzać RISC w Twoim projekcie. Nie będziesz mieć możliwości utworzenia konfiguracji niestandardowej. Jeśli nie używasz Logowania przez Google w projekcie w Firebase, wyłącz je i spróbuj ponownie przeprowadzić aktualizację po godzinie.
403 Nie udało się znaleźć projektu. Upewnij się, że używasz właściwego konta usługi w odpowiednim projekcie. Być może używasz konta usługi powiązanego z usuniętym projektem. Dowiedz się, jak wyświetlić wszystkie konta usługi powiązane z projektem.
403 Konto usługi musi mieć uprawnienia dostępu do konfiguracji RISC Otwórz konsolę interfejsów API projektu i przypisz rolę „Administrator konfiguracji RISC” (roles/riscconfigs.admin) do konta usługi, które wykonuje wywołania do projektu. Aby to zrobić, postępuj zgodnie z tymi instrukcjami.
403 Interfejsy API zarządzania strumieniami powinny być wywoływane tylko przez konto usługi. Więcej informacji o tym, jak wywoływać interfejsy API Google za pomocą konta usługi.
403 Punkt końcowy dostawy nie należy do żadnej z domen Twojego projektu. Każdy projekt ma zestaw autoryzowanych domen. Jeśli Twój punkt końcowy dostawy (czyli punkt końcowy, do którego mają być dostarczane zdarzenia RISC) nie jest hostowany na żadnej z tych platform, musisz dodać domenę punktu końcowego do tego zestawu.
403 Aby korzystać z tego interfejsu API, musisz mieć w projekcie skonfigurowanego co najmniej 1 klienta OAuth. RISC działa tylko wtedy, gdy utworzysz aplikację obsługującą Logowanie przez Google. To połączenie wymaga klienta OAuth. Jeśli Twój projekt nie ma klientów OAuth, RISC prawdopodobnie nie będzie dla Ciebie przydatny. Dowiedz się więcej o używaniu przez Google protokołu OAuth w interfejsach API.
403

Stan nieobsługiwany.

Nieprawidłowy stan.

Obecnie obsługujemy tylko stany transmisji „enabled” i „disabled”.
404

Projekt nie ma konfiguracji RISC.

Projekt nie ma konfiguracji RISC, nie można zaktualizować stanu.

Wywołaj punkt końcowy https://risc.googleapis.com/v1beta/stream:update, aby utworzyć nową konfigurację strumienia.
4XX/5XX Nie można zaktualizować stanu. Aby uzyskać więcej informacji, sprawdź szczegółowy komunikat o błędzie.

Zakresy tokenów dostępu

Jeśli zdecydujesz się używać tokenów dostępu do uwierzytelniania w interfejsie RISC API, Twoja aplikacja musi żądać tych zakresów:

Punkt końcowy Zakres
https://risc.googleapis.com/v1beta/stream/status https://www.googleapis.com/auth/risc.status.readonly LUB https://www.googleapis.com/auth/risc.status.readwrite
https://risc.googleapis.com/v1beta/stream/status:update https://www.googleapis.com/auth/risc.status.readwrite
https://risc.googleapis.com/v1beta/stream https://www.googleapis.com/auth/risc.configuration.readonly LUB https://www.googleapis.com/auth/risc.configuration.readwrite
https://risc.googleapis.com/v1beta/stream:update https://www.googleapis.com/auth/risc.configuration.readwrite
https://risc.googleapis.com/v1beta/stream:verify https://www.googleapis.com/auth/risc.verify

Potrzebujesz pomocy?

Najpierw zapoznaj się z sekcją Kody błędów. Jeśli nadal masz pytania, opublikuj je na Stack Overflow z tagiem #SecEvents.