Nếu ứng dụng của bạn cho phép người dùng đăng nhập vào tài khoản của họ bằng Google, thì bạn có thể cải thiện bảo mật tài khoản của những người dùng chung này bằng cách lắng nghe và phản hồi thông báo sự kiện bảo mật do dịch vụ Bảo vệ nhiều tài khoản cung cấp.
Những thông báo này cảnh báo bạn về những thay đổi lớn đối với Tài khoản Google của người dùng, thường cũng có thể ảnh hưởng đến bảo mật cho tài khoản của họ trong ứng dụng của bạn. Ví dụ: nếu Tài khoản Google của người dùng bị xâm nhập, thì có thể dẫn đến việc tài khoản của người dùng trong ứng dụng của bạn bị xâm phạm thông qua quy trình khôi phục tài khoản email hoặc việc sử dụng tính năng đăng nhập một lần.
Để giúp bạn giảm thiểu rủi ro tiềm ẩn của những sự kiện như vậy, Google sẽ gửi cho dịch vụ của bạn các đối tượng được gọi là mã thông báo sự kiện bảo mật. Những mã thông báo này hiển thị rất ít thông tin (chỉ có loại sự kiện bảo mật, thời điểm xảy ra và giá trị nhận dạng của người dùng bị ảnh hưởng) nhưng bạn có thể sử dụng chúng để thực hiện hành động thích hợp nhằm ứng phó. Ví dụ: nếu Tài khoản Google của người dùng bị xâm phạm, bạn có thể tạm thời tắt tính năng Đăng nhập bằng Google cho người dùng đó và ngăn email khôi phục tài khoản được gửi đến địa chỉ Gmail của người dùng.
Tính năng Bảo vệ nhiều tài khoản dựa trên tiêu chuẩn RISC do OpenID Foundation phát triển.
Tổng quan
Để sử dụng tính năng Bảo vệ nhiều tài khoản với ứng dụng hoặc dịch vụ của mình, bạn phải hoàn tất các nhiệm vụ sau:
Thiết lập dự án trong API Console.
Tạo một điểm cuối của trình nhận sự kiện, nơi Google sẽ gửi mã thông báo sự kiện bảo mật. Điểm cuối này chịu trách nhiệm xác thực mã thông báo mà nó nhận được, sau đó phản hồi các sự kiện bảo mật theo bất kỳ cách nào bạn chọn.
Đăng ký điểm cuối của bạn với Google để bắt đầu nhận mã thông báo sự kiện bảo mật.
Điều kiện tiên quyết
Bạn chỉ nhận được mã thông báo sự kiện bảo mật cho những người dùng Google đã cấp cho dịch vụ của bạn quyền truy cập vào thông tin hồ sơ hoặc địa chỉ email của họ. Bạn có thể nhận được quyền này bằng cách yêu cầu phạm vi profile hoặc email. SDK Đăng nhập bằng Google mới hơn hoặc SDK Đăng nhập bằng Google cũ yêu cầu các phạm vi này theo mặc định, nhưng nếu bạn không sử dụng chế độ cài đặt mặc định hoặc nếu bạn truy cập trực tiếp vào điểm cuối OpenID Connect của Google, hãy đảm bảo bạn đang yêu cầu ít nhất một trong các phạm vi này.
Thiết lập dự án trong API Console
Trước khi có thể bắt đầu nhận mã thông báo sự kiện bảo mật, bạn phải tạo một tài khoản dịch vụ và bật API RISC trong dự án API Console. Bạn phải sử dụng cùng một dự án API Console mà bạn dùng để truy cập vào các dịch vụ của Google, chẳng hạn như Đăng nhập bằng Google, trong ứng dụng của bạn.
Cách tạo tài khoản dịch vụ:
Mở trang Thông tin xác thực của API Console. Khi được nhắc, hãy chọn dự án API Console mà bạn dùng để truy cập vào các dịch vụ của Google trong ứng dụng của mình.
Nhấp vào Tạo thông tin xác thực > Tài khoản dịch vụ.
Tạo một tài khoản dịch vụ mới có vai trò Quản trị viên cấu hình RISC (
roles/riscconfigs.admin) bằng cách làm theo hướng dẫn này.(Không bắt buộc) Nếu tổ chức Google Cloud của bạn cho phép tạo khoá tài khoản dịch vụ và bạn dự định ký JWT trên thiết bị, hãy tạo một khoá cho tài khoản dịch vụ mới tạo. Chọn loại khoá JSON rồi nhấp vào Tạo. Khi khoá được tạo, bạn sẽ tải một tệp JSON chứa thông tin đăng nhập tài khoản dịch vụ xuống. Hãy lưu tệp này ở nơi an toàn nhưng cũng phải đảm bảo điểm cuối của trình nhận sự kiện có thể truy cập được.
Khi bạn đang ở trang Thông tin xác thực của dự án, hãy lưu ý đến mã ứng dụng khách mà bạn dùng cho tính năng Đăng nhập bằng Google hoặc Đăng nhập bằng Google (cũ). Thông thường, bạn có một mã ứng dụng khách cho mỗi nền tảng mà bạn hỗ trợ. Bạn sẽ cần những mã ứng dụng khách này để xác thực mã thông báo sự kiện bảo mật, như mô tả trong phần tiếp theo.
Cách bật RISC API:
Mở trang RISC API trong API Console. Đảm bảo rằng bạn vẫn chọn dự án mà bạn dùng để truy cập vào các dịch vụ của Google.
Đọc Điều khoản RISC và đảm bảo bạn hiểu rõ các yêu cầu.
Nếu bạn đang bật API cho một dự án thuộc sở hữu của một tổ chức, hãy đảm bảo bạn được uỷ quyền để ràng buộc tổ chức của mình với Điều khoản RISC.
Chỉ nhấp vào Bật nếu bạn đồng ý với Điều khoản RISC.
Tạo điểm cuối của trình nhận sự kiện
Để nhận thông báo sự kiện bảo mật từ Google, bạn cần tạo một điểm cuối HTTPS xử lý các yêu cầu POST qua HTTPS. Sau khi bạn đăng ký điểm cuối này (xem bên dưới), Google sẽ bắt đầu đăng các chuỗi được ký bằng mật mã (gọi là mã thông báo sự kiện bảo mật) lên điểm cuối. Mã thông báo sự kiện bảo mật là các JWT đã ký, chứa thông tin về một sự kiện liên quan đến bảo mật.
Đối với mỗi mã thông báo sự kiện bảo mật mà bạn nhận được tại điểm cuối, trước tiên, hãy xác thực và giải mã mã thông báo, sau đó xử lý sự kiện bảo mật sao cho phù hợp với dịch vụ của bạn. Bạn bắt buộc phải xác thực mã thông báo sự kiện trước khi giải mã để ngăn chặn các cuộc tấn công độc hại từ các đối tượng xấu. Các phần sau đây mô tả những việc cần làm này:
1. Giải mã và xác thực mã thông báo sự kiện bảo mật
Vì mã thông báo sự kiện bảo mật là một loại JWT cụ thể, nên bạn có thể sử dụng bất kỳ thư viện JWT nào, chẳng hạn như thư viện được liệt kê trên jwt.io, để giải mã và xác thực các mã thông báo đó. Dù bạn sử dụng thư viện nào, mã xác thực mã thông báo của bạn cũng phải làm những việc sau:
- Lấy giá trị nhận dạng của tổ chức phát hành tính năng Bảo vệ nhiều tài khoản (
issuer) và URI chứng chỉ khoá ký (jwks_uri) từ tài liệu cấu hình RISC của Google. Bạn có thể tìm thấy tài liệu này tạihttps://accounts.google.com/.well-known/risc-configuration. - Sử dụng thư viện JWT mà bạn chọn, lấy mã khoá ký từ tiêu đề của mã thông báo sự kiện bảo mật.
- Trong tài liệu chứng chỉ khoá ký của Google, hãy lấy khoá công khai có mã khoá mà bạn nhận được ở bước trước. Nếu tài liệu không chứa khoá có mã nhận dạng mà bạn đang tìm, thì có thể mã thông báo sự kiện bảo mật không hợp lệ và điểm cuối của bạn sẽ trả về lỗi HTTP 400.
- Sử dụng thư viện JWT mà bạn chọn, hãy xác minh những thông tin sau:
- Mã thông báo sự kiện bảo mật được ký bằng khoá công khai mà bạn nhận được ở bước trước.
- Xác nhận quyền sở hữu
audcủa mã thông báo là một trong các mã ứng dụng khách của ứng dụng. - Xác nhận quyền sở hữu
isscủa mã thông báo khớp với giá trị nhận dạng của công ty phát hành mà bạn nhận được từ tài liệu khám phá RISC. Xin lưu ý rằng bạn không cần xác minh thời gian hết hạn của mã thông báo (exp) vì mã thông báo sự kiện bảo mật đại diện cho các sự kiện trong quá khứ và do đó, không hết hạn.
Ví dụ:
Java
Sử dụng java-jwt và 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)
Nếu mã thông báo hợp lệ và được giải mã thành công, hãy trả về trạng thái HTTP 202. Sau đó, hãy xử lý sự kiện bảo mật được mã thông báo chỉ định.
2. Xử lý sự kiện bảo mật
Khi được giải mã, mã thông báo sự kiện bảo mật sẽ có dạng như ví dụ sau:
{
"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"
}
}
}
Xác nhận quyền sở hữu iss và aud cho biết tổ chức phát hành mã thông báo (Google) và người nhận dự kiến của mã thông báo (dịch vụ của bạn). Bạn đã xác minh các thông báo xác nhận quyền sở hữu này ở bước trước.
Xác nhận quyền sở hữu jti là một chuỗi xác định một sự kiện bảo mật duy nhất và là duy nhất đối với luồng. Bạn có thể sử dụng giá trị nhận dạng này để theo dõi những sự kiện bảo mật
mà bạn đã nhận được.
Xác nhận quyền sở hữu events chứa thông tin về sự kiện bảo mật mà mã thông báo đại diện. Xác nhận quyền sở hữu này là mối liên kết từ giá trị nhận dạng loại sự kiện đến một xác nhận quyền sở hữu subject, trong đó chỉ định người dùng mà sự kiện này liên quan và mọi thông tin chi tiết bổ sung về sự kiện có thể có.
Xác nhận quyền sở hữu subject xác định một người dùng cụ thể bằng Mã Tài khoản Google duy nhất của người dùng đó (sub). Mã Tài khoản Google này là cùng một giá trị nhận dạng (sub) có trong mã thông báo JWT ID do thư viện Đăng nhập bằng Google (Javascript, HTML) mới hơn, thư viện Đăng nhập bằng Google cũ hoặc OpenID Connect cấp. Khi subject_type của thông báo xác nhận quyền sở hữu là id_token_claims, thông báo này cũng có thể bao gồm trường email có địa chỉ email của người dùng.
Sử dụng thông tin trong thông báo events để thực hiện hành động thích hợp cho loại sự kiện trên tài khoản của người dùng được chỉ định.
Giá trị nhận dạng mã thông báo OAuth
Đối với các sự kiện OAuth về mã thông báo riêng lẻ, loại giá trị nhận dạng token subject (đối tượng mã thông báo) chứa các trường sau:
token_type: Chỉ hỗ trợrefresh_token.token_identifier_alg: Xem bảng bên dưới để biết các giá trị có thể có.token: Xem bảng bên dưới.
| token_identifier_alg | token |
|---|---|
prefix |
16 ký tự đầu tiên của mã thông báo. |
hash_base64_sha512_sha512 |
Hàm băm kép của mã thông báo sử dụng SHA-512. |
Nếu tích hợp với các sự kiện này, bạn nên lập chỉ mục mã thông báo dựa trên các giá trị có thể có này để đảm bảo khớp nhanh khi nhận được sự kiện.
Các loại sự kiện được hỗ trợ
Tính năng Bảo vệ nhiều tài khoản hỗ trợ các loại sự kiện bảo mật sau:
| Loại sự kiện | Thuộc tính | Cách phản hồi |
|---|---|---|
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked |
Bắt buộc: Bảo mật lại tài khoản của người dùng bằng cách kết thúc các phiên hiện đang mở của họ. | |
https://schemas.openid.net/secevent/oauth/event-type/tokens-revoked |
Bắt buộc: Nếu mã thông báo là dành cho tính năng Đăng nhập bằng Google, hãy chấm dứt các phiên hiện đang mở của người dùng. Ngoài ra, bạn nên đề xuất người dùng thiết lập một phương thức đăng nhập thay thế. Đề xuất: Nếu mã thông báo là để truy cập vào các API khác của Google, hãy xoá mọi mã thông báo OAuth của người dùng mà bạn đã lưu trữ. |
|
https://schemas.openid.net/secevent/oauth/event-type/token-revoked |
Hãy xem phần Giá trị nhận dạng mã thông báo OAuth để biết giá trị nhận dạng mã thông báo |
Bắt buộc: Nếu bạn lưu trữ mã làm mới tương ứng, hãy xoá mã đó và yêu cầu người dùng đồng ý lại vào lần tiếp theo cần mã truy cập. |
https://schemas.openid.net/secevent/risc/event-type/account-disabled |
reason=hijacking,reason=bulk-account |
Bắt buộc: Nếu lý do tài khoản bị vô hiệu hoá là Đề xuất: Nếu lý do tài khoản bị vô hiệu hoá là Đề xuất: Nếu không có lý do nào được đưa ra, hãy tắt tính năng Đăng nhập bằng Google cho người dùng và tắt tính năng khôi phục tài khoản bằng địa chỉ email được liên kết với Tài khoản Google của người dùng (thường là tài khoản Gmail, nhưng không nhất thiết). Cung cấp cho người dùng một phương thức đăng nhập thay thế. |
https://schemas.openid.net/secevent/risc/event-type/account-enabled |
Đề xuất: Bật lại tính năng Đăng nhập bằng Google cho người dùng và bật lại tính năng khôi phục tài khoản bằng địa chỉ email của Tài khoản Google của người dùng. | |
https://schemas.openid.net/secevent/risc/event-type/account-credential-change-required |
Đề xuất: Chú ý đến hoạt động đáng ngờ trên dịch vụ của bạn và thực hiện hành động thích hợp. | |
https://schemas.openid.net/secevent/risc/event-type/verification |
state=state | Đề xuất: Ghi nhật ký rằng đã nhận được mã thông báo thử nghiệm. |
Sự kiện trùng lặp và bị bỏ lỡ
Tính năng Bảo vệ nhiều tài khoản sẽ cố gắng gửi lại những sự kiện mà tính năng này cho rằng chưa được gửi. Do đó, đôi khi bạn có thể nhận được cùng một sự kiện nhiều lần. Nếu điều này có thể gây ra các hành động lặp lại gây bất tiện cho người dùng, hãy cân nhắc sử dụng thông báo xác nhận quyền sở hữu jti (là giá trị nhận dạng riêng biệt cho một sự kiện) để loại bỏ các sự kiện trùng lặp. Có các công cụ bên ngoài như Google Cloud Dataflow có thể giúp bạn thực thi luồng dữ liệu loại bỏ trùng lặp.
Xin lưu ý rằng các sự kiện được gửi với số lần thử lại có giới hạn, vì vậy, nếu trình nhận của bạn ngừng hoạt động trong một khoảng thời gian dài, bạn có thể bỏ lỡ vĩnh viễn một số sự kiện.
Đăng ký thiết bị nhận
Để bắt đầu nhận các sự kiện bảo mật, hãy đăng ký điểm cuối của trình nhận bằng API RISC. Các lệnh gọi đến RISC API phải đi kèm với mã uỷ quyền.
Bạn sẽ chỉ nhận được sự kiện bảo mật cho người dùng ứng dụng của mình, vì vậy, bạn cần định cấu hình màn hình xin phép bằng OAuth trong dự án GCP của mình làm điều kiện tiên quyết cho các bước được mô tả bên dưới.
1. Tạo mã thông báo uỷ quyền
Bạn có thể tạo mã uỷ quyền cho RISC API bằng cách sử dụng
Google Cloud CLI (gcloud) với tính năng mạo danh tài khoản dịch vụ (nên dùng khi iam.disableServiceAccountKeyCreation
được thực thi hoặc để thiết lập CLI một lần) hoặc bằng cách ký JWT cục bộ bằng
khoá riêng tư của tài khoản dịch vụ.
Cách A: Tạo mã truy cập ngắn hạn bằng gcloud (Không cần khoá JSON)
Nếu tài khoản người dùng của bạn có vai trò Người tạo mã thông báo tài khoản dịch vụ (roles/iam.serviceAccountTokenCreator) trên tài khoản dịch vụ, thì bạn có thể tạo mã truy cập OAuth 2.0 ngắn hạn có phạm vi cấu hình RISC bắt buộc ngay trong thiết bị đầu cuối:
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)
Hãy xem phần Phạm vi của mã truy cập để biết thêm thông tin về các phạm vi OAuth 2.0 hiện có cho RISC API.
Lựa chọn B: Tạo JWT tự ký bằng khoá tài khoản dịch vụ
Ngoài ra, để tạo mã thông báo uỷ quyền cục bộ mà không cần khứ hồi mạng, hãy tạo một JWT có các thông báo xác nhận quyền sở hữu sau:
{
"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
}Ký JWT bằng khoá riêng tư của tài khoản dịch vụ. Bạn có thể tìm thấy khoá này trong tệp JSON mà bạn đã tải xuống khi tạo khoá tài khoản dịch vụ.
Ví dụ:
Java
Sử dụng java-jwt và thư viện xác thực của 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')
Bạn có thể dùng mã thông báo uỷ quyền này để thực hiện lệnh gọi API RISC trong một giờ. Khi mã thông báo hết hạn, hãy tạo một mã thông báo mới để tiếp tục thực hiện lệnh gọi RISC API.
2. Gọi API cấu hình luồng RISC
Giờ đây, khi đã có mã thông báo uỷ quyền, bạn có thể sử dụng RISC API để định cấu hình luồng sự kiện bảo mật của dự án, bao gồm cả việc đăng ký điểm cuối của trình nhận.
Để làm việc này, hãy gửi một yêu cầu POST qua HTTPS đến https://risc.googleapis.com/v1beta/stream:update,
chỉ định điểm cuối của bên nhận và loại sự kiện
bảo mật mà bạn quan tâm:
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
]
}
Ví dụ:
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'])
Nếu yêu cầu trả về HTTP 200, thì luồng sự kiện đã được định cấu hình thành công và điểm cuối nhận của bạn sẽ bắt đầu nhận được mã thông báo sự kiện bảo mật. Phần tiếp theo mô tả cách bạn có thể kiểm thử cấu hình luồng và điểm cuối để xác minh mọi thứ đang hoạt động chính xác cùng nhau.
Lấy và cập nhật cấu hình hiện tại của sự kiện phát trực tiếp
Nếu sau này bạn muốn sửa đổi cấu hình luồng, bạn có thể thực hiện bằng cách gửi yêu cầu GET được uỷ quyền đến https://risc.googleapis.com/v1beta/stream để lấy cấu hình luồng hiện tại, sửa đổi nội dung phản hồi, sau đó POST cấu hình đã sửa đổi trở lại https://risc.googleapis.com/v1beta/stream:update như mô tả ở trên.
Dừng và tiếp tục luồng sự kiện
Nếu bạn cần dừng luồng sự kiện từ Google, hãy gửi một yêu cầu POST được uỷ quyền đến https://risc.googleapis.com/v1beta/stream/status:update kèm theo { "status": "disabled" } trong nội dung yêu cầu. Khi luồng bị vô hiệu hoá, Google sẽ không gửi sự kiện đến điểm cuối của bạn và không lưu sự kiện bảo mật vào vùng đệm khi sự kiện xảy ra. Để bật lại luồng sự kiện, hãy gửi yêu cầu POST { "status": "enabled" } đến cùng một điểm cuối.
3. Không bắt buộc: Kiểm tra cấu hình luồng
Bạn có thể xác minh rằng cấu hình luồng và điểm cuối của trình nhận đang hoạt động chính xác cùng nhau bằng cách gửi mã xác minh thông qua luồng sự kiện. Mã thông báo này có thể chứa một chuỗi riêng biệt mà bạn có thể dùng để xác minh rằng mã thông báo đã được nhận tại điểm cuối của bạn. Để sử dụng quy trình này, hãy nhớ đăng ký loại sự kiện https://schemas.openid.net/secevent/risc/event-type/verification khi đăng ký trình nhận.
Để yêu cầu mã xác minh, hãy gửi một yêu cầu POST qua HTTPS được uỷ quyền đến https://risc.googleapis.com/v1beta/stream:verify. Trong phần nội dung của yêu cầu, hãy chỉ định một số chuỗi nhận dạng:
{
"state": "ANYTHING"
}
Ví dụ:
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()))
Nếu yêu cầu thành công, mã xác minh sẽ được gửi đến điểm cuối mà bạn đã đăng ký. Sau đó, ví dụ: nếu điểm cuối của bạn xử lý mã xác minh bằng cách chỉ cần ghi nhật ký, thì bạn có thể kiểm tra nhật ký để xác nhận rằng mã thông báo đã được nhận.
Tài liệu tham khảo về mã lỗi
RISC API có thể trả về các lỗi sau:
| Mã lỗi | Thông báo lỗi | Hành động đề xuất |
|---|---|---|
| 400 | Cấu hình luồng phải chứa trường $fieldname. | Yêu cầu của bạn đến điểm cuối https://risc.googleapis.com/v1beta/stream:update không hợp lệ hoặc không thể phân tích cú pháp. Vui lòng thêm $fieldname vào yêu cầu của bạn. |
| 401 | Không được uỷ quyền. | Cấp phép không thành công. Hãy nhớ đính kèm mã uỷ quyền vào yêu cầu và đảm bảo rằng mã đó hợp lệ và chưa hết hạn. |
| 403 | Điểm cuối phân phối phải là một URL loại HTTPS. | Điểm cuối phân phối (tức là điểm cuối mà bạn muốn các sự kiện RISC được phân phối đến) phải là HTTPS. Chúng tôi không gửi sự kiện RISC đến URL loại HTTP. |
| 403 | Cấu hình luồng hiện tại không có phương thức phân phối tuân thủ thông số kỹ thuật cho RISC. | Dự án trên đám mây của bạn phải có cấu hình RISC. Nếu bạn đang sử dụng Firebase và đã bật tính năng Đăng nhập bằng Google, thì Firebase sẽ quản lý RISC cho dự án của bạn; bạn sẽ không thể tạo cấu hình tuỳ chỉnh. Nếu bạn không sử dụng tính năng Đăng nhập bằng Google cho dự án Firebase, vui lòng tắt tính năng này rồi thử cập nhật lại sau một giờ. |
| 403 | Không tìm thấy dự án. | Hãy đảm bảo bạn đang sử dụng đúng tài khoản dịch vụ cho đúng dự án. Có thể bạn đang sử dụng một tài khoản dịch vụ liên kết với một dự án đã bị xoá. Tìm hiểu cách xem tất cả tài khoản dịch vụ liên kết với một dự án. |
| 403 | Tài khoản dịch vụ cần có quyền truy cập vào cấu hình RISC của bạn | Chuyển đến API Console của dự án và
chỉ định vai trò "Quản trị viên cấu hình RISC"
(roles/riscconfigs.admin)
cho tài khoản dịch vụ đang thực hiện lệnh gọi đến dự án của bạn bằng cách
làm theo
các hướng dẫn này.
|
| 403 | Chỉ tài khoản dịch vụ mới được gọi API quản lý luồng. | Sau đây là thông tin chi tiết về cách gọi API của Google bằng tài khoản dịch vụ. |
| 403 | Điểm cuối phân phối không thuộc bất kỳ miền nào trong dự án của bạn. | Mỗi dự án đều có một nhóm miền được uỷ quyền. Nếu điểm cuối phân phối của bạn (tức là điểm cuối mà bạn muốn các sự kiện RISC được phân phối đến) không được lưu trữ trên một trong các miền đó, thì bạn phải thêm miền của điểm cuối vào nhóm đó. |
| 403 | Để sử dụng API này, dự án của bạn phải có ít nhất một ứng dụng OAuth được định cấu hình. | RISC chỉ hoạt động nếu bạn xây dựng một ứng dụng hỗ trợ tính năng Đăng nhập bằng Google. Kết nối này cần có một ứng dụng OAuth. Nếu dự án của bạn không có ứng dụng OAuth, thì có thể RISC sẽ không hữu ích cho bạn. Tìm hiểu thêm về cách Google sử dụng OAuth cho các API của chúng tôi. |
| 403 |
Trạng thái không được hỗ trợ. Trạng thái không hợp lệ. |
Hiện tại, chúng tôi chỉ hỗ trợ các trạng thái luồng phát là "enabled" và "disabled". |
| 404 |
Dự án không có cấu hình RISC. Dự án không có cấu hình RISC hiện tại, không thể cập nhật trạng thái. |
Gọi điểm cuối https://risc.googleapis.com/v1beta/stream:update để tạo cấu hình luồng mới. |
| 4XX/5XX | Không thể cập nhật trạng thái. | Hãy kiểm tra thông báo lỗi chi tiết để biết thêm thông tin. |
Phạm vi mã truy cập
Nếu bạn quyết định sử dụng mã truy cập để xác thực với RISC API, thì đây là các phạm vi mà ứng dụng của bạn phải yêu cầu:
| Điểm cuối | Phạm vi |
|---|---|
https://risc.googleapis.com/v1beta/stream/status |
https://www.googleapis.com/auth/risc.status.readonly
HOẶC 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
HOẶC 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 |
Bạn cần trợ giúp?
Trước tiên, hãy xem phần tham chiếu mã lỗi của chúng tôi. Nếu bạn vẫn còn thắc mắc, hãy đăng câu hỏi lên Stack Overflow kèm theo thẻ #SecEvents.