為什麼要進行網域驗證?
雖然 Cloud Channel API 允許您大規模佈建 Google 工作區,但客戶仍須採取以下行動才能啟用服務。
- 接受《服務條款》
- 驗證網域擁有權
- 設定 MX 記錄
新建立的客戶初次存取管理控制台 (admin.google.com) 時,請遵循引導式程序。
如果您透過程式存取網域的 DNS 記錄 (例如,您轉售網域給客戶),就能自動進行步驟 2 和 3 來提高啟用率,因為這些步驟通常需要有技術知識經銷商客戶。
本程式碼研究室說明如何使用網站驗證 API 實作這個自動化作業。
事前準備
請務必完成 API 設定程式碼研究室,以設定 Google Cloud 專案並建立服務帳戶,以呼叫 Cloud Channel API。
建議您使用這個 Test Channel Services Console 來使用這個程式碼研究室。
這個程式碼研究室也會預期您完成工作區端對端佈建程式碼研究室。
總覽
驗證 Google 工作區授權的網域涉及數種 API 呼叫。
Site Verification API 未開放給經銷商使用。網域驗證是用於各項 Google 產品 (Search Console、廣告等) 的信號。本文所述程序,將經銷商網域的超級管理員設為網域的「擁有者」,並將客戶的第一位管理員設為共同擁有者。如要進一步瞭解這些概念,請參閱開始使用 Site Verification API 頁面。
步驟 1:準備網站驗證 API
- 前往 Google Cloud Console 的「API Library」(API 資料庫) 區段,並啟用 Site Verification API。
- 使用經銷商網域的超級管理員前往全網域委派頁面。
- 在服務帳戶所在的列中,按一下 [Edit] (編輯)。
- 在「OAuth Scopes」(OAuth 範圍) 欄位中輸入
https://www.googleapis.com/auth/siteverification
。 - 按一下 [授權]。
- 安裝 Site Verification API 用戶端程式庫。
步驟 2:取得驗證憑證
這個程式碼研究室會著重於驗證網域最常見的方法:使用 TXT
DNS 記錄。Site Verification API 支援其他驗證方法。
如要擷取您要以 TXT
記錄形式放入的憑證,您必須取得 type=INET_DOMAIN
和 verificationMethod=DNS_TXT
的憑證。
將下列程式碼中的資訊填入下列程式碼。
jsonKeyFile
:建立服務帳戶時產生的 JSON 金鑰檔案路徑。resellerAdminUser
:經銷商網域超級管理員的電子郵件地址。customerDomain
:客戶的網域。如果您在 Test Channel Services Console 上執行此程式碼研究室,請確保網域遵循網域命名慣例。
C#
使用以下匯入作業:
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.SiteVerification.v1;
using Google.Apis.SiteVerification.v1.Data;
建立 API 用戶端並擷取憑證:
// Set up credentials with user impersonation
ICredential credential = GoogleCredential.FromFile(jsonKeyFile)
.CreateScoped("https://www.googleapis.com/auth/siteverification")
.CreateWithUser(resellerAdminUser);
// Create the API service
var verificationService = new SiteVerificationService(new BaseClientService.Initializer{
HttpClientInitializer = credential,
});
// Fetch the token
var request = new SiteVerificationWebResourceGettokenRequest {
VerificationMethod = "DNS_TXT",
Site = new SiteVerificationWebResourceGettokenRequest.SiteData {
Type = "INET_DOMAIN",
Identifier = customerDomain
}
};
var response = verificationService.WebResource.GetToken(request).Execute();
string token = response.Token;
Console.WriteLine("Site Verification token: " + token);
Go
使用以下匯入作業:
import (
"context"
"fmt"
"io/ioutil"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
"google.golang.org/api/siteverification/v1"
)
建立 API 用戶端並擷取憑證:
ctx := context.Background()
// Set up credentials with user impersonation
jsonKey, _ := ioutil.ReadFile(jsonKeyFile)
jwt, _ := google.JWTConfigFromJSON(jsonKey, "https://www.googleapis.com/auth/siteverification")
jwt.Subject = resellerAdminUser
tokenSource := jwt.TokenSource(ctx)
// Create the API Service
verificationService, _ := siteverification.NewService(ctx, option.WithTokenSource(tokenSource))
// Fetch the token
req := &siteverification.SiteVerificationWebResourceGettokenRequest{
Site: &siteverification.SiteVerificationWebResourceGettokenRequestSite{
Type: "INET_DOMAIN",
Identifier: customerDomain,
},
VerificationMethod: "DNS_TXT",
}
res, _ := verificationService.WebResource.GetToken(req).Do()
token := res.Token
fmt.Println("Site verification token: " + token)
Java
使用以下匯入作業:
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.siteVerification.SiteVerification;
import com.google.api.services.siteVerification.SiteVerificationScopes;
import com.google.api.services.siteVerification.model.SiteVerificationWebResourceGettokenRequest;
import com.google.api.services.siteVerification.model.SiteVerificationWebResourceGettokenResponse;
import com.google.api.services.siteVerification.model.SiteVerificationWebResourceResource;
import java.io.FileInputStream;
import java.util.Arrays;
建立 API 用戶端並擷取憑證:
// Set up credentials with user impersonation
FileInputStream jsonKeyFileSteam = new FileInputStream(JSON_KEY_FILE);
GoogleCredentials credentials = ServiceAccountCredentials.fromStream(jsonKeyFileSteam)
.createScoped("https://www.googleapis.com/auth/siteverification")
.createDelegated(RESELLER_ADMIN_USER);
// Create the API service
SiteVerification verificationService = new SiteVerification.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JacksonFactory.getDefaultInstance(),
new HttpCredentialsAdapter(credentials)).build();
// Fetch the token
SiteVerificationWebResourceGettokenRequest request =
new SiteVerificationWebResourceGettokenRequest()
.setVerificationMethod("DNS_TXT")
.setSite(new SiteVerificationWebResourceGettokenRequest.Site()
.setType("INET_DOMAIN")
.setIdentifier(CUSTOMER_DOMAIN));
SiteVerificationWebResourceGettokenResponse response =
verificationService.webResource().getToken(request).execute();
String token = response.getToken();
System.out.println("Site Verification token: " + token);
Node.js
使用以下匯入作業:
const {google} = require('googleapis');
建立 API 用戶端並擷取憑證:
// Set up credentials with user impersonation
const authJWT = new JWT({
keyFile: jsonKeyFile,
scopes: ['https://www.googleapis.com/auth/siteverification'],
subject: resellerAdminUser,
});
// Create the API service
const verificationService = google.siteVerification({version: 'v1', auth: authJWT});
// Fetch the token
const { data } = await verificationService.webResource.getToken({
requestBody: {
site: {
type: 'INET_DOMAIN',
identifier: customerDomain,
},
verificationMethod: 'DNS_TXT',
}
});
const token = data.token;
console.log(`Site Verification token: ${token}`);
PHP
建立 API 用戶端並擷取憑證:
// Set up credentials with user impersonation
$client = new Google_Client();
$client->setAuthConfig($JSON_KEY_FILE);
$client->setSubject($RESELLER_ADMIN_USER);
$client->setScopes('https://www.googleapis.com/auth/siteverification');
// Create the API service
$verificationService = new Google_Service_SiteVerification($client);
// Fetch the token
$request = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest([
'verificationMethod' => 'DNS_TXT',
'site' => [
'type' => 'INET_DOMAIN',
'identifier' => $CUSTOMER_DOMAIN
]
]);
$response = $verificationService->webResource->getToken($request);
$token = $response->token;
print 'Site Verification token: ' . $token . PHP_EOL;
Python
使用以下匯入作業:
from google.oauth2 import service_account
from apiclient.discovery import build
建立 API 用戶端並擷取憑證:
# Set up credentials with user impersonation
credentials = service_account.Credentials.from_service_account_file(
JSON_KEY_FILE, scopes=["https://www.googleapis.com/auth/siteverification"])
credentials_delegated = credentials.with_subject(RESELLER_ADMIN_USER)
# Create the API service
verification_service = build(serviceName="siteVerification", version="v1",
credentials=credentials_delegated)
# Fetch the token
response = verification_service.webResource().getToken(
body={
"site": {
"type": "INET_DOMAIN",
"identifier": CUSTOMER_DOMAIN
},
"verificationMethod": "DNS_TXT"
}).execute()
token = response["token"]
print("Site Verification token: " + token)
步驟 3:放置驗證憑證
撰寫程式碼,將憑證新增為客戶網域的 DNS 記錄中的 TXT
記錄。
如果是新網域,您可以為 Gmail 設定必要的 MX
記錄。
步驟 4:觸發網域驗證
將憑證新增為 TXT
記錄後,您可以呼叫 Site Verification API 來進行驗證。這是藉由呼叫 webResource.insert()
來實現的。
如果找不到預期的憑證,呼叫就會失敗並顯示 400 錯誤。您可以採用指數輪詢重試策略,直到呼叫成功完成 DNS 傳播延遲為止。
如果呼叫傳回沒有錯誤,Site Verification API 會確認要驗證網域,webResource
中 owners
欄位中的任何電子郵件都是已驗證的擁有者。
驗證狀態可能需要 3 小時的時間才會傳播到客戶的 Google 工作區帳戶中。您可以透過設定客戶的管理員 (在呼叫provisionCloudIdentity
) 當做owner
以下webResource
,才能使用 Android 手機或平板電腦尋找另一部裝置。
C#
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
string[] owners = { "admin@" + customerDomain };
var resource = new SiteVerificationWebResourceResource {
Site = new SiteVerificationWebResourceResource.SiteData {
Type = "INET_DOMAIN",
Identifier = customerDomain
},
Owners = owners
};
resource = verificationService.WebResource.Insert(resource, "DNS_TXT").Execute();
Console.WriteLine("=== Domain has been verified");
Go
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
resource := &siteverification.SiteVerificationWebResourceResource{
Site: &siteverification.SiteVerificationWebResourceResourceSite{
Type: "INET_DOMAIN",
Identifier: customerDomain,
},
Owners: []string{"admin@" + customerDomain},
}
resource, err := verificationService.WebResource.Insert("DNS_TXT", resource).Do()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("=== Domain has been verified")
}
Java
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
SiteVerificationWebResourceResource resource =
new SiteVerificationWebResourceResource()
.setSite(new SiteVerificationWebResourceResource.Site()
.setIdentifier(CUSTOMER_DOMAIN)
.setType("INET_DOMAIN"))
.setOwners(Arrays.asList("admin@" + CUSTOMER_DOMAIN));
resource = verificationService.webResource().insert("DNS_TXT", resource).execute();
System.out.println("=== Domain has been verified");
Node.js
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
await verificationService.webResource.insert({
verificationMethod: 'DNS_TXT',
requestBody: {
site: {
type: 'INET_DOMAIN',
identifier: customerDomain,
},
owners: [`admin@${customerDomain}`],
}
});
console.log('=== Domain has been verified');
PHP
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
$resource = new Google_Service_SiteVerification_SiteVerificationWebResourceResource([
'site' => [
'type' => 'INET_DOMAIN',
'identifier' => $CUSTOMER_DOMAIN,
],
'owners' => ['admin@' . $CUSTOMER_DOMAIN]
]);
$resource = $verificationService->webResource->insert('DNS_TXT', $resource);
print '=== Domain has been verified' . PHP_EOL;
Python
# Set the customer's admin user as an owner to make sure the domain
# verification status is instantly propagated to the Workspace account
resource = verification_service.webResource().insert(
verificationMethod="DNS_TXT",
body={
"site": {
"type": "INET_DOMAIN",
"identifier": CUSTOMER_DOMAIN
},
"owners": ["admin@" + CUSTOMER_DOMAIN]
}).execute()
print("=== Domain has been verified")