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

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

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

このようなイベントのリスクを軽減するため、Google ではセキュリティ イベント トークンと呼ばれるサービス オブジェクトを Google に送信します。これらのトークンで公開される情報は非常に少ないため、セキュリティ イベントの種類、発生日時、影響を受けるユーザーの ID だけが表示されますが、それを使用して適切なアクションを行うことができます。たとえば、ユーザーの Google アカウントが不正使用された場合、そのユーザーの Google でログインを一時的に無効にし、アカウント復元用メールがユーザーの Gmail アドレスに送信されるのを防ぐことができます。

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

概要

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

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

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

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

前提条件

プロフィール情報またはメールアドレスにアクセスする権限がサービスに付与されている Google ユーザーのみが、セキュリティ イベント トークンを受け取ります。この権限を取得するには、profile スコープまたは email スコープをリクエストします。新しい Google でログインまたは従来の 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 エンドポイントを作成します。このエンドポイントを登録すると(下記を参照)、セキュリティ イベント トークンと呼ばれる暗号署名付き文字列がエンドポイントに送信されます。セキュリティ イベント トークンは、単一のセキュリティ関連イベントに関する情報を含む署名付き JWT です。

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

1. セキュリティ イベント トークンをデコードして検証する

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

  1. Google の RISC 構成ドキュメント(https://accounts.google.com/.well-known/risc-configuration にあります)から、クロスアカウント保護発行者 ID(issuer)と署名鍵証明書 URI(jwks_uri)を取得します。
  2. 任意の JWT ライブラリを使用して、セキュリティ イベント トークンのヘッダーから署名鍵 ID を取得します。
  3. Google の署名鍵証明書のドキュメントから、前の手順で取得した鍵 ID を含む公開鍵を取得します。探している ID のキーがドキュメントに含まれていない場合、セキュリティ イベント トークンが無効であり、エンドポイントが HTTP エラー 400 を返す可能性があります。
  4. 任意の JWT ライブラリを使用して、次のことを確認します。
    • セキュリティ イベント トークンは、前の手順で取得した公開鍵を使用して署名されます。
    • トークンの aud クレームは、アプリのクライアント ID の一つです。
    • トークンの 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 イベントの場合、トークン サブジェクトの識別子タイプには以下のフィールドが含まれます。

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

この認証トークンを使用すると、RISC API 呼び出しを 1 時間実行できます。トークンの有効期限が切れたら、引き続き 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" } を POST します。

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

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

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

{
  "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 サービス アカウントに RISC 構成へのアクセス権限が必要です こちらの手順に沿って、プロジェクトの API Console に移動し、プロジェクトを呼び出すサービス アカウントに「RISC 構成管理者」ロール(roles/riscconfigs.admin)を割り当てます。
403 ストリーム管理 API は、サービス アカウントによってのみ呼び出す必要があります。 詳しくは、サービス アカウントで Google API を呼び出す方法をご覧ください。
403 デリバリー エンドポイントがプロジェクトのどのドメインにも属していません。 すべてのプロジェクトに承認済みドメインのセットがあります。配信エンドポイント(RISC イベントが配信されるはずのエンドポイント)がこれらのホストのいずれかでホストされていない場合は、そのエンドポイントのドメインをそのセットに追加する必要があります。
403 この API を使用するには、プロジェクトに OAuth クライアントが少なくとも 1 つ構成されている必要があります。 RISC は、Google ログインをサポートするアプリをビルドする場合にのみ機能します。この接続には OAuth クライアントが必要です。プロジェクトに OAuth クライアントがない場合、RISC は役に立ちません。詳しくは、Google による OAuth の API の使用に関する記事をご覧ください。
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 タグを付けて投稿してください。