クロスアカウント保護機能でユーザー アカウントを保護する

アプリでユーザーが Google を使用してアカウントにログインできる場合、クロスアカウント保護サービスが提供するセキュリティ イベント通知をリッスンして応答することで、これらの共有ユーザーのアカウントのセキュリティを向上させることができます。

これらの通知は、ユーザーの Google アカウントに重大な変更があったことを警告するものであり、アプリを使用しているユーザーのアカウントにもセキュリティに影響することがよくあります。たとえば、ユーザーの Google アカウントが乗っ取られた場合、メール アカウントの復元やシングル サインオンの使用によって、ユーザーのアカウントが不正使用される可能性があります。

このようなイベントのリスクを軽減するため、Google はセキュリティ イベント トークンと呼ばれるサービス オブジェクトを送信します。これらのトークンによって公開される情報はほとんどありません(セキュリティ イベントの種類、発生日時、影響を受けたユーザーの ID のみ)。ただし、これらのトークンを使用して適切な措置を講じることができます。たとえば、ユーザーの Google アカウントが不正使用された場合、そのユーザーの「Google でログイン」を一時的に無効にして、アカウントの再設定用のメールアドレスがユーザーの Gmail アドレスに送信されないようにできます。

クロスアカウント保護は、OpenID Foundation で開発された RISC 標準に基づいています。

概要

アプリやサービスでクロスアカウント保護機能を使用するには、次のタスクを行う必要があります。

  1. API Consoleでプロジェクトを設定します。

  2. Google がセキュリティ イベント トークンを送信するイベント レシーバー エンドポイントを作成します。このエンドポイントは、受け取ったトークンを検証し、任意の方法でセキュリティ イベントに応答します。

  3. エンドポイントを Google に登録して、セキュリティ イベント トークンの受信を開始します。

前提条件

セキュリティ イベント トークンを受け取るのは、ユーザーのプロフィール情報やメールアドレスにアクセスする権限を付与した Google ユーザーのみです。この権限を取得するには、profile または email スコープをリクエストします。新しい Google でログイン SDK または以前の Google ログイン SDK はデフォルトでこれらのスコープをリクエストしますが、デフォルト設定を使用しない場合、または Google の OpenID Connect エンドポイントに直接アクセスする場合は、これらのスコープのうち少なくとも 1 つをリクエストしていることを確認してください。

API Consoleでプロジェクトを設定する

セキュリティ イベント トークンの受信を開始する前に、サービス アカウントを作成し、API Console プロジェクトで RISC API を有効にする必要があります。アプリで Google サービス(Google ログインなど)にアクセスする場合と同じAPI Console プロジェクトを使用する必要があります。

サービス アカウントを作成するには:

  1. API Console Credentials page を開きます。プロンプトが表示されたら、アプリで Google サービスへのアクセスに使用するAPI Consoleプロジェクトを選択します。

  2. [認証情報を作成] > [サービス アカウント] をクリックします。

  3. こちらの手順に沿って、RISC 構成管理者のロール(roles/riscconfigs.admin)を持つ新しいサービス アカウントを作成します。

  4. 新しく作成したサービス アカウントのキーを作成します。JSON キータイプを選択し、[作成] をクリックします。キーが作成されると、サービス アカウントの認証情報を含む JSON ファイルがダウンロードされます。このファイルは安全な場所に保管し、イベント レシーバ エンドポイントからもアクセスできる場所に保管してください。

プロジェクトの [認証情報] ページを表示しているときに、「Google でログイン」または Google ログイン(レガシー)に使用するクライアント ID もメモしておきます。通常、サポートするプラットフォームごとにクライアント ID があります。次のセクションで説明するように、これらのクライアント ID はセキュリティ イベント トークンを検証するために必要です。

RISC API を有効にするには:

  1. API Consoleの RISC API ページを開きます。Google サービスへのアクセスに使用するプロジェクトが選択されていることを確認します。

  2. RISC 規約を読み、要件を確実に理解します。

    組織が所有するプロジェクトで API を有効にする場合は、組織を RISC 規約に拘束する権限を持っている必要があります。

  3. RISC 規約に同意する場合にのみ、[有効にする] をクリックしてください。

イベント レシーバ エンドポイントを作成する

Google からセキュリティ イベント通知を受け取るには、HTTPS POST リクエストを処理する HTTPS エンドポイントを作成します。このエンドポイントを登録すると(以下を参照)、Google はセキュリティ イベント トークンと呼ばれる暗号署名された文字列をエンドポイントに送信し始めます。セキュリティ イベント トークンは、単一のセキュリティ関連イベントに関する情報を含む署名付き JWT です。

エンドポイントで受信するセキュリティ イベント トークンごとに、まずトークンを検証してデコードしてから、サービスに適したセキュリティ イベントを処理します。不正な行為者による悪意のある攻撃を防ぐため、デコードする前にイベント トークンを検証することが不可欠です。以降のセクションでは、これらのタスクについて説明します。

1. セキュリティ イベント トークンのデコードと検証

セキュリティ イベント トークンは特定の種類の JWT であるため、jwt.io にリストされているものなど、任意の JWT ライブラリを使用してデコードと検証を行うことができます。どのライブラリを使用する場合でも、トークン検証コードで次のことを行う必要があります。

  1. Google の RISC 構成ドキュメントからクロスアカウント保護の発行者 ID(issuer)と署名鍵証明書の URI(jwks_uri)を取得します。このドキュメントは https://accounts.google.com/.well-known/risc-configuration にあります。
  2. 任意の JWT ライブラリを使用して、セキュリティ イベント トークンのヘッダーから署名鍵 ID を取得します。
  3. Google の署名鍵証明書ドキュメントから、前の手順で取得した鍵 ID を含む公開鍵を取得します。探している ID のキーがドキュメントに含まれていない場合は、セキュリティ イベント トークンが無効である可能性が高く、エンドポイントから HTTP エラー 400 が返されます。
  4. 任意の JWT ライブラリを使用して、次のことを確認します。
    • セキュリティ イベント トークンは、前の手順で取得した公開鍵で署名されます。
    • トークンの aud クレームがアプリのクライアント ID の 1 つである。
    • トークンの iss クレームは、RISC ディスカバリ ドキュメントから取得した発行者 ID と一致します。セキュリティ イベント トークンは過去のイベントを表し、有効期限がないため、トークンの有効期限(exp)を検証する必要はありません。

次に例を示します。

Java

java-jwtjwks-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)

トークンが有効で、正常にデコードされた場合は、HTTP ステータス 202 を返します。次に、トークンが示すセキュリティ イベントを処理します。

2. セキュリティ イベントを処理する

デコードされたセキュリティ イベント トークンは、次の例のようになります。

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

iss クレームと aud クレームは、トークンの発行元(Google)とトークンの受信者(サービス)を示します。これらのクレームは前の手順で確認しました。

jti クレームは、単一のセキュリティ イベントを識別する文字列で、ストリームに対して一意です。この識別子を使用して、受信したセキュリティ イベントを追跡できます。

events クレームには、トークンが表すセキュリティ イベントに関する情報が含まれます。このクレームは、イベントタイプ識別子から、このイベントに関連するユーザーを指定する subject クレームと、使用可能なイベントに関する追加情報へのマッピングです。

subject クレームは、一意の Google アカウント ID(sub)で特定のユーザーを識別します。この Google アカウント ID は、新しい「Google でログイン」(JavaScriptHTML)ライブラリ、従来の Google ログイン ライブラリ、または OpenID Connect によって発行される JWT ID トークンに含まれる識別子(sub)と同じです。クレームの subject_typeid_token_claims の場合、ユーザーのメールアドレスの email フィールドが含まれることもあります。

events クレームの情報を使用して、指定したユーザーのアカウントのイベントタイプに対して適切なアクションを実行します。

OAuth トークン識別子

個々のトークンに関する OAuth イベントの場合、トークン サブジェクト識別子タイプには次のフィールドが含まれます。

  • token_type: refresh_token のみがサポートされています。

  • token_identifier_alg: 設定可能な値については、以下の表をご覧ください。

  • token: 下記の表をご覧ください。

token_identifier_alg token
prefix トークンの最初の 16 文字。
hash_base64_sha512_sha512 SHA-512 を使用したトークンのダブルハッシュ。

これらのイベントと統合する場合は、イベントの受信時にすばやく一致させるために、これらの可能な値に基づいてトークンをインデックスに登録することをおすすめします。

サポートされているイベントタイプ

クロスアカウント保護機能は、次の種類のセキュリティ イベントをサポートしています。

イベントタイプ 属性 対応方法
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked 必須: 現在開いているセッションを終了して、ユーザーのアカウントを再度保護します。
https://schemas.openid.net/secevent/oauth/event-type/tokens-revoked

必須: トークンが Google ログイン用の場合は、現在開いているセッションを終了します。また、別のログイン方法を設定するようユーザーに提案することもできます。

推奨: 他の Google API へのアクセス用のトークンの場合は、保存したユーザーの OAuth トークンをすべて削除します。

https://schemas.openid.net/secevent/oauth/event-type/token-revoked トークン識別子については、OAuth トークン識別子のセクションをご覧ください。

必須: 対応する更新トークンを保存している場合は、トークンを削除し、次回アクセス トークンが必要になったときにユーザーに再度同意するようリクエストします。

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

必須: アカウントが無効になった理由が hijacking の場合は、現在開いているセッションを終了してユーザーのアカウントを再度保護します。

推奨: アカウントが無効になった理由が bulk-account の場合は、サービスでのユーザーのアクティビティを分析し、適切なフォローアップ アクションを決定します。

推奨: 理由が提供されていない場合は、ユーザーの Google ログインを無効にし、ユーザーの Google アカウントに関連付けられたメールアドレスを使用してアカウント復元を無効にします(通常は Gmail アカウントとは限りません)。別のログイン方法をユーザーに提供します。

https://schemas.openid.net/secevent/risc/event-type/account-enabled 推奨: ユーザーの Google ログインを再度有効にし、ユーザーの Google アカウントのメールアドレスでアカウント復元を再度有効にします。
https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required 推奨: サービスで不審なアクティビティがないか注意して、適切な措置を講じてください。
https://schemas.openid.net/secevent/risc/event-type/verification state=state 推奨: テストトークンを受け取ったことをログに記録します。

重複する予定や見逃された予定

クロスアカウント保護機能は、配信されていないと思われるイベントの再配信を試みます。そのため、同じイベントが複数回受信される可能性があります。ユーザーに不便を感じる繰り返しアクションが発生する可能性がある場合は、jti クレーム(イベントの一意の識別子)を使用してイベントの重複を減らすことを検討してください。Google Cloud Dataflow などの外部ツールは、重複除去データフローの実行に役立ちます。

イベントは限定的な再試行で配信されるため、レシーバが長時間ダウンすると、一部のイベントが恒久的に失われる可能性があります。

レシーバーを登録する

セキュリティ イベントの受信を開始するには、RISC API を使用してレシーバー エンドポイントを登録します。RISC API を呼び出す場合は、認証トークンを指定する必要があります。

受け取るセキュリティ イベントはアプリのユーザーのみを対象としているため、以下で説明する手順の前提条件として、GCP プロジェクトで OAuth 同意画面を構成する必要があります。

1. 認証トークンを生成する

RISC API の認証トークンを生成するには、次のクレームを持つ JWT を作成します。

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

サービス アカウントの秘密鍵を使用して JWT に署名します。秘密鍵は、サービス アカウント キーの作成時にダウンロードした JSON ファイルで確認できます。

次に例を示します。

Java

java-jwtGoogle の認証ライブラリを使用する場合:

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

この認証トークンを使用して 1 時間の RISC API 呼び出しを行うことができます。トークンが期限切れになったら、新しいトークンを生成し、引き続き RISC API 呼び出しを行います。

2. RISC ストリーム構成 API を呼び出す

認証トークンを取得したら、RISC API を使用して、レシーバー エンドポイントの登録など、プロジェクトのセキュリティ イベント ストリームを構成できます。

これを行うには、https://risc.googleapis.com/v1beta/stream:update に HTTPS POST リクエストを行い、レシーバー エンドポイントと目的のセキュリティ イベントのタイプを指定します。

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

次に例を示します。

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

リクエストが HTTP 200 を返した場合、イベント ストリームは正常に構成されており、レシーバー エンドポイントはセキュリティ イベント トークンの受信を開始する必要があります。次のセクションでは、ストリーム構成とエンドポイントをテストして、すべてが正常に動作していることを検証する方法について説明します。

現在のストリーム構成を取得して更新する

今後ストリーム構成を変更する場合は、https://risc.googleapis.com/v1beta/stream に承認済みの GET リクエストを発行して現在のストリーム構成を取得し、レスポンスの本文を変更して、変更された構成を上記のように POST で https://risc.googleapis.com/v1beta/stream:update に返します。

イベント ストリームを停止、再開する

Google からのイベント ストリームを停止する必要がある場合は、リクエスト本文に { "status": "disabled" } を使用して、承認済みの POST リクエストを https://risc.googleapis.com/v1beta/stream/status:update に送信します。ストリームが無効になっている間、Google はエンドポイントにイベントを送信せず、セキュリティ イベントが発生したときにバッファリングしません。イベント ストリームを再度有効にするには、同じエンドポイントに { "status": "enabled" } を POST します。

3.省略可: ストリーム構成をテストする

イベント ストリームを介して確認トークンを送信することで、ストリーム構成とレシーバ エンドポイントが正しく連携していることを確認できます。このトークンには、トークンがエンドポイントで受信されたことを確認するために使用できる一意の文字列を含めることができます。このフローを使用するには、レシーバーを登録するときに、必ず https://schemas.openid.net/secevent/risc/event-type/verification イベントタイプに登録してください。

確認トークンをリクエストするには、承認済みの HTTPS POST リクエストを https://risc.googleapis.com/v1beta/stream:verify に送信します。リクエストの本文で、識別文字列を指定します。

{
  "state": "ANYTHING"
}

次に例を示します。

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

リクエストが成功すると、登録したエンドポイントに検証トークンが送信されます。たとえば、エンドポイントが検証トークンをログに記録するだけで処理している場合は、ログを調べてトークンが受信されたことを確認できます。

エラーコードの参照

RISC API から次のエラーが返されることがあります。

エラーコード エラー メッセージ 推奨される対応
400 ストリーム構成には $fieldname フィールドを含める必要があります。 https://risc.googleapis.com/v1beta/stream:update エンドポイントへのリクエストが無効であるか、解析できません。リクエストには $fieldname を含めてください。
401 許可されていません。 承認に失敗しました。リクエストに 認証トークンを添付していること、トークンが有効で期限切れになっていないことを確認してください。
403 配信エンドポイントは HTTPS URL にする必要があります。 配信エンドポイント(RISC イベントが配信されるエンドポイント)は HTTPS にする必要があります。RISC イベントは HTTP URL に送信されません。
403 既存のストリーム構成に、RISC の仕様に準拠した配信方法がありません。 Google Cloud プロジェクトには、すでに RISC 構成が存在している必要があります。Firebase を使用していて、Google ログインを有効にしている場合、Firebase がプロジェクトの RISC を管理します。カスタム構成を作成することはできません。Firebase プロジェクトで Google ログインを使用していない場合は、無効にし、1 時間後にもう一度更新してみてください。
403 プロジェクトが見つかりませんでした。 正しいプロジェクトに正しいサービス アカウントを使用していることを確認してください。削除されたプロジェクトに関連付けられたサービス アカウントを使用している可能性があります。 プロジェクトに関連付けられているすべてのサービス アカウントを表示する方法をご覧ください。
403 サービス アカウントには RISC 構成へのアクセス権限が必要です プロジェクトの API Console に移動し、こちらの手順に沿って、プロジェクトを呼び出すサービス アカウントに「RISC 構成管理者」ロール(roles/riscconfigs.admin)を割り当てます。
403 ストリーム管理 API は、サービス アカウントによってのみ呼び出す必要があります。 詳細については、サービス アカウントで Google API を呼び出す方法をご覧ください。
403 配信エンドポイントは、プロジェクトのどのドメインに属していません。 どのプロジェクトにも、一連の承認済みドメインがあります。配信エンドポイント(RISC イベントの配信先エンドポイント)がホストされていない場合、エンドポイントのドメインをそのセットに追加する必要があります。
403 この API を使用するには、プロジェクトに少なくとも 1 つの OAuth クライアントが設定されている必要があります。 RISC は、Google ログインをサポートするアプリをビルドする場合にのみ機能します。この接続には OAuth クライアントが必要です。プロジェクトに OAuth クライアントがない場合、RISC はおそらく役に立ちません。Google による API での OAuth の使用の詳細をご覧ください。
403

サポートされていないステータスです。

無効なステータスです。

現時点では、ストリーム ステータス「enabled」と「disabled」のみがサポートされています。
404

プロジェクトに RISC 構成がありません。

プロジェクトに既存の RISC 構成がないため、ステータスを更新できません。

https://risc.googleapis.com/v1beta/stream:update エンドポイントを呼び出して、新しいストリーム構成を作成します。
4XX/5XX ステータスを更新できませんでした。 詳しくは、詳細なエラー メッセージを確認してください。

アクセス トークンのスコープ

RISC API の認証にアクセス トークンを使用する場合は、アプリケーションで次のスコープをリクエストする必要があります。

エンドポイント 範囲
https://risc.googleapis.com/v1beta/stream/status https://www.googleapis.com/auth/risc.status.readonly または 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 または 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

お困りの場合

まず、エラーコード リファレンスを確認します。ご不明な点がある場合は、Stack Overflow に #SecEvents タグを付けて投稿してください。