ปกป้องบัญชีผู้ใช้ด้วยการป้องกันข้ามบัญชี

หากแอปของคุณอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้บัญชีของตนโดยใช้ Google คุณสามารถปรับปรุงการรักษาความปลอดภัยของบัญชีผู้ใช้ที่แชร์เหล่านี้ได้โดยการฟังและตอบสนองต่อการแจ้งเตือนเหตุการณ์ด้านความปลอดภัยที่บริการการป้องกันข้ามบัญชีให้ไว้

การแจ้งเตือนเหล่านี้จะแจ้งเตือนคุณถึงการเปลี่ยนแปลงที่สำคัญในบัญชี Google ของผู้ใช้ของคุณ ซึ่งมักจะมีนัยด้านความปลอดภัยสำหรับบัญชีของผู้ใช้ในแอปของคุณ ตัวอย่างเช่น หากบัญชี Google ของผู้ใช้ถูกจี้ อาจนำไปสู่การประนีประนอมกับบัญชีของผู้ใช้กับแอปของคุณผ่านการกู้คืนบัญชีอีเมลหรือการใช้การลงชื่อเพียงครั้งเดียว

เพื่อช่วยคุณลดความเสี่ยงที่อาจเกิดขึ้นจากเหตุการณ์ดังกล่าว Google จะส่งออบเจ็กต์บริการของคุณที่เรียกว่าโทเค็นเหตุการณ์ความปลอดภัย โทเค็นเหล่านี้เปิดเผยข้อมูลเพียงเล็กน้อย—เพียงประเภทของเหตุการณ์ความปลอดภัยและเวลาที่มันเกิดขึ้น และตัวระบุของผู้ใช้ที่ได้รับผลกระทบ—แต่คุณสามารถใช้เพื่อดำเนินการตามความเหมาะสมในการตอบกลับ ตัวอย่างเช่น หากบัญชี Google ของผู้ใช้ถูกบุกรุก คุณสามารถปิดใช้งานการลงชื่อเข้าใช้ด้วย Google สำหรับผู้ใช้รายนั้นชั่วคราวและป้องกันไม่ให้ส่งอีเมลการกู้คืนบัญชีไปยังที่อยู่ Gmail ของผู้ใช้

การป้องกันข้ามบัญชีเป็นไปตาม มาตรฐาน RISC ซึ่งพัฒนาขึ้นที่ OpenID Foundation

ภาพรวม

หากต้องการใช้การป้องกันข้ามบัญชีกับแอปหรือบริการของคุณ คุณต้องดำเนินการดังต่อไปนี้:

  1. ตั้งค่าโครงการของคุณใน API Console

  2. สร้างจุดสิ้นสุดของตัวรับเหตุการณ์ ซึ่ง Google จะส่งโทเค็นของเหตุการณ์ความปลอดภัยไปให้ ปลายทางนี้มีหน้าที่ตรวจสอบความถูกต้องของโทเค็นที่ได้รับ จากนั้นจึงตอบสนองต่อเหตุการณ์ด้านความปลอดภัยในแบบที่คุณเลือก

  3. ลงทะเบียนปลายทางของคุณกับ Google เพื่อเริ่มรับโทเค็นการรักษาความปลอดภัย

วิชาบังคับก่อน

คุณจะได้รับโทเค็นกิจกรรมความปลอดภัยสำหรับผู้ใช้ Google ที่อนุญาตให้เข้าถึงข้อมูลโปรไฟล์หรือที่อยู่อีเมลของพวกเขาเท่านั้น คุณได้รับการอนุญาตนี้โดยขอ profile หรือขอบเขต email Sign In With Google ที่ใหม่กว่าหรือ Google Sign-in SDK แบบเดิมขอขอบเขตเหล่านี้โดยค่าเริ่มต้น แต่ถ้าคุณไม่ได้ใช้การตั้งค่าเริ่มต้น หรือหากคุณเข้าถึง ปลายทาง OpenID Connect ของ Google โดยตรง ตรวจสอบว่าคุณขออย่างน้อยหนึ่งรายการ ขอบเขต

ตั้งค่าโครงการใน API Console

ก่อนที่คุณจะเริ่มรับโทเค็นเหตุการณ์ความปลอดภัย คุณต้องสร้างบัญชีบริการและเปิดใช้งาน RISC API ในโปรเจ็กAPI Console ของคุณ คุณต้องใช้โปรเจ็API Console เดียวกันกับที่คุณใช้เพื่อเข้าถึงบริการของ Google เช่น Google Sign-in ในแอปของคุณ

ในการสร้างบัญชีบริการ:

  1. เปิด API ConsoleCredentials page เมื่อได้รับแจ้ง ให้เลือกโปรเจ็API Consoleคุณใช้เพื่อเข้าถึงบริการของ Google ในแอปของคุณ

  2. คลิก สร้างข้อมูลรับรอง > บัญชีบริการ

  3. สร้างบัญชีบริการใหม่ที่มีบทบาทบรรณาธิการ

  4. สร้างคีย์สำหรับบัญชีบริการที่สร้างขึ้นใหม่ เลือกประเภทคีย์ JSON แล้วคลิก Create เมื่อสร้างคีย์แล้ว คุณจะต้องดาวน์โหลดไฟล์ JSON ที่มีข้อมูลรับรองบัญชีบริการของคุณ เก็บไฟล์นี้ไว้ในที่ที่ปลอดภัย แต่ยังเข้าถึงจุดสิ้นสุดของตัวรับเหตุการณ์ของคุณได้ด้วย

ขณะที่คุณอยู่ในหน้าข้อมูลประจำตัวของโปรเจ็กต์ ให้จดบันทึกรหัสไคลเอ็นต์ที่คุณใช้สำหรับการลงชื่อเข้าใช้ด้วย Google หรือการลงชื่อเข้าใช้ Google (เดิม) โดยปกติ คุณมีรหัสลูกค้าสำหรับแต่ละแพลตฟอร์มที่คุณสนับสนุน คุณจะต้องใช้รหัสไคลเอ็นต์เหล่านี้เพื่อตรวจสอบโทเค็นเหตุการณ์ความปลอดภัย ตามที่อธิบายไว้ในส่วนถัดไป

ในการเปิดใช้งาน RISC API:

  1. เปิดหน้า RISC API ในAPI Consoleตรวจสอบให้แน่ใจว่ายังคงเลือกโปรเจ็กต์ที่คุณใช้เพื่อเข้าถึงบริการของ Google

  2. อ่าน ข้อกำหนด RISC และตรวจสอบให้แน่ใจว่าคุณเข้าใจข้อกำหนด

    หากคุณกำลังเปิดใช้งาน API สำหรับโครงการที่เป็นเจ้าของโดยองค์กร ตรวจสอบให้แน่ใจว่าคุณได้รับอนุญาตให้ผูกมัดองค์กรของคุณกับข้อกำหนด RISC

  3. คลิก เปิดใช้งาน ก็ต่อเมื่อคุณยินยอมตามข้อกำหนดของ RISC

สร้างจุดสิ้นสุดตัวรับเหตุการณ์

หากต้องการรับการแจ้งเตือนเหตุการณ์ด้านความปลอดภัยจาก Google คุณต้องสร้างปลายทาง HTTPS ที่จัดการคำขอ HTTPS POST หลังจากที่คุณลงทะเบียนปลายทางนี้ (ดูด้านล่าง) Google จะเริ่มโพสต์สตริงที่มีการเข้ารหัสลับที่เรียกว่าโทเค็นเหตุการณ์ความปลอดภัยไปยังปลายทาง โทเค็นเหตุการณ์ความปลอดภัยได้รับการลงนาม JWT ที่มีข้อมูลเกี่ยวกับเหตุการณ์ที่เกี่ยวข้องกับความปลอดภัยเดียว

สำหรับโทเค็นเหตุการณ์ความปลอดภัยแต่ละรายการที่คุณได้รับที่ปลายทางของคุณ ก่อนอื่นให้ตรวจสอบและถอดรหัสโทเค็น จากนั้นจัดการเหตุการณ์ความปลอดภัยตามความเหมาะสมกับบริการของคุณ จำเป็น ต้องตรวจสอบโทเค็นเหตุการณ์ก่อนถอดรหัสเพื่อป้องกันการโจมตีที่เป็นอันตรายจากผู้ไม่หวังดี ส่วนต่อไปนี้อธิบายงานเหล่านี้:

1. ถอดรหัสและตรวจสอบโทเค็นเหตุการณ์ความปลอดภัย

เนื่องจากโทเค็นเหตุการณ์ความปลอดภัยเป็นประเภทเฉพาะของ JWT คุณจึงสามารถใช้ไลบรารี JWT ใดก็ได้ เช่น ที่อยู่ในรายการ jwt.io เพื่อถอดรหัสและตรวจสอบความถูกต้อง ไม่ว่าคุณจะใช้ไลบรารี่ใด รหัสตรวจสอบความถูกต้องของโทเค็นต้องทำดังต่อไปนี้:

  1. รับตัวระบุผู้ออก Cross-Account Protection ( issuer ) และลงนามใบรับรองคีย์ URI ( jwks_uri ) จากเอกสารการกำหนดค่า RISC ของ Google ซึ่งคุณสามารถพบได้ที่ https://accounts.google.com/.well-known/risc-configuration
  2. ใช้ไลบรารี JWT ที่คุณเลือก รับ ID คีย์การลงนามจากส่วนหัวของโทเค็นเหตุการณ์ความปลอดภัย
  3. จากเอกสารรับรองคีย์การลงนามของ Google ให้รับคีย์สาธารณะที่มีรหัสคีย์ที่คุณได้รับในขั้นตอนก่อนหน้า หากเอกสารไม่มีคีย์ที่มี ID ที่คุณกำลังค้นหา เป็นไปได้ว่าโทเค็นเหตุการณ์ความปลอดภัยไม่ถูกต้อง และปลายทางของคุณควรส่งคืนข้อผิดพลาด HTTP 400
  4. ใช้ไลบรารี JWT ที่คุณเลือก ตรวจสอบสิ่งต่อไปนี้:
    • โทเค็นเหตุการณ์การรักษาความปลอดภัยได้รับการลงนามโดยใช้กุญแจสาธารณะที่คุณได้รับในขั้นตอนก่อนหน้า
    • การ aud สิทธิ์ของโทเค็นเป็นหนึ่งในรหัสไคลเอ็นต์ของแอปของคุณ
    • การอ้างสิทธิ์ iss ของโทเค็นตรงกับตัวระบุผู้ออกที่คุณได้รับจากเอกสารการค้นพบ RISC โปรดทราบว่าคุณไม่จำเป็นต้องตรวจสอบการหมดอายุของโทเค็น ( exp ) เนื่องจากโทเค็นเหตุการณ์ความปลอดภัยแสดงถึงเหตุการณ์ในอดีต จึงไม่หมดอายุ

ตัวอย่างเช่น:

Java

ใช้ java-jwt และ 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)

หากโทเค็นถูกต้องและถอดรหัสสำเร็จ ให้ส่งคืนสถานะ 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 เฉพาะของผู้ใช้ ( sub ) รหัสบัญชี Google นี้เป็นตัวระบุ ( sub ) เดียวกันกับที่มีอยู่ในโทเค็น JWT ID ที่ออกโดยไลบรารี Sign In With Google ( Javascript , HTML ) ที่ใหม่กว่า, ไลบรารี Google Sign-in แบบเดิม หรือ OpenID Connect เมื่อ subject_type ของการอ้างสิทธิ์คือ id_token_claims อาจมีฟิลด์ email พร้อมที่อยู่อีเมลของผู้ใช้

ใช้ข้อมูลใน events ที่อ้างว่าดำเนินการที่เหมาะสมสำหรับประเภทเหตุการณ์ในบัญชีของผู้ใช้ที่ระบุ

ประเภทเหตุการณ์ที่รองรับ

การป้องกันข้ามบัญชีรองรับเหตุการณ์ความปลอดภัยประเภทต่อไปนี้:

ประเภทงาน คุณลักษณะ วิธีการตอบสนอง
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked จำเป็น : รักษาความปลอดภัยให้กับบัญชีของผู้ใช้อีกครั้งโดยสิ้นสุดเซสชันที่เปิดอยู่ในปัจจุบัน
https://schemas.openid.net/secevent/oauth/event-type/tokens-revoked

จำเป็น : หากโทเค็นนั้นมีไว้สำหรับ Google Sign-in ให้ยุติเซสชันที่เปิดอยู่ในปัจจุบัน นอกจากนี้ คุณอาจต้องการแนะนำให้ผู้ใช้ตั้งค่าวิธีการลงชื่อเข้าใช้แบบอื่น

แนะนำ : หากโทเค็นนั้นมีไว้สำหรับการเข้าถึง Google API อื่นๆ ให้ลบโทเค็น OAuth ของผู้ใช้ที่คุณเก็บไว้

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

บังคับ : หากสาเหตุที่บัญชีถูกปิดใช้งานถูก hijacking ใช้ ให้รักษาความปลอดภัยบัญชีของผู้ใช้อีกครั้งโดยยุติเซสชันที่เปิดอยู่ในปัจจุบัน

แนะนำ : หากสาเหตุที่บัญชีถูกปิดใช้งานเป็น bulk-account ให้วิเคราะห์กิจกรรมของผู้ใช้ในบริการของคุณและพิจารณาการดำเนินการติดตามผลที่เหมาะสม

แนะนำ : หากไม่ได้ระบุเหตุผล ให้ปิดใช้งาน Google Sign-in สำหรับผู้ใช้และปิดใช้งานการกู้คืนบัญชีโดยใช้ที่อยู่อีเมลที่เชื่อมโยงกับบัญชี Google ของผู้ใช้ (โดยปกติคือบัญชี Gmail แต่ไม่จำเป็น) เสนอวิธีการลงชื่อเข้าใช้แบบอื่นแก่ผู้ใช้

https://schemas.openid.net/secevent/risc/event-type/account-enabled แนะนำ : เปิดใช้งาน Google Sign-in อีกครั้งสำหรับผู้ใช้ และเปิดใช้งานการกู้คืนบัญชีอีกครั้งด้วยที่อยู่อีเมลบัญชี 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 ที่อาจช่วยให้คุณดำเนินการ de-dup dataflow

โปรดทราบว่ากิจกรรมจะถูกส่งโดยจำกัดการลองใหม่ ดังนั้นหากผู้รับของคุณไม่ทำงานเป็นเวลานาน คุณอาจพลาดบางกิจกรรมอย่างถาวร

ลงทะเบียนผู้รับของคุณ

ในการเริ่มรับเหตุการณ์ความปลอดภัย ให้ลงทะเบียนเครื่องรับปลายทางของคุณโดยใช้ RISC API การเรียกไปยัง RISC API จะต้องมาพร้อมกับโทเค็นการให้สิทธิ์

คุณจะได้รับกิจกรรมความปลอดภัยสำหรับผู้ใช้แอปเท่านั้น ดังนั้นคุณต้อง กำหนดค่า หน้าจอคำยินยอม OAuth ในโครงการ GCP เป็นข้อกำหนดเบื้องต้นสำหรับขั้นตอนที่อธิบายไว้ด้านล่าง

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-jwt และ ห้องสมุดรับรองความถูกต้องของ 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')

โทเค็นการให้สิทธิ์นี้สามารถใช้เพื่อเรียก RISC API เป็นเวลาหนึ่งชั่วโมง เมื่อโทเค็นหมดอายุ ให้สร้างใหม่เพื่อดำเนินการเรียก RISC API ต่อไป

2. เรียก API การกำหนดค่าสตรีม RISC

ตอนนี้ คุณมีโทเค็นการให้สิทธิ์แล้ว คุณสามารถใช้ RISC API เพื่อกำหนดค่าสตรีมเหตุการณ์ความปลอดภัยของโปรเจ็กต์ของคุณ ซึ่งรวมถึงการลงทะเบียนปลายทางผู้รับของคุณ

ในการดำเนินการดังกล่าว ให้ส่งคำขอ HTTPS POST ไปที่ https://risc.googleapis.com/v1beta/stream:update โดยระบุปลายทางผู้รับและ ประเภทของเหตุการณ์ความปลอดภัยที่ คุณสนใจ:

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 แสดงว่าสตรีมเหตุการณ์ได้รับการกำหนดค่าสำเร็จแล้ว และปลายทางผู้รับของคุณควรเริ่มรับโทเค็นเหตุการณ์การรักษาความปลอดภัย ส่วนถัดไปจะอธิบายวิธีทดสอบการกำหนดค่าสตรีมและปลายทางเพื่อตรวจสอบว่าทุกอย่างทำงานร่วมกันอย่างถูกต้อง

รับและอัปเดตการกำหนดค่าสตรีมปัจจุบันของคุณ

หากคุณต้องการแก้ไขการกำหนดค่าสตรีมของคุณในอนาคต คุณสามารถทำได้โดยส่งคำขอ GET ที่ได้รับอนุญาตไปที่ https://risc.googleapis.com/v1beta/stream เพื่อรับการกำหนดค่าสตรีมปัจจุบัน แก้ไขเนื้อหาการตอบกลับ จากนั้นโพสต์การกำหนดค่าที่แก้ไขแล้วกลับไปที่ https://risc.googleapis.com/v1beta/stream:update ตามที่อธิบายไว้ข้างต้น

หยุดและกลับมาสตรีมกิจกรรมต่อ

หากคุณต้องการหยุดสตรีมกิจกรรมจาก Google ให้ส่งคำขอ POST ที่ได้รับอนุญาตไปที่ https://risc.googleapis.com/v1beta/stream/status:update ด้วย { "status": "disabled" } ในเนื้อหาคำขอ ในขณะที่สตรีมถูกปิดใช้งาน Google จะไม่ส่งกิจกรรมไปยังปลายทางของคุณและจะไม่บัฟเฟอร์เหตุการณ์ด้านความปลอดภัยเมื่อเกิดขึ้น หากต้องการเปิดใช้งานสตรีมเหตุการณ์อีกครั้ง ให้ POST { "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 endpoint ไม่ถูกต้องหรือไม่สามารถแยกวิเคราะห์ได้ โปรดใส่ $fieldname ในคำขอของคุณ
401 ไม่ได้รับอนุญาต การให้สิทธิ์ล้มเหลว ตรวจสอบให้แน่ใจว่าคุณได้แนบ โทเค็นการให้สิทธิ์ กับคำขอและโทเค็นนั้นถูกต้องและยังไม่หมดอายุ
403 ปลายทางการส่งต้องเป็น HTTPS URL ปลายทางการส่งของคุณ (เช่น ปลายทางที่คุณคาดว่าเหตุการณ์ RISC จะถูกส่งไป) จะต้องเป็น HTTPS เราไม่ส่งเหตุการณ์ RISC ไปยัง HTTP URL
403 การกำหนดค่าสตรีมที่มีอยู่ไม่มีวิธีการจัดส่งที่เป็นไปตามข้อกำหนดสำหรับ RISC โปรเจ็กต์ Google Cloud ของคุณต้องมีการกำหนดค่า RISC อยู่แล้ว หากคุณใช้ Firebase และเปิดใช้งาน Google Sign-In แล้ว Firebase จะจัดการ RISC สำหรับโปรเจ็กต์ของคุณ คุณจะไม่สามารถสร้างการกำหนดค่าแบบกำหนดเองได้ หากคุณไม่ได้ใช้ Google Sign-In สำหรับโปรเจ็กต์ Firebase ของคุณ โปรดปิดการใช้งาน จากนั้นลองอัปเดตอีกครั้งหลังจากผ่านไปหนึ่งชั่วโมง
403 ไม่พบโปรเจ็กต์ ตรวจสอบว่าคุณใช้บัญชีบริการที่ถูกต้องสำหรับโครงการที่ถูกต้อง คุณอาจกำลังใช้บัญชีบริการที่เชื่อมโยงกับโปรเจ็กต์ที่ถูกลบ เรียนรู้ วิธีดูบัญชีบริการทั้งหมดที่เชื่อมโยงกับโปรเจ็ กต์
403 บัญชีบริการต้องมีสิทธิ์แก้ไขในโปรเจ็กต์ของคุณ ไปที่คอนโซล Google Cloud Platform ของโปรเจ็กต์และให้สิทธิ์บัญชีบริการที่อนุญาตให้แก้ไขการโทร/เจ้าของโปรเจ็กต์ของคุณโดยทำตาม คำแนะนำเหล่านี้
403 API การจัดการสตรีมควรเรียกโดยบัญชีบริการเท่านั้น ต่อไปนี้เป็นข้อมูลเพิ่มเติมเกี่ยวกับ วิธีการเรียก Google API ด้วยบัญชีบริการ
403 ปลายทางการจัดส่งไม่ได้อยู่ในโดเมนของโครงการของคุณ ทุกโครงการมีชุด โดเมนที่ได้รับอนุญาต หากปลายทางการจัดส่งของคุณ (เช่น ปลายทางที่คุณคาดว่าเหตุการณ์ RISC จะถูกส่งไป) ไม่ได้โฮสต์ไว้ที่จุดใดจุดหนึ่ง เราจำเป็นต้องให้คุณเพิ่มโดเมนของปลายทางไปยังชุดนั้น
403 หากต้องการใช้ API นี้ โปรเจ็กต์ของคุณต้องมีไคลเอ็นต์ OAuth ที่กำหนดค่าไว้อย่างน้อยหนึ่งเครื่อง RISC ใช้งานได้เฉพาะเมื่อคุณสร้างแอปที่รองรับ Google Sign In การเชื่อมต่อนี้ต้องใช้ไคลเอ็นต์ OAuth หากโปรเจ็กต์ของคุณไม่มีไคลเอ็นต์ OAuth มีแนวโน้มว่า RISC จะไม่มีประโยชน์สำหรับคุณ เรียนรู้เพิ่มเติมเกี่ยวกับ การใช้ OAuth ของ Google สำหรับ API ของเรา
403

สถานะที่ไม่รองรับ

สถานะไม่ถูกต้อง

ขณะนี้เราสนับสนุนเฉพาะสถานะสตรีม " enabled " และ " disabled " เท่านั้น
404

โครงการไม่มีการกำหนดค่า RISC

โครงการไม่มีการกำหนดค่า RISC ที่มีอยู่ ไม่สามารถอัปเดตสถานะได้

เรียก https://risc.googleapis.com/v1beta/stream:update endpoint เพื่อสร้างการกำหนดค่าสตรีมใหม่
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