محافظت از حساب‌های کاربری با «محافظت بین‌حسابی»

اگر برنامه‌تان به کاربران اجازه می‌دهد بااستفاده از Google به سیستم حساب‌هایشان وارد شوند، می‌توانید با گوش دادن و پاسخ دادن به اعلان‌های رویداد امنیتی ارائه‌شده توسط سرویس «محافظت بین‌حسابی»، امنیت حساب‌های این کاربران مشترک را بهبود بخشید.

این اعلان‌ها تغییرات عمده در «حساب‌های Google» کاربران را به شما هشدار می‌دهند، که اغلب می‌تواند پیامدهای امنیتی برای حساب‌های آن‌ها در برنامه شما نیز داشته باشد. برای مثال، اگر «حساب Google» کاربری ربوده شود، می‌تواند به‌طور بالقوه منجر به به‌خطر افتادن حساب کاربر در برنامه شما ازطریق بازیابی حساب ایمیل یا استفاده از ورود به سیستم تکی شود.

برای کمک به شما در کاهش احتمال خطر چنین رویدادهایی، Google اشیاء سرویس شما را که توکن‌های رویداد امنیتی نامیده می‌شوند ارسال می‌کند. این توکن‌ها اطلاعات بسیار کمی را افشا می‌کنند (فقط نوع رویداد امنیتی و زمان وقوع آن، و شناسه کاربر تحت‌تأثیرقرارگرفته) اما می‌توانید از آن‌ها برای انجام اقدام مناسب در پاسخ استفاده کنید. برای مثال، اگر «حساب Google» کاربری به‌خطر افتاده باشد، می‌توانید «ورود به سیستم با Google» را موقتاً برای آن کاربر غیرفعال کنید و از ارسال ایمیل‌های بازیابی حساب به نشانی Gmail کاربر جلوگیری کنید.

«محافظت بین‌حسابی» براساس استاندارد RISC است که در «بنیاد OpenID» توسعه یافته است.

نمای کلی

برای استفاده از «محافظت بین‌حسابی» در برنامه یا سرویس خود، باید کارهای زیر را انجام دهید:

  1. پروژه‌تان را در «کنسول API» راه‌اندازی کنید.

  2. نقطه پایانی گیرنده رویداد ایجاد کنید تا Google بتواند کدهای امنیتی رویداد را به آن ارسال کند. این نقطه پایانی مسئولیت اعتبارسنجی نشانه‌های دریافتی را برعهده دارد و سپس به هر روشی که انتخاب کنید به رویدادهای امنیتی پاسخ می‌دهد.

  3. نقطه پایانی‌تان را در Google ثبت کنید تا دریافت کردن کدهای امنیتی رویداد را شروع کنید.

پیش‌نیاز

فقط برای کاربران Google که به سرویس شما اجازه دسترسی به اطلاعات نمایه یا نشانی‌های ایمیلشان را داده‌اند، کد رویداد امنیتی دریافت می‌کنید. با درخواست کردن دامنه‌های profile یا email، این اجازه را دریافت می‌کنید. کیت‌های توسعه نرم‌افزار جدیدتر ورود به سیستم با Google یا کیت‌های توسعه نرم‌افزار قدیمی‌تر ورود به سیستم با Google این دامنه‌ها را به‌طور پیش‌فرض درخواست می‌کنند، اما اگر از تنظیمات پیش‌فرض استفاده نمی‌کنید، یا اگر مستقیماً به نقطه پایانی OpenID Connect Google دسترسی دارید، مطمئن شوید که حداقل یکی از این دامنه‌ها را درخواست می‌کنید.

راه‌اندازی پروژه در «کنسول API»

قبل‌از اینکه بتوانید دریافت نشان‌های رویداد امنیتی را شروع کنید، باید حساب سرویسی ایجاد کنید و RISC API را در پروژه «کنسول API» خود فعال کنید. باید از همان پروژه «کنسول میانای برنامه‌سازی کاربردی» استفاده کنید که برای دسترسی به سرویس‌های Google، مثل «ورود به سیستم با Google»، در برنامه‌تان استفاده می‌کنید.

برای ایجاد حساب سرویس:

  1. صفحه اطلاعات کاربری کنسول API را باز کنید. وقتی از شما خواسته شد، پروژه «کنسول میانای برنامه‌سازی کاربردی» را که برای دسترسی به سرویس‌های Google در برنامه‌تان استفاده می‌کنید انتخاب کنید.

  2. روی ایجاد اطلاعات کاربری > حساب خدمات کلیک کنید.

  3. با دنبال کردن این دستورالعمل‌ها، حساب سرویس جدیدی با نقش «سرپرست پیکربندی RISC» (roles/riscconfigs.admin) ایجاد کنید.

  4. (اختیاری) اگر سازمان Google Cloud شما اجازه ایجاد کلید حساب خدمات را می‌دهد و قصد دارید JWTها را به‌صورت محلی امضا کنید، کلیدی برای حساب خدمات جدیدتان ایجاد کنید. نوع کلید JSON را انتخاب کنید و سپس روی ایجاد کلیک کنید. وقتی کلید ایجاد شد، فایل JSON حاوی اعتبارنامه‌های حساب سرویس را بارگیری خواهید کرد. این فایل را در جایی امن نگه دارید، اما همچنین برای نقطه پایانی گیرنده رویداد شما قابل‌دسترس باشد.

وقتی در صفحه «اطلاعات کاربری» پروژه‌تان هستید، شناسه‌های کارخواهی را که برای «ورود به سیستم با Google» یا «ورود به سیستم Google» (قدیمی) استفاده می‌کنید نیز یادداشت کنید. معمولاً برای هر پلاتفرمی که پشتیبانی می‌کنید، یک شناسه کارخواه دارید. به این شناسه‌های کارخواه برای اعتبارسنجی کردن توکن‌های رویداد امنیتی نیاز خواهید داشت، همان‌طور که در بخش بعدی توضیح داده شده است.

برای فعال کردن RISC API:

  1. صفحه RISC API را در «کنسول میانای برنامه‌سازی کاربردی» باز کنید. مطمئن شوید پروژه‌ای که برای دسترسی به سرویس‌های Google استفاده می‌کنید همچنان انتخاب شده باشد.

  2. شرایط RISC را بخوانید و مطمئن شوید که الزامات را درک کرده‌اید.

    اگر میانای برنامه‌سازی کاربردی را برای پروژه‌ای فعال می‌کنید که متعلق به سازمانی است، مطمئن شوید که مجاز هستید سازمانتان را به «شرایط RISC» ملزم کنید.

  3. فقط درصورتی روی فعال کردن کلیک کنید که با «شرایط RISC» موافقت کنید.

ایجاد نقطه پایانی گیرنده رویداد

برای دریافت اعلان‌های رویداد امنیتی از Google، نقطه پایانی HTTPS ایجاد می‌کنید که درخواست‌های HTTPS POST را مدیریت می‌کند. پس‌از ثبت این نقطه پایانی (به زیر مراجعه کنید)، Google شروع به پست کردن رشته‌های امضاشده با رمزنگاری به نام نشان‌های رویداد امنیتی به نقطه پایانی می‌کند. نشان‌های رویداد امنیتی، JWTهای امضاشده‌ای هستند که حاوی اطلاعاتی درباره یک رویداد مرتبط با امنیت هستند.

برای هر کد رویداد امنیتی که در نقطه پایانی‌تان دریافت می‌کنید، ابتدا کد را اعتبارسنجی و رمزگشایی کنید، سپس رویداد امنیتی را به‌طور مناسب برای سرویستان مدیریت کنید. برای جلوگیری از حملات مخرب ازسوی عاملان بدخواه، ضروری است که پیش‌از رمزگشایی، توکن رویداد را اعتبارسنجی کنید. بخش‌های زیر این تکالیف را شرح می‌دهند:

۱. رمزگشایی و اعتبارسنجی کردن کد امنیتی رویداد

چون توکن‌های رویداد امنیتی نوع خاصی از JWT هستند، می‌توانید از هر کتابخانه JWT، مثل کتابخانه‌های فهرست‌شده در jwt.io، برای رمزگشایی و اعتبارسنجی آن‌ها استفاده کنید. از هر کتابخانه‌ای که استفاده می‌کنید، کد اعتبارسنجی توکن شما باید کارهای زیر را انجام دهد:

  1. شناسه صادرکننده «محافظت بین‌حسابی» (issuer) و شناسه URI گواهی کلید امضا (jwks_uri) را از سند پیکربندی RISC‏ Google دریافت کنید. این سند را می‌توانید در https://accounts.google.com/.well-known/risc-configuration پیدا کنید.
  2. بااستفاده از کتابخانه JWT انتخابی‌تان، شناسه کلید امضا را از سرصفحه ژتون رویداد امنیتی دریافت کنید.
  3. از سند گواهینامه کلید امضای Google، کلید عمومی را با شناسه کلیدی که در مرحله قبل دریافت کردید دریافت کنید. اگر سند حاوی کلیدی با شناسه‌ای که به‌دنبال آن هستید نباشد، احتمالاً کد رویداد امنیتی نامعتبر است و نقطه پایانی شما باید خطای HTTP 400 را برگرداند.
  4. بااستفاده از کتابخانه JWT انتخابی‌تان، موارد زیر را تأیید کنید:
    • ژتون رویداد امنیتی بااستفاده از کلید عمومی که در مرحله قبل دریافت کردید امضا می‌شود.
    • ادعای aud از کد یکی از شناسه‌های مشتری برنامه‌های شما است.
    • ادعای iss از کد با شناسه صادرکننده‌ای که از سند اکتشاف RISC دریافت کرده‌اید مطابقت دارد. توجه داشته باشید که نیازی نیست انقضای کد (exp) را درستی‌سنجی کنید زیرا کدهای رویداد امنیتی نشان‌دهنده رویدادهای تاریخی هستند و بنابراین منقضی نمی‌شوند.

برای مثال:

جاوا

بااستفاده از 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‏ ۲۰۲ را برگردانید. سپس، رویداد امنیتی نشان‌داده‌شده توسط کد را مدیریت کنید.

۲. رسیدگی به رویدادهای امنیتی

وقتی رمزگشایی می‌شود، یک کد امنیتی رویداد شبیه به مثال زیر است:

{
  "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 است که توسط کتابخانه جدیدتر «ورود به سیستم با Google» (جاوا اسکریپت، HTML)، کتابخانه قدیمی ورود به سیستم با Google، یا OpenID Connect صادر شده است. وقتی subject_type ادعا id_token_claims باشد، ممکن است شامل فیلد email با نشانی ایمیل کاربر نیز باشد.

از اطلاعات موجود در ادعای events برای انجام اقدام مناسب برای نوع رویداد در حساب کاربر مشخص‌شده استفاده کنید.

شناسه‌های کد OAuth

برای رویدادهای OAuth درباره توکن‌های فردی، نوع شناسه موضوع توکن حاوی فیلدهای زیر است:

  • token_type: فقط از refresh_token پشتیبانی می‌شود.

  • token_identifier_alg: برای مقادیر احتمالی، جدول زیر را ببینید.

  • token: جدول زیر را ببینید.

token_identifier_alg رمز
prefix ‫۱۶ نویسه اول از کد.
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 است، هرکدام از کدهای 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 باید با یک کد مجوز همراه باشد.

رویدادهای امنیتی را فقط برای کاربران برنامه‌تان دریافت خواهید کرد، بنابراین باید صفحه رضایت OAuth پیکربندی‌شده در پروژه GCP خود داشته باشید تا بتوانید مراحل شرح‌داده‌شده در زیر را انجام دهید.

۱. تولید کردن کد مجوز

می‌توانید بااستفاده از Google Cloud CLI (gcloud) با جعل هویت حساب سرویس (توصیه‌شده هنگام اجرای iam.disableServiceAccountKeyCreation یا برای راه‌اندازی یک‌باره CLI) یا با امضای محلی JWT با کلید خصوصی حساب سرویس، یک توکن مجوز برای RISC API تولید کنید.

گزینه الف: تولید کد دسترسی کوتاه‌مدت بااستفاده از gcloud (کلید JSON لازم نیست)

اگر حساب کاربری شما نقش «ایجادکننده کد حساب خدمات» (roles/iam.serviceAccountTokenCreator) را در حساب خدمات داشته باشد، می‌توانید کد دسترسی OAuth 2.0 کوتاه‌مدت با محدوده پیکربندی RISC موردنیاز را مستقیماً از پایانه خودتان صادر کنید:

AUTH_TOKEN=$(gcloud auth print-access-token \
  --impersonate-service-account=SERVICE_ACCOUNT_EMAIL \
  --scopes=https://www.googleapis.com/auth/risc.configuration.readwrite,https://www.googleapis.com/auth/risc.verify,https://www.googleapis.com/auth/risc.status.readwrite)

برای جزئیات بیشتر درباره دامنه‌های OAuth 2.0 دردسترس برای RISC API، به دامنه‌های کد دسترسی مراجعه کنید.

گزینه ب: ایجاد JWT خودامضاشده بااستفاده از کلید حساب سرویس

یا برای تولید کردن توکن مجوز به‌صورت محلی بدون رفت‌وبرگشت شبکه، یک 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-jwt و کتابخانه auth‏ 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 ادامه دهید.

۲. فراخوانی میانای برنامه‌سازی کاربردی پیکربندی جاری‌سازی 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
  ]
}

برای مثال:

جاوا

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 با POST همان‌طور که در بالا توضیح داده شد انجام دهید.

متوقف کردن و ازسر گرفتن جاری‌سازی رویداد

اگر زمانی نیاز داشتید که جاری‌سازی رویداد از Google را متوقف کنید، یک درخواست POST مجاز به https://risc.googleapis.com/v1beta/stream/status:update با { "status": "disabled" } در بدنه درخواست ارسال کنید. وقتی جاری‌سازی غیرفعال است، Google رویدادها را به نقطه پایانی شما ارسال نمی‌کند و رویدادهای امنیتی را هنگام وقوع بافر نمی‌کند. برای فعال کردن مجدد جاری‌سازی رویداد، { "status": "enabled" } را به همان نقطه پایانی ارسال کنید.

۳. اختیاری: پیکربندی جاری‌سازی‌تان را آزمایش کنید

با ارسال کردن یک توکن درستی‌سنجی ازطریق جریان رویداد، می‌توانید درستی‌سنجی کنید که پیکربندی جریان و نقطه پایانی گیرنده به‌درستی باهم کار می‌کنند. این کد می‌تواند حاوی رشته‌ای منحصربه‌فرد باشد که می‌توانید از آن برای تأیید اینکه کد در نقطه پایانی شما دریافت شده است استفاده کنید. برای استفاده از این جریان، حتماً هنگام ثبت گیرنده، در نوع رویداد https://schemas.openid.net/secevent/risc/event-type/verification مشترک شوید.

برای درخواست کردن یک کد درستی‌سنجی، یک درخواست HTTPS POST مجاز به https://risc.googleapis.com/v1beta/stream:verify ارسال کنید. در بدنه درخواست، رشته شناسایی را مشخص کنید:

{
  "state": "ANYTHING"
}

برای مثال:

جاوا

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 برگردانده شود:

کد خطا پیام خطا کنش‌های پیشنهادی
۴۰۰ پیکربندی جاری‌سازی باید حاوی فیلد $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 را برای پروژه‌تان مدیریت خواهد کرد؛ نمی‌توانید پیکربندی سفارشی ایجاد کنید. اگر از «ورود به سیستم با Google» برای پروژه Firebase خود استفاده نمی‌کنید، لطفاً آن را غیرفعال کنید و سپس بعداز یک ساعت دوباره به‌روزرسانی کنید.
403 پروژه پیدا نشد. مطمئن شوید که از حساب سرویس صحیح برای پروژه صحیح استفاده می‌کنید. ممکن است از حساب سرویسی استفاده می‌کنید که با پروژه حذف‌شده‌ای مرتبط است. با نحوه دیدن همه حساب‌های خدماتی مرتبط با پروژه آشنا شوید.
403 حساب سرویس برای دسترسی به پیکربندی RISC شما به اجازه نیاز دارد به «کنسول میانای برنامه‌سازی کاربردی» پروژه‌تان بروید و با دنبال کردن این دستورالعمل‌ها، نقش «سرپرست پیکربندی RISC» (roles/riscconfigs.admin) را به حساب سرویسی که با پروژه‌تان تماس می‌گیرد اختصاص دهید.
403 میاناهای برنامه‌سازی کاربردی مدیریت جاری‌سازی فقط باید توسط حساب سرویس فراخوانی شوند. در اینجا اطلاعات بیشتری درباره نحوه فراخوانی Google API با حساب سرویس ارائه شده است.
403 نقطه پایانی تحویل به هیچ‌یک از دامنه‌های پروژه شما تعلق ندارد. هر پروژه مجموعه‌ای از دامنه‌های مجاز دارد. اگر نقطه پایانی تحویل شما (یعنی نقطه پایانی‌ای که انتظار دارید رویدادهای RISC به آن تحویل داده شود) در یکی از آن‌ها میزبانی نمی‌شود، لازم است دامنه نقطه پایانی را به آن مجموعه اضافه کنید.
403 برای استفاده از این API، پروژه شما باید حداقل یک کارخواه OAuth پیکربندی‌شده داشته باشد. RISC فقط درصورتی کار می‌کند که برنامه‌ای بسازید که از ورود به سیستم با Google پشتیبانی کند. این اتصال به کارخواه OAuth نیاز دارد. اگر پروژه‌تان کارخواه OAuth ندارد، احتمالاً RISC برایتان مفید نخواهد بود. درباره استفاده Google از OAuth برای میاناهای برنامه‌سازی کاربردی ما بیشتر بدانید.
403

وضعیت پشتیبانی‌نشده.

وضعیت نامعتبر است.

درحال‌حاضر فقط از وضعیت‌های جاری‌سازی «enabled» و «disabled» پشتیبانی می‌کنیم.
404

پروژه پیکربندی RISC ندارد.

پروژه پیکربندی RISC موجود ندارد، نمی‌توان وضعیت را به‌روز کرد.

برای ایجاد پیکربندی جاری‌سازی جدید، نقطه پایانی https://risc.googleapis.com/v1beta/stream:update را فراخوانی کنید.
4XX/5XX وضعیت به‌روزرسانی نشد. برای اطلاعات بیشتر، پیام خطای دقیق را بررسی کنید.

حوزه‌های کد دسترسی

اگر تصمیم گرفتید از کد دسترسی برای اصالت‌سنجی در RISC API استفاده کنید، این‌ها دامنه‌هایی هستند که برنامه‌تان باید درخواست کند:

نقطه پایانی Scope
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 پست کنید.