Google Data Protocol 用戶端程式庫中的 AuthSub

警告:本頁面說明 Google 的舊版 API (即 Google Data API);該 API 只與 Google Data API 目錄中列出的 API 相關,其中許多 API 已由新版 API 取代。如需特定新的 API 的相關資訊,請參閱新 API 的說明文件。如要瞭解如何使用新版 API 授權要求,請參閱 Google 帳戶驗證與授權

本文件說明如何使用 Google Data API 用戶端程式庫連線至 Google 的網路應用程式 AuthSub 驗證

AuthSub 介面可讓網頁式應用程式代表使用者存取 Google 服務。為了維持高安全性,AuthSub 介面可讓應用程式取得驗證權杖,而無需處理使用者帳戶的登入資訊。

Google Data API 用戶端程式庫提供許多方法,可協助您在網路應用程式中使用 AuthSub。具體來說,您可以透過以下方法建構要求網址、取得一次性驗證權杖、交換單次使用憑證憑證,以及簽署要求。

注意:JavaScript 用戶端程式庫有自己的 AuthSub 版本,稱為 AuthSubJS。如要瞭解如何在 JavaScript 應用程式中使用 AuthSubJS,請參閱搭配 JavaScript 用戶端程式庫使用「AuthSub」驗證一文。

目標對象

本文件的適用對象,是想讓網頁式應用程式代表使用者使用 Google Data API 用戶端程式庫,存取 Google 服務的程式。

本文假設您已熟悉 AuthSub 介面,以及將 AuthSub 整合至網頁應用程式的一般程序。如需 AuthSub 通訊協定的完整說明,請參閱網路應用程式的 AuthSub 驗證

在沒有用戶端程式庫的情況下使用 AuthSub 和 Google Data API

如果您希望網路應用程式用戶端使用 AuthSub 做為驗證系統來與 Google Data 服務互動,您需要瞭解的一切資訊都位於網路應用程式的 SubSub 驗證。如果不想使用 Google Data API 用戶端程式庫,則不需要使用。

以下概述您的應用程式可能如何使用 AuthSub 驗證使用者:

您的應用程式會建構適當的 AuthSub 網址,並將使用者傳送至該網址,以便使用者登入;AuthSub 系統會傳回使用者在您網站上指定的網址,並傳回一次性的符記;您的應用程式會選擇性將該憑證用於工作階段憑證,然後應用程式會在「Authorization 標頭」中傳送憑證,而應用程式會把要求傳送至服務。

Google Data API 用戶端程式庫會為您處理各種詳細資訊,藉此簡化這項授權程序。本文將說明如何進行。

使用 AuthSub 和 Google Data API:用戶端程式庫範例

本節提供 Google Data API 用戶端程式庫方法的實作範例,請按照 AuthSub 說明文件中使用 AuthSub 一節所述步驟進行。

在此範例中,我們將 AuthSub 介面整合至與「Google 日曆」互動的網路應用程式 (但是您不需要知道任何關於「Google 日曆」的說明)。此範例假設網路應用程式託管於 example.com

決定要使用的權杖類型 (session=0session=1)

您可以選擇使用一次性符記 (session=0) 或工作階段符記 (session=1)。 如 AuthSub 說明文件所述,如果您決定在網路應用程式中使用工作階段符記,則必須自行管理憑證儲存空間。本文件不涵蓋憑證管理。另請注意,使用 session=0 要求的權杖日後無法交換 (升級) 至長期工作階段符記。

決定要註冊網路應用程式 (secure=0secure=1)

AuthSub 可用於三種不同的模式,分別是「未註冊」、「已註冊」,以及透過安全機制註冊。本文件的其餘部分將以最後一個選項做為安全 AuthSub。雖然未註冊/註冊模式的設定比安全 AuthSub 來得簡單,但我們建議您使用安全權杖來強化安全性。

登記方式

選擇 [註冊網頁式應用程式] 可讓您的應用程式享有下列好處:

  1. 安全性較高。
  2. 值得 Google 信賴 (在「授權」頁面上不會向使用者顯示警告)。

已註冊 + 安全驗證

如果您決定使用安全 AuthSub,除了註冊網路應用程式之外,您還需要建立一個自行簽署的 RSA 私密金鑰和公開憑證組合。 如需建立 X.509 憑證的範例,請參閱產生用於已註冊模式的金鑰和憑證

決定資料存取的範圍

每個 Google 服務都定義了 scope 值,用於決定 (也可能縮小) 符記對於使用者資料的存取權。如需可用 scope 值的清單,請參閱常見問題

我們決定與 Google Calendar API 互動,因此 scope 應為 http://www.google.com/calendar/feeds/

注意:除非您需要更精細的限制條件,否則務必將範圍值設為最廣泛的網址。 舉例來說,範圍較窄的 scope=http://www.google.com/calendar/feeds/default/allcalendars/full 等範圍會限制符記只能存取全日曆/完整資訊提供。使用 scope=http://www.google.com/calendar/feeds/ 將允許存取所有日曆的動態消息:http://www.google.com/calendar/feeds/*

多範圍憑證

如要建立可存取多個 Google Data API 的權杖,請以網址編碼空間來分隔每個範圍。以下範例會建立憑證,可用來存取使用者的 Google 聯絡人和 Google 日曆資料。

scope=http://www.google.com/calendar/feeds/%20http://www.google.com/m8/feeds/

要求一次性驗證權杖

如要取得特定使用者和特定服務的 AuthSub 憑證,您的應用程式必須將使用者重新導向 AuthSubRequest 網址,藉此提示他們登入自己的 Google 帳戶。(如要進一步瞭解 AuthSubRequest 網址,請參閱完整的網路應用程式 AuthSub 驗證)。

如要建構 AuthSubRequest 網址,請針對每個用戶端程式庫使用以下內容:

Java

import com.google.gdata.client.*;

String nextUrl = "http://www.example.com/RetrieveToken.jsp";
String scope = "http://www.google.com/calendar/feeds/";
boolean secure = false;  // set secure=true to request secure AuthSub tokens
boolean session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);

如果您要驗證 G Suite 網域的使用者,請按照下列步驟操作:

import com.google.gdata.client.*;

String hostedDomain = "example.com";
String nextUrl = "http://www.example.com/RetrieveToken.jsp";
String scope = "http://www.google.com/calendar/feeds/";
boolean secure = false;  // set secure=true to request AuthSub tokens
boolean session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);

.NET

using Google.GData.Client;

String nextUrl = "http://www.example.com/RetrieveToken.aspx";
String scope = "http://www.google.com/calendar/feeds/";
bool secure = false; // set secure=true to request secure AuthSub tokens
bool session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);

如果您要驗證 G Suite 網域的使用者,請按照下列步驟操作:

using Google.GData.Client;

String hostedDomain = "example.com";
String nextUrl = "http://www.example.com/RetrieveToken.aspx";
String scope = "http://www.google.com/calendar/feeds/";
bool secure = false; // set secure=true to request secure AuthSub tokens
bool session = true;
String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);

PHP

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');

$nextUrl = 'http://www.example.com/RetrieveToken.php';
$scope = 'http://www.google.com/calendar/feeds/';
$secure = 0;  // set $secure=1 to request secure AuthSub tokens
$session = 1;
$authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session);

如果您要驗證 G Suite 網域的使用者,請按照下列步驟操作:

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');

$hostedDomain = 'example.com';
$nextUrl = 'http://www.example.com/RetrieveToken.php';
$scope = 'http://www.google.com/calendar/feeds/';
$secure = 0;  // set $secure=1 to request secure AuthSub tokens
$session = 1;
$authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session) . '&hd=' . $hostedDomain;

Python

import gdata.auth

next = 'http://www.example.com/RetrieveToken.pyc'
scope = 'http://www.google.com/calendar/feeds/'
secure = False  # set secure=True to request secure AuthSub tokens
session = True
auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session)

如果您要驗證 G Suite 網域的使用者,請按照下列步驟操作:

import gdata.auth

hosted_domain = 'example.com'
next = 'http://www.example.com/RetrieveToken.pyc'
scope = 'http://www.google.com/calendar/feeds/'
secure = False  # set secure=True to request secure AuthSub tokens
session = True
auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session, domain=hosted_domain)

建構「下一個」網址之後,您的應用程式可透過各種方式,將使用者傳送至 AuthSubRequest 處理常式。最常見的方法是顯示網頁,告訴使用者他們必須點選連結,授權您的應用程式存取自己的 Google 帳戶,然後將要求網址附加到連結中。例如,您可以在網路應用程式中輸出下列字串:

String authorizationUrl =
        "<p>MyApp needs access to your Google Calendar account to read your Calendar feed. " +
        "To authorize MyApp to access your account, <a href=\"" + authSubUrl + "\">log in to your account</a>.</p>";

使用者前往 Google 的 AuthSub 頁面連結,然後進行登入。然後,AuthSub 系統使用您提供的「下一個」網址將使用者重新導向回您的應用程式。

擷取單次使用的權杖

當 Google 重新導向至您的應用程式時,這個權杖會附加為「下一步」網址做為查詢參數。以上述範例為例,使用者登入後,Google 就會重新導向至類似網址 (例如 http://www.example.com/RetrieveToken?token=DQAADKEDE)。 您的應用程式應從其網址查詢參數擷取符記值。

如果您的應用程式會在傳送給使用者至 AuthSub 系統之前設定使用者驗證 Cookie,當 Google 傳回「下一個」網址時,應用程式可以讀取驗證 Cookie,以識別已到達該網址的使用者。您可以使用這類 Cookie,將應用程式中的 User-ID 與從 Google 擷取的 AuthSub 憑證建立關聯。

用戶端程式庫會提供單一擷取權杖的便利方法:

Java

String singleUseToken = AuthSubUtil.getTokenFromReply(httpServletRequest.getQueryString());

.NET

String singleUseToken = Request.QueryString["token"];
// or
String singleUseToken = AuthSubUtil.getTokenFromReply(new Uri(Request.QueryString));

PHP

$singleUseToken = $_GET['token'];

Python

current_url = 'http://' + req.hostname + req.unparsed_uri
# Unlike the other calls, extract_auth_sub_token_from_url() will create an AuthSubToken or SecureAuthSubToken object.
# Use str(single_use_token) to return the token's string value.
single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url)

如果您使用安全 AuthSub,請務必設定 RSA 私密金鑰,以建立 SecureAuthSubToken

f = open('/path/to/yourRSAPrivateKey.pem')
rsa_key = f.read()
f.close()
current_url = 'http://' + req.hostname + req.unparsed_uri
# Unlike the other calls, extract_auth_sub_token_from_url() will create an AuthSubToken or SecureAuthSubToken object.
# Use str(single_use_token) to return the token's string value.
single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url, rsa_key=rsa_key)

要求工作階段符記

從網址擷取的符記一律是一次性的符記,下一步是使用 AuthSubSessionToken 網址,為長期工作階段工作階段憑證升級憑證,如完整的網路應用程式適用的 AuthSub 驗證說明文件中所述。如果您使用安全 AuthSub,則必須先設定 RSA 私密金鑰,才能進行交換。以下列舉每個使用用戶端程式庫的範例:

Java

import com.google.gdata.client.*;
import com.google.gdata.client.calendar.*;

String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null);

CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0");
calendarService.setAuthSubToken(sessionToken, null);

// ready to interact with Calendar feeds

如要使用安全的 AuthSub,請將 RSA 私密金鑰傳送到 exchangeForSessionToken (而不是貼上 null):

import com.google.gdata.client.*;
import com.google.gdata.client.calendar.*;

java.security.PrivateKey privateKey =
    AuthSubUtil.getPrivateKeyFromKeystore("AuthSubExample.jks", "privKeyPa$$word", "AuthSubExample", "privKeyPa$$word");
String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, privateKey);

CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0");
calendarService.setAuthSubToken(sessionToken, privateKey);

// ready to interact with Calendar feeds

.NET

using Google.GData.Client;
using Google.GData.Calendar;

String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null).ToString();

GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0");
authFactory.Token = (String) sessionToken;

CalendarService calendarService = new CalendarService(authFactory.ApplicationName);
calendarService.RequestFactory = authFactory;

// ready to interact with Calendar feeds

如要使用安全的 AuthSub,請將 RSA 私密金鑰傳送到 exchangeForSessionToken (而不是貼上 null):

using Google.GData.Client;
using Google.GData.Calendar;

protected AsymmetricAlgorithm getRsaKey()
{
  X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx", "privKeyPa$$word");
  RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider;
  return privateKey;
}

AsymmetricAlgorithm rsaKey = getRsaKey();
String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, rsaKey).ToString();

GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0");
authFactory.Token = (String) sessionToken;
authFactory.PrivateKey = rsaKey;

CalendarService calendarService = new CalendarService(authFactory.ApplicationName);
calendarService.RequestFactory = authFactory;

// ready to interact with Calendar feeds

PHP

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_Calendar');

$sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken);

// Create a Calendar service object and set the session token for subsequent requests
$calendarService = new Zend_Gdata_Calendar(null, 'google-ExampleApp-v1.0');
$calendarService->setAuthSubToken($sessionToken);

// ready to interact with Calendar feeds

如要使用安全的 AuthSub,廣告交易平台會要求您先使用 Zend_Gdata_HttpClient 設定 setAuthSubPrivateKeyFile(),並設定 RSA 私密金鑰:

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_Calendar');

$client = new Zend_Gdata_HttpClient();
$client->setAuthSubPrivateKeyFile('/path/to/myrsakey.pem', null, true);
$sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken, $client);

$calendarService = new Zend_Gdata_Calendar($client, 'google-ExampleApp-v1.0');
$calendarService->setAuthSubToken($sessionToken);

// ready to interact with Calendar feeds

Python

import gdata.calendar
import gdata.calendar.service

calendar_service = gdata.calendar.service.CalendarService()
calendar_service.UpgradeToSessionToken(single_use_token)  # calls gdata.service.SetAuthSubToken() for you

# ready to interact with Calendar feeds

附註:只要您使用 gdata.auth.extract_auth_sub_token_from_url(url, rsa_key=rsa_key) 擷取單次使用權杖,安全的 AuthSub 程序也會相同。

注意:使用安全 AuthSub 時,私密金鑰本身不會透過網路傳送。用戶端程式庫會使用您的金鑰簽署要求 (而非金鑰本身),藉此產生專屬簽章。

使用工作階段符記

您可以使用工作階段符記來驗證伺服器的要求,方法是將權杖放入 Authorization 標頭中,如 AuthSub 說明文件所述。

設定工作階段符記後,您可以使用標準 Google Data API 用戶端程式庫呼叫來與服務互動,而不必考慮憑證。詳細資訊請參閱您所使用服務和語言的 Google Data API 用戶端程式庫相關指南和 Google Data API 開發人員指南。

擷取工作階段符記的相關資訊

如果您要測試用戶端和伺服器是否同意憑證參數,您可以將憑證傳遞至 AuthSubTokenInfo 處理常式,以傳回含有憑證相關資訊的一組名稱/值組合。

Java

Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, null);

如果您使用的是安全 AuthSub,請傳入您的 RSA 私密金鑰:

Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, privateKey);

.NET

Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, null);

如果您使用的是安全 AuthSub,請傳入您的 RSA 私密金鑰:

Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, privateKey);

PHP

$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken);

如果您使用的是安全 AuthSub,請傳入 Zend_Gdata_HttpClient,讓系統使用您的 RSA 私密金鑰簽署要求:

$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken, $client);

Python

token_info = calendar_service.AuthSubTokenInfo()

撤銷工作階段符記

AuthSub 工作階段符記不會過期,用戶端可視需要儲存工作階段符記。

因此,當用戶端使用工作階段符記完成用戶端時,可使用 AuthSub 說明文件,使用 AuthSubRevokeToken 處理常式撤銷憑證。

例如,如果您想以傳統的工作階段來管理權杖,則您的用戶端可在使用者工作階段開始時取得憑證,並在使用者工作階段結束時將其撤銷。

如要撤銷憑證,請在各個用戶端程式庫中使用以下內容:

Java

AuthSubUtil.revokeToken(sessionToken, null);

如果您使用的是安全 AuthSub,請傳入您的 RSA 私密金鑰:

AuthSubUtil.revokeToken(sessionToken, privateKey);

.NET

AuthSubUtil.revokeToken(sessionToken, null);

如果您使用的是安全 AuthSub,請傳入您的 RSA 私密金鑰:

AuthSubUtil.revokeToken(sessionToken, privateKey);

PHP

$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken);

如果您使用的是安全 AuthSub,請傳入 Zend_Gdata_HttpClient,讓系統使用您的 RSA 私密金鑰簽署要求:

$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken, $client);

Python

calendar_service.RevokeAuthSubToken()

其他資源和樣本

返回頁首

產生自行簽署私密金鑰與公開憑證,以便與安全的 AuthSub 搭配使用

您必須使用私密金鑰產生簽章,每筆要求中都必須包含簽名。Google 會使用憑證中嵌入的公開金鑰來驗證簽名。公開金鑰必須是 1024 位元 RSA 金鑰,並以 PEM 格式的 X.509 憑證編碼。應於註冊時將憑證傳送給 Google。

以下各節說明如何使用 OpenSSL 公用程式和 Java 的 keytool 公用程式產生金鑰和憑證。

這些範例不限於 Google Data API,因此您可以使用相同的公用程式產生用於任何目的的金鑰。

以下範例假設貴公司名稱為 My_Company,並且位在美國加州山景城,網域名稱為 example.com。

使用 OpenSSL 產生金鑰

如要建立一組 RSA 金鑰和對應的憑證,您可以使用下列指令:

# Generate the RSA keys and certificate
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \
  '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \
  myrsakey.pem -out /tmp/myrsacert.pem

警告:加入 -nodes 參數後,系統會建立沒有密碼的私密金鑰以保護金鑰。 不過,為了加強安全性,請考慮省略這個參數。

-sha1 參數會指定該金鑰將用來產生 SHA1 簽名。

-subj 參數會指定憑證代表的應用程式身分。

-keyout 參數會指定要包含金鑰的檔案。 這個檔案含有機密資訊,因此不應與任何人共用。

-out 參數會指定要納入 PEM 格式憑證的檔案 (註冊時可在 Google 上找到)。

正在產生 .NET 用戶端的金鑰

.NET 架構無法解讀以 PEM 格式儲存的金鑰或憑證。因此,建立 .pem 檔案之後,您必須進行一個額外步驟:

openssl pkcs12 -export -in test_cert.pem -inkey myrsacert.pem -out myrsacert.pfx -name "Testing Certificate"

這個步驟會產生私密金鑰和憑證產生的 PFX 檔案。這個檔案可匯入 .NET 用戶端程式庫,以數位方式簽署對 Google Data API 發出的要求。

為 Java 用戶端產生金鑰

Java 用戶端接受採用 PKCS#8 格式的私密金鑰。使用上述指示產生金鑰/憑證後,請透過您產生的 .pem 檔案建立 .pk8 檔案:

openssl pkcs8 -in myrsakey.pem -topk8 -nocrypt -out myrsakey.pk8

或者,您也可以使用 Java Key Store 和 keytool 公用程式來建立一對 RSA 金鑰以及對應的憑證。使用下列指令:

# Generate the RSA keys and certificate
keytool -genkey -v -alias Example -keystore ./Example.jks\
  -keyalg RSA -sigalg SHA1withRSA\
  -dname "CN=www.example.com, OU=Engineering, O=My_Company, L=Mountain  View, ST=CA, C=US"\
  -storepass changeme -keypass changeme

警告:「changeme」不是很好的密碼,這只是範例。

-dname 參數會指定憑證代表的應用程式身分。-storepass 參數會指定保護 KeyStore 的密碼。-keypass 參數會指定保護私密金鑰的密碼。

如要將憑證寫入可在 ManageDomains 工具中使用的檔案,請使用下列指令:

# Output the public certificate to a file
keytool -export -rfc -keystore ./Example.jks -storepass changeme \
  -alias Example -file mycert.pem

返回頁首