我正在使用gdata-python-client
访问Google Domain Shared Contacts API。
在企业应用程序中,您可能希望以编程方式访问用户数据,而无需他们进行任何手动授权。
有一个名为2LO(2脚OAuth)的协议,但似乎它已被弃用的OAuth1链接:“重要:不推荐使用OAuth 1.0,并关闭新OAuth 1.0客户端的注册。”已遍布Oauth1 docs。
“Domain-wide Delegation of Authority”有一个基于OAuth2的新配方:
在Google Apps域中,域管理员可以向第三方应用程序授予对其用户数据的域范围内访问权限 - 这称为域范围的授权。要以这种方式委派权限,域管理员可以将服务帐户与OAuth 2.0一起使用。
这适用于google-api-python-client
,但不适用于gdata-python-client
。
问题:有没有办法用Python实现这一目标?似乎来自gdata客户端的代码是史前的 - 是否有任何其他GAE运行时具有支持数据API委派的现代客户端库?
[更新]
如果我签署了一个httplib2连接,并在我能够检索到Feed时调用Atom端点。
http = httplib2.Http()
http = credentials.authorize(http)
resp, content = http.request(
'https://www.google.com/m8/feeds/contacts/default/full', 'GET'
)
不幸的是gdata-python-client
使用httplib而不是httplib2。
[解决]
也许我错过了一些步骤,但在我们使用httplib2执行调用之前看起来令牌无效。我必须在运行[aeijdenberg]答案中给出的样本之前运行上面的代码,否则我得到401。
答案 0 :(得分:9)
以下是如何使用gdata库在Google App Engine中使用Python进行域范围委派的示例:
在“API& Auth”下启用您需要使用的API(此处不显示某些gdata API,如果是这样,请跳过此步骤。)
在“API& Auth”下 - > “凭据”创建服务帐户类型的新OAuth2客户端ID。记下电子邮件地址和客户端ID,并将下载的私钥保存到安全位置。
作为域管理员,请转到管理控制台(https://admin.google.com/AdminHome),导航至“安全” - > “高级设置” - > “托管第三方OAuth客户端访问”。
将之前的完整客户端ID粘贴到“客户端名称”字段中,然后将API访问所需的范围粘贴到范围字段中。
由于我们在Google App Engine上运行,我们需要将PKCS12格式的私钥转换为PEM格式(因为目前部署在Google App Engine上的PyCrypto库不支持PCKS12):
cat secret-privatekey.p12 | openssl pkcs12 -nodes -nocerts -passin pass:notasecret | openssl rsa > secret-privatekey.pem
将此文件放入您的应用目录。
从https://code.google.com/p/google-api-python-client/downloads/list下载Google API Python客户端,选择google-api-python-client-gae-1.2.zip
。
在您的应用目录中解压缩:
unzip ~/Downloads/google-api-python-client-gae-1.2.zip
从https://code.google.com/p/gdata-python-client/downloads/list下载gdata python客户端,选择gdata-2.0.18.zip
。
在您的app目录中安装:
unzip ~/Downloads/gdata-2.0.18.zip
mv gdata-2.0.18/src/* .
rm -rf gdata-2.0.18/
确保PyCrypto已在本地安装(但不在您的应用程序目录中):
sudo easy_install pycrypto
在app.yaml
中,将PyCrypto添加为库:
libraries:
- name: pycrypto
version: "2.6"
声明以下助手类:
import httplib2
class TokenFromOAuth2Creds:
def __init__(self, creds):
self.creds = creds
def modify_request(self, req):
if self.creds.access_token_expired or not self.creds.access_token:
self.creds.refresh(httplib2.Http())
self.creds.apply(req.headers)
使用私钥创建SignedJwtAssertionCredentials
对象:
from oauth2client.client import SignedJwtAssertionCredentials
credentials = SignedJwtAssertionCredentials(
"<service account email>@developer.gserviceaccount.com",
file("secret-privatekey.pem", "rb").read(),
scope=["http://www.google.com/m8/feeds/"],
prn="<user to impersonate>@your-domain.com"
)
创建一个gdata客户端并使用它:
gd_client = gdata.contacts.client.ContactsClient('your-domain.com')
gd_client.auth_token = TokenFromOAuth2Creds(credentials)
xxx = gd_client.get_contacts()