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

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

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

これらの通知は、ユーザーの Google アカウントに重大な変更があったときに警告します。このような変更は通常、アプリでのユーザーのアカウントのセキュリティに影響を及ぼす可能性があります。たとえば、ユーザーの Google アカウントがハイジャックされた場合、メール アカウントの復元またはシングル サインオンの使用により、ユーザーのアカウントとアプリの不正使用につながる可能性があります。

このようなイベントのリスクを低減するため、Google はセキュリティ イベント トークンと呼ばれるサービス オブジェクトを送信します。これらのトークンは、セキュリティ イベントの種類や発生日時、影響を受けたユーザーの ID など、ごくわずかな情報しか公開しませんが、これを使用して適切な措置を講じることができます。たとえば、あるユーザーの Google アカウントが不正使用された場合、対象のユーザーに対して「Google でログイン」を一時的に無効にして、そのユーザーのアカウント復元に関するメールがユーザーの Gmail アドレスに送信されるのを防止できます。

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

概要

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

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

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

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

前提条件

セキュリティ イベント トークンは、プロフィール情報またはメールアドレスにアクセスする権限をサービスに付与した Google ユーザーにのみ表示されます。この権限を取得するには、profile または email スコープをリクエストします。新しい Sign In With 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. 編集者のロールを持つ新しいサービス アカウントを作成します。

  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 エンドポイントを作成します。このエンドポイントを登録すると(下記を参照)、セキュリティ イベント トークンと呼ばれる暗号署名付き文字列がエンドポイントに送信されます。セキュリティ イベント トークンは、単一のセキュリティ関連イベントに関する情報を含む署名付き JWT です。

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

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

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

  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 クレームは、単一のセキュリティ イベントを識別する文字列であり、ストリームに対して一意です。この ID を使用して、受信したセキュリティ イベントを追跡できます。

events クレームには、トークンが表すセキュリティ イベントに関する情報が含まれています。このクレームは、イベントタイプ ID から、このイベントのユーザーユーザーを指定する subject クレームと、利用可能なイベントに関するその他の詳細とのマッピングです。

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

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

OAuth トークン識別子

個々のトークンに関する OAuth イベントの場合、トークン サブジェクト ID には次のタイプが含まれます。

  • 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-purged 推奨: ユーザー アカウントを削除するか、代わりのログイン方法を提供します。
https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required 推奨方法: サービスに対する不審なアクティビティがないか確認し、適切な処置を行います。
https://schemas.openid.net/secevent/risc/event-type/verification 都道府県 = 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 リクエストを行って現在のストリーム構成を取得し、レスポンスの本文を変更してから、上記のように変更済みの構成を https://risc.googleapis.com/v1beta/stream:update に戻します。

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

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

3. 省略可: ストリームの設定をテストする

イベント ストリームを介して確認トークンを送信することで、ストリーム構成とレシーバー エンドポイントが連携して動作していることを確認できます。このトークンには、トークンがエンドポイントで受信されたことを確認するために使用できる一意の文字列を含めることができます。

確認トークンをリクエストするには、承認済みの 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 である必要があります。Google は RISC イベントを HTTP URL に送信しません。
403 ページ 既存のストリーム構成には、RISC の仕様準拠の配信方法がありません。 Google Cloud プロジェクトには、すでに RISC 構成が必要です。Firebase を使用していて、Google ログインが有効になっている場合、Firebase はプロジェクトの RISC を管理します。カスタム構成を作成することはできません。Firebase プロジェクトで Google ログインを使用していない場合は、無効にしてから 1 時間後に再度更新をお試しください。
403 ページ プロジェクトが見つかりませんでした。 正しいプロジェクトに正しいサービス アカウントを使用していることを確認してください。削除されたプロジェクトに関連付けられているサービス アカウントを使用している可能性があります。プロジェクトに関連付けられたすべてのサービス アカウントを確認する方法をご覧ください。
403 ページ サービス アカウントには、プロジェクトの編集者権限が必要です。 プロジェクトの Google Cloud Platform コンソールに移動し、こちらの手順に沿って、呼び出しエディタ / オーナーの権限のあるサービス アカウントをプロジェクトに付与します。
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

お困りの場合

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