Proteja as contas de usuário com a Proteção entre contas

Se o app permite que os usuários façam login nas contas usando o Google, você pode melhorar a segurança das contas desses usuários compartilhados ouvindo e respondendo às notificações de ocorrências de segurança fornecidas pelo serviço de Proteção entre Contas.

Essas notificações alertam sobre mudanças importantes nas Contas do Google dos seus usuários, o que também pode ter implicações de segurança para as contas deles no seu app. Por exemplo, se a Conta do Google de um usuário for invadida, isso poderá comprometer a conta dele no seu app por meio da recuperação de conta de e-mail ou do uso de Logon único.

Para ajudar você a reduzir o potencial de risco desses eventos, o Google envia ao seu serviço objetos chamados de tokens de ocorrência de segurança. Esses tokens expõem pouquíssimas informações, apenas o tipo de ocorrência de segurança, quando ela ocorreu e o identificador do usuário afetado, mas você pode usá-los para tomar as medidas adequadas em resposta. Por exemplo, se a Conta do Google de um usuário for comprometida, você poderá desativar temporariamente o recurso Fazer Login com o Google para esse usuário e impedir que e-mails de recuperação de conta sejam enviados para o endereço do Gmail do usuário.

A Proteção entre Contas é baseada no padrão RISC, desenvolvido na OpenID Foundation.

Visão geral

Para usar a Proteção entre Contas com seu app ou serviço, conclua as seguintes tarefas:

  1. Configure seu projeto no Console de APIs.

  2. Crie um endpoint de receptor de eventos, para o qual o Google vai enviar tokens de ocorrência de segurança. Esse endpoint é responsável por validar os tokens que recebe e responder às ocorrências de segurança da maneira que você escolher.

  3. Registre seu endpoint no Google para começar a receber tokens de ocorrência de segurança.

Pré-requisito

Você só recebe tokens de ocorrência de segurança para usuários do Google que concederam ao seu serviço permissão para acessar as informações de perfil ou os endereços de e-mail deles. Para receber essa permissão, solicite os escopos profile ou email. Os SDKs mais recentes do Fazer login com o Google ou os SDKs legados do Login do Google solicitam esses escopos por padrão, mas, se você não usar as configurações padrão ou se acessar o endpoint do OpenID Connect do Google diretamente, verifique se está solicitando pelo menos um desses escopos.

Configurar um projeto no Console de APIs

Antes de começar a receber tokens de ocorrência de segurança, você precisa criar uma conta de serviço e ativar a API RISC no seu projeto do Console de APIs. Use o mesmo projeto do Console de APIs que você usa para acessar os Serviços do Google, como o Login do Google, no seu app.

Para criar a conta de serviço:

  1. Abra a página "Credenciais" do Console de APIs. Quando solicitado, escolha o projeto do Console de APIs que você usa para acessar os Serviços do Google no seu app.

  2. Clique em Criar credenciais > Conta de serviço.

  3. Crie uma nova conta de serviço com o papel de administrador de configuração RISC (roles/riscconfigs.admin) seguindo estas instruções.

  4. (Opcional) Se a organização do Google Cloud permitir a criação de chaves de conta de serviço e você planeja assinar JWTs localmente, crie uma chave para a conta de serviço recém-criada. Escolha o tipo de chave JSON e clique em Criar. Quando a chave for criada, você vai baixar um arquivo JSON que contém as credenciais da sua conta de serviço. Mantenha esse arquivo em um local seguro, mas também acessível ao endpoint do receptor de eventos.

Enquanto estiver na página "Credenciais" do projeto, anote também os IDs do cliente que você usa para o recurso Fazer Login com o Google ou o Login do Google (legado). Normalmente, você tem um ID do cliente para cada plataforma compatível. Você vai precisar desses IDs do cliente para validar tokens de ocorrência de segurança, conforme descrito na próxima seção.

Para ativar a API RISC:

  1. Abra a página da API RISC no Console de APIs. Verifique se o projeto que você usa para acessar os Serviços do Google ainda está selecionado.

  2. Leia os Termos do RISC e entenda os requisitos.

    Se você estiver ativando a API para um projeto de uma organização, verifique se tem autorização para vincular sua organização aos Termos do RISC.

  3. Clique em Ativar somente se você concordar com os Termos do RISC.

Criar um endpoint de receptor de eventos

Para receber notificações de ocorrências de segurança do Google, crie um endpoint HTTPS que processe solicitações POST HTTPS. Depois que você registrar esse endpoint (veja abaixo), o Google vai começar a postar strings assinadas criptograficamente, chamadas de tokens de ocorrência de segurança, no endpoint. Os tokens de ocorrência de segurança são JWTs assinados que contêm informações sobre uma única ocorrência relacionada à segurança.

Para cada token de ocorrência de segurança recebido no endpoint, primeiro valide e descodifique o token e, em seguida, processe a ocorrência de segurança conforme apropriado para seu serviço. É essencial validar o token de evento antes da decodificação para evitar ataques maliciosos de usuários de má-fé. As seções a seguir descrevem essas tarefas:

1. Decodificar e validar o token de ocorrência de segurança

Como os tokens de ocorrência de segurança são um tipo específico de JWT, é possível usar qualquer biblioteca JWT, como uma listada em jwt.io, para decodificar e validá-los. Seja qual for a biblioteca usada, o código de validação do token precisa fazer o seguinte:

  1. Encontre o identificador do emissor da Proteção entre Contas (issuer) e o URI do certificado da chave de assinatura (jwks_uri) no documento de configuração do RISC do Google, disponível em https://accounts.google.com/.well-known/risc-configuration.
  2. Usando a biblioteca JWT de sua escolha, obtenha o ID da chave de assinatura no cabeçalho da ocorrência de segurança.
  3. No documento do certificado da chave de assinatura do Google, pegue a chave pública com o ID da chave que você recebeu na etapa anterior. Se o documento não tiver uma chave com o ID que você está procurando, é provável que o token de ocorrência de segurança seja inválido, e seu endpoint deve retornar o erro de HTTP 400.
  4. Usando a biblioteca JWT de sua escolha, verifique o seguinte:
    • O token de ocorrência de segurança é assinado usando a chave pública que você recebeu na etapa anterior.
    • A declaração aud do token é um dos IDs do cliente dos seus apps.
    • A declaração iss do token corresponde ao identificador do emissor que você recebeu do documento de descoberta do RISC. Não é necessário verificar a validade do token (exp) porque os tokens de ocorrência de segurança representam eventos históricos e, portanto, não expiram.

Exemplo:

Java

Como usar java-jwt e 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)

Se o token for válido e tiver sido decodificado, retorne o status HTTP 202. Em seguida, processe a ocorrência de segurança indicada pelo token.

2. Processar ocorrências de segurança

Quando decodificado, um token de ocorrência de segurança se parece com o seguinte exemplo:

{
  "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"
    }
  }
}

As declarações iss e aud indicam o emissor do token (Google) e o destinatário pretendido do token (seu serviço). Você verificou essas declarações na etapa anterior.

A declaração jti é uma string que identifica uma única ocorrência de segurança e é exclusiva do stream. É possível usar esse identificador para rastrear quais ocorrências de segurança você recebeu.

A declaração events contém informações sobre a ocorrência de segurança que o token representa. Essa declaração é um mapeamento de um identificador de tipo de evento para uma declaração subject, que especifica o usuário a que esse evento se refere, e para outros detalhes sobre o evento que possam estar disponíveis.

A declaração subject identifica um usuário específico com o ID exclusivo da Conta do Google (sub). Esse ID da conta é o mesmo identificador (sub) contido nos tokens de ID do JWT emitidos pela biblioteca mais recente do recurso Fazer login com o Google (Javascript, HTML), pela biblioteca legada do Login do Google ou pelo OpenID Connect. Quando o subject_type da declaração é id_token_claims, ele também pode incluir um campo email com o endereço de e-mail do usuário.

Use as informações na declaração events para tomar as medidas adequadas para o tipo de evento na conta do usuário especificado.

Identificadores de token OAuth

Para eventos OAuth sobre tokens individuais, o tipo de identificador token subject contém os seguintes campos:

  • token_type: somente refresh_token é aceito.

  • token_identifier_alg: consulte a tabela abaixo para ver os valores possíveis.

  • token: confira a tabela abaixo.

token_identifier_alg token
prefix Os primeiros 16 caracteres do token.
hash_base64_sha512_sha512 O hash duplo do token usando SHA-512.

Se você fizer a integração com esses eventos, sugerimos indexar seus tokens com base nesses valores possíveis para garantir uma correspondência rápida quando o evento for recebido.

Tipos de evento compatíveis

A Proteção entre Contas é compatível com os seguintes tipos de ocorrências de segurança:

Tipo de evento Atributos Como responder
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked Obrigatório: proteja novamente a conta do usuário encerrando as sessões abertas.
https://schemas.openid.net/secevent/oauth/event-type/tokens-revoked

Obrigatório: se o token for para o Login do Google, encerre as sessões abertas no momento. Além disso, sugerimos que você recomende ao usuário configurar um método de login alternativo.

Sugestão: se o token for para acesso a outras APIs do Google, exclua todos os tokens OAuth do usuário que você armazenou.

https://schemas.openid.net/secevent/oauth/event-type/token-revoked Consulte a seção Identificadores de token OAuth para ver os identificadores de token.

Obrigatório: se você armazenar o token de atualização correspondente, exclua-o e peça para o usuário dar o consentimento novamente na próxima vez que um token de acesso for necessário.

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

Obrigatório: se o motivo da desativação da conta foi hijacking, encerre as sessões abertas do usuário para proteger a conta novamente.

Sugestão: se o motivo da desativação da conta foi bulk-account, analise a atividade do usuário no seu serviço e determine as ações de acompanhamento adequadas.

Sugestão: se nenhum motivo for informado, desative o Login do Google para o usuário e desative a recuperação de conta usando o endereço de e-mail associado à Conta do Google do usuário (geralmente, mas não necessariamente, uma conta do Gmail). Ofereça ao usuário um método de login alternativo.

https://schemas.openid.net/secevent/risc/event-type/account-enabled Sugestão: reative o Login do Google para o usuário e a recuperação de conta com o endereço de e-mail da Conta do Google do usuário.
https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required Sugestão: procure atividades suspeitas no serviço e tome as medidas adequadas.
https://schemas.openid.net/secevent/risc/event-type/verification state=state Sugerido: registre que um token de teste foi recebido.

Eventos duplicados e perdidos

A Proteção entre Contas vai tentar reenviar os eventos que acredita que não foram entregues. Portanto, às vezes você pode receber o mesmo evento várias vezes. Se isso puder causar ações repetidas que incomodam os usuários, use a declaração jti (que é um identificador exclusivo de um evento) para eliminar a duplicação de eventos. Há ferramentas externas, como o Google Cloud Dataflow, que podem ajudar você a executar o fluxo de dados de eliminação de duplicação.

Os eventos são entregues com um número limitado de novas tentativas. Portanto, se o receptor estiver inativo por um longo período, talvez você perca alguns eventos permanentemente.

Registrar o receptor

Para começar a receber ocorrências de segurança, registre seu endpoint receptor usando a API RISC. As chamadas para a API RISC precisam ser acompanhadas por um token de autorização.

Você vai receber ocorrências de segurança apenas para os usuários do seu app. Por isso, é necessário ter uma tela de permissão OAuth configurada no projeto do GCP como pré-requisito para as etapas descritas abaixo.

1. Gerar um token de autorização

É possível gerar um token de autorização para a API RISC usando a CLI do Google Cloud (gcloud) com identidade temporária de conta de serviço (recomendado quando iam.disableServiceAccountKeyCreation é aplicada ou para configuração única da CLI) ou assinando um JWT localmente com uma chave privada de conta de serviço.

Opção A: gerar um token de acesso de curta duração usando gcloud (não é necessária uma chave JSON)

Se a conta de usuário tiver o papel de Criador de tokens de conta de serviço (roles/iam.serviceAccountTokenCreator) na conta de serviço, será possível gerar um token de acesso do OAuth 2.0 de curta duração com o escopo de configuração do RISC necessário diretamente no terminal:

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)

Consulte Escopos de token de acesso para mais detalhes sobre os escopos do OAuth 2.0 disponíveis para a API RISC.

Opção B: criar um JWT autoassinado usando uma chave de conta de serviço

Como alternativa, para gerar um token de autorização localmente sem uma ida e volta de rede, crie um JWT com as seguintes declarações:

{
  "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
}

Assine o JWT usando a chave privada da conta de serviço, que pode ser encontrada no arquivo JSON que você salvou ao criar a chave da conta de serviço.

Exemplo:

Java

Usando java-jwt e a biblioteca de autenticação do 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')

Esse token de autorização pode ser usado para fazer chamadas de API RISC por uma hora. Quando o token expirar, gere um novo para continuar fazendo chamadas de API RISC.

2. Chamar a API de configuração de stream do RISC

Agora que você tem um token de autorização, use a API RISC para configurar o fluxo de ocorrências de segurança do projeto, incluindo o registro do endpoint do receptor.

Para isso, faça uma solicitação POST HTTPS para https://risc.googleapis.com/v1beta/stream:update, especificando o endpoint do receptor e os tipos de eventos de segurança em que você tem interesse:

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
  ]
}

Exemplo:

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'])

Se a solicitação retornar HTTP 200, o stream de eventos foi configurado corretamente, e o endpoint receptor vai começar a receber tokens de ocorrência de segurança. A próxima seção descreve como testar a configuração do stream e o endpoint para verificar se tudo está funcionando corretamente.

Acessar e atualizar a configuração atual do stream

Se, no futuro, você quiser modificar a configuração do stream, faça uma solicitação GET autorizada para https://risc.googleapis.com/v1beta/stream para receber a configuração atual do stream, modificar o corpo da resposta e, em seguida, POSTar a configuração modificada de volta para https://risc.googleapis.com/v1beta/stream:update, conforme descrito acima.

Interromper e retomar o stream de eventos

Se você precisar interromper o stream de eventos do Google, faça uma solicitação POST autorizada para https://risc.googleapis.com/v1beta/stream/status:update com { "status": "disabled" } no corpo da solicitação. Enquanto o stream estiver desativado, o Google não enviará eventos para seu endpoint nem armazenará em buffer as ocorrências de segurança quando elas ocorrerem. Para reativar o stream de eventos, envie uma solicitação POST { "status": "enabled" } para o mesmo endpoint.

3. Opcional: testar a configuração do stream

Para verificar se a configuração do stream e o endpoint do receptor estão funcionando corretamente, envie um token de verificação pelo stream de eventos. Esse token pode conter uma string exclusiva que você pode usar para verificar se o token foi recebido no endpoint. Para usar esse fluxo, inscreva-se no tipo de evento https://schemas.openid.net/secevent/risc/event-type/verification ao registrar seu receptor.

Para solicitar um token de verificação, faça uma solicitação POST HTTPS autorizada para https://risc.googleapis.com/v1beta/stream:verify. No corpo da solicitação, especifique uma string de identificação:

{
  "state": "ANYTHING"
}

Exemplo:

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()))

Se a solicitação for bem-sucedida, o token de verificação será enviado ao endpoint que você registrou. Em seguida, por exemplo, se o endpoint processar tokens de verificação simplesmente registrando-os, você poderá examinar os registros para confirmar se o token foi recebido.

Referência do código do erro

Os seguintes erros podem ser retornados pela API RISC:

Código do erro Mensagem de erro Ações sugeridas
400 A configuração do stream precisa conter o campo $fieldname. Sua solicitação para o endpoint https://risc.googleapis.com/v1beta/stream:update é inválida ou não pode ser analisada. Inclua $fieldname na solicitação.
401 Não autorizado. Houve falha na autorização. Verifique se você anexou um token de autorização à solicitação e se o token é válido e não expirou.
403 O endpoint de entrega precisa ser um URL HTTPS. O endpoint de entrega (ou seja, o endpoint em que você espera que os eventos do RISC sejam entregues) precisa ser HTTPS. Não enviamos eventos RISC para URLs HTTP.
403 A configuração de stream atual não tem um método de entrega compatível com as especificações para RISC. Seu projeto na nuvem do Google Cloud já precisa ter uma configuração de RISC. Se você estiver usando o Firebase e tiver o Login do Google ativado, o Firebase vai gerenciar o RISC para seu projeto. Não será possível criar uma configuração personalizada. Se você não estiver usando o Login do Google no seu projeto do Firebase, desative-o e tente atualizar novamente após uma hora.
403 Não foi possível encontrar o projeto. Verifique se você está usando a conta de serviço correta para o projeto correto. Talvez você esteja usando uma conta de serviço associada a um projeto excluído. Saiba como ver todas as contas de serviço associadas a um projeto.
403 A conta de serviço precisa de permissão para acessar sua configuração do RISC Acesse o console de APIs do seu projeto e atribua o papel "Administrador de configuração do RISC" (roles/riscconfigs.admin) à conta de serviço que está fazendo as chamadas para seu projeto seguindo estas instruções.
403 As APIs de gerenciamento de stream só podem ser chamadas por uma conta de serviço. Confira mais informações sobre como chamar APIs do Google com uma conta de serviço.
403 O endpoint de entrega não pertence a nenhum dos domínios do seu projeto. Cada projeto tem um conjunto de domínios autorizados. Se o endpoint de entrega (ou seja, o endpoint em que você espera que os eventos do RISC sejam entregues) não estiver hospedado em um deles, será necessário adicionar o domínio do endpoint a esse conjunto.
403 Para usar essa API, seu projeto precisa ter pelo menos um cliente OAuth configurado. O RISC só funciona se você criar um app compatível com o Login do Google. Essa conexão exige um cliente OAuth. Se o projeto não tiver clientes OAuth, é provável que o RISC não seja útil para você. Saiba mais sobre o uso do OAuth pelo Google para nossas APIs.
403

Status não aceito.

Status de inválido(a).

No momento, só aceitamos os status de stream "enabled" e "disabled".
404

O projeto não tem configuração de RISC.

O projeto não tem uma configuração RISC, não é possível atualizar o status.

Chame o endpoint https://risc.googleapis.com/v1beta/stream:update para criar uma nova configuração de stream.
4XX/5XX Não foi possível atualizar o status. Confira a mensagem de erro detalhada para mais informações.

Escopos de token de acesso

Se você decidir usar tokens de acesso para autenticação na API RISC, estes são os escopos que seu aplicativo precisa solicitar:

Endpoint Escopo
https://risc.googleapis.com/v1beta/stream/status https://www.googleapis.com/auth/risc.status.readonly OU 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 OU 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

Precisa de ajuda?

Primeiro, confira nossa seção de referência de códigos de erro. Se ainda tiver dúvidas, poste-as no Stack Overflow com a tag #SecEvents.