使用跨帳戶防護功能保護使用者帳戶

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

如果您的應用程式可讓使用者透過 Google 登入帳戶,您可以監聽及回應跨帳戶防護服務的安全性事件通知,加強這些共用使用者的帳戶安全性。

這些通知會通知您使用者的 Google 帳戶有重大異動,這類問題通常也會對應用程式造成安全問題。舉例來說,假設使用者的 Google 帳戶遭人盜用,那麼我們可能會透過電子郵件帳戶復原或單一登入等方式,損害使用者的帳戶。

為降低這類事件的風險,Google 會傳送名為「安全性事件權杖」的服務物件。這些權杖所提供的資訊非常少,只是安全性事件的類型、發生時機和受影響使用者的 ID,但這些憑證可以採取適當的行動來回應。舉例來說,如果使用者的 Google 帳戶遭到入侵,您可以暫時停用該使用者的「使用 Google 帳戶登入」功能,並避免系統將帳戶救援電子郵件傳送至使用者的 Gmail 地址。

跨帳戶防護是以 OpenID Foundation 開發的 RISC 標準為基礎。

總覽

如要將跨帳戶防護功能與應用程式或服務搭配使用,您必須完成以下工作:

  1. 在 API Console中設定專案。

  2. 建立事件接收器端點,供 Google 將安全性事件權杖傳送給此。此端點負責驗證收到的權杖,並以您選擇的方式回應安全性事件。

  3. 向 Google 註冊端點,即可開始接收安全性事件權杖。

先修規定

只有已授權服務存取使用者個人資訊或電子郵件的電子郵件地址的 Google 使用者,才會收到安全性事件權杖。您可以藉由要求 profileemail 範圍取得這項權限。根據預設,新版使用 Google 帳戶登入功能或舊版 Google 登入 SDK 會要求這些範圍,但如果您未使用預設設定,或是您直接存取 Google 的 OpenID Connect 端點,請確保您要求至少提供其中一個範圍。

在 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 條款後,才可啟用「Enable」(啟用)

建立事件接收器端點

如要接收 Google 的安全性事件通知,您必須建立 HTTPS 端點來處理 HTTPS POST 要求。註冊這個端點後 (如下所示),Google 會開始將稱為安全性事件權杖的加密簽署字串發布至端點。安全性事件權杖是已簽署的 JWT,其中包含單一安全性相關事件的相關資訊。

針對在端點收到的每個安全性事件權杖,請先驗證並解碼該權杖,然後視需要處理服務的安全性事件。「務必」在解碼之前驗證事件符記,以免惡意人士遭受惡意攻擊。下列各節說明這些工作:

1. 將安全性事件權杖解碼並完成驗證

由於安全性事件權杖是特定類型的 JWT,因此您可以使用任何 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。
    • 權杖的 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"
    }
  }
}

issaud 憑證附加資訊表示權杖 (Google) 的核發者和權杖的指定收件者 (您的服務)。您可以在上一個步驟中驗證這些聲明。

jti 憑證是可識別單一安全性事件的字串,是串流的專屬字串。您可以使用此 ID 追蹤您收到的安全性事件。

events 憑證包含權杖代表的安全性事件的相關資訊。這個憑證是從事件類型 ID 對應至 subject 憑證,以指定這個事件有疑慮的使用者,以及任何其他可能的事件詳細資料。

subject 憑證附加資訊可識別特定使用者的專屬 Google 帳戶 ID (sub)。此 Google 帳戶 ID 與新版「使用 Google 帳戶登入」(JavaScriptHTML) 程式庫、舊版 Google 登入程式庫或 OpenID Connect 核發的 JWT ID 權杖中的 ID 相同 (sub)。當憑證的 subject_typeid_token_claims 時,其中可能包含使用者電子郵件地址的 email 欄位。

使用 events 憑證中的資訊,對指定使用者帳戶中的事件類型採取適當行動。

OAuth 權杖 ID

如果是個別權杖的 OAuth 事件,權杖主體 ID 類型包含下列欄位:

  • token_type:僅支援 refresh_token

  • token_identifier_alg:請參閱下表,瞭解可能的值。

  • token:請參閱下表。

token_identifier_alg 權杖
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 如需權杖 ID,請參閱 OAuth 權杖 ID 一節

必要:如果您儲存對應的重新整理權杖,請刪除該權杖,並在下次需要存取權杖時要求重新取得同意聲明。

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=state 建議使用:已收到收到的測試權杖記錄。

重複和錯過的活動

跨帳戶防護功能會盡量重新提交認為未傳送的事件。因此,您有時可能會多次收到相同的事件。如果這會導致使用者重複採取重複操作,請考慮使用 jti 聲明 (事件的專屬 ID) 來排除事件。有些外部工具 (例如 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 檔案中找到這組 JWT。

例如:

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 呼叫,權杖過期後,請產生新的權杖來繼續發出 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://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 網址。 您的傳送端點 (也就是您希望將 RISC 事件傳送給的端點) 必須是 HTTPS。系統不會將 RISC 事件傳送至 HTTP 網址。
403 現有串流設定沒有 RISC 的規格提交方式。 您的 Google Cloud 專案已有 RISC 設定。如果您使用 Firebase 並啟用 Google 登入功能,Firebase 就會為您的專案管理 RISC;您將無法建立自訂設定。如果您的 Firebase 專案並非使用 Google 登入功能,請將其停用,然後在一小時後再次嘗試更新。
403 找不到專案。 請確認您使用的服務帳戶正確無誤。您可能使用了與刪除專案相關聯的服務帳戶。瞭解如何查看與專案相關聯的所有服務帳戶
403 服務帳戶需要取得您的 RISC 設定存取權 前往專案的 API Console ,並將「RISC 設定管理員」角色 (roles/riscconfigs.admin) 指派給按照這些操作說明呼叫專案的服務帳戶。
403 只有服務帳戶才能呼叫串流管理 API。 進一步瞭解如何使用服務帳戶呼叫 Google API
403 提交端點不屬於您專案的任何網域。 每個專案都有一組授權網域。如果您的提供端點 (也就是您希望將 RISC 事件傳送給的端點) 未透過其中一個端點託管,您必須將端點的網域新增至該組合。
403 如要使用這個 API,您的專案必須至少設定一個 OAuth 用戶端。 只有在您建構支援 Google 登入的應用程式時,RISC 才能正常運作。此連線需要 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.readonlyhttps://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.readonlyhttps://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 標記。