そのようなAPIを探したのですが、どうもないようです。
(もしご存知の方はご一報を!)
そこで、ドメイン管理者にのみ利用可能なApps APIである、Reporting APIを使用することとしました。
つまり、Reporting APIを実行してみて、結果が無事返ってくればドメイン管理者、
認証エラーが返ってきたらドメイン管理者ではない、と判断します。
しかし、Reporting APIを呼び出す際には、ユーザー名とパスワードが必要です。
もちろんアプリ側でユーザー名とパスワードを入力してもらう画面を作ればいいのですが、
そのユーザー名とパスワードはGoogleアカウントのものであり、自分のアプリに入力させたくありません。
(利用者からすればフィッシングにも見えてしまう)
せっかく認証にOpenIDを使ったのですから、ユーザー名とパスワードは自分のアプリに入力させたくないのです。
そこで、AuthSubという、Google側で認証を行い、認証が通れば、トークン(セッションIDのようなもの)をこちらに返してくれるサービスがありますので、それを使うことにしました。
ちなみに、ソースコードは、マーケットプレースのOpenID利用のサンプルソースコードを元にしています。
基本的な方法は、ここの方法と同じです。
Google App Engine 上で認証が必要な Google Data Feeds を取得する方法
import os, re from datetime import datetime from datetime import timedelta from urlparse import urlparse import gdata.auth from gdata import service from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext.webapp import template from google.appengine.ext.webapp import util import logging import gdata.apps.reporting import gdata.alt.appengine def check_email(user): """Performs basic validation of the supplied email address as outlined in http://code.google.com/googleapps/marketplace/best_practices.html """ domain = urlparse(user.federated_identity()).hostname m = re.search('.*@' + domain, user.email()) if m: return True else: return False class MainHandler(webapp.RequestHandler): def get(self): #まず最初にここが呼ばれます。 #ログインを確認した後、AuthSubの認証をするためのリンクをユーザーに返します。 #(ユーザーにクリックしてもらう) #ユーザーがクリックすると、Googleが、認証を許可するかどうかのページを表示します。 #ユーザーが認証を許可すると、gdata.auth.GenerateAuthSubUrlのnextに指定したurlに返ってきます。 #その際、認証トークンを、getパラメータに含めてくれます。 template_values = {} user = users.get_current_user() if user and check_email(user): next = 'https://***.appspot.com/check_domain_admin' #scopeは、許可対象のAPIを指定します。これはReporting APIです。 scope = ('https://www.google.com' '/hosted/services/v1.0/reports/ReportingData') secure = 0 session = 0 #1回限りのアクセスの場合は0(=False)。1(=True)にした場合は、トークンをセッションIDにアップグレードできます。 auth_url = gdata.auth.GenerateAuthSubUrl(next, scope, secure=secure, session=session) self.response.out.write("""<html><body> <a href="%s">Request token for the Google Documents Scope</a> </body></html>""" % auth_url) else: greeting = 'You need to log in!' template_values['greeting'] = greeting path = os.path.join(os.path.dirname(__file__), 'templates/index.html') self.response.out.write(template.render(path, template_values)) class CheckDomainAdmin(webapp.RequestHandler): def get(self): #認証を許可すると、ここが呼ばれます。(GenerateAuthSubUrlのnext) user = users.get_current_user() if user and check_email(user): self.response.out.write(user.email()) else: logging.info("user NOT exist") #トークンを取得します。これが欲しかったんです。 token = self.request.get("token") #GDataServiceの、run_on_appengineを実行する必要があります。 #これは、「GAEのurlfetchを使え」という指示だそうです。 srv = service.GDataService() gdata.alt.appengine.run_on_appengine(srv) #Reporting APIのpython-clientライブラリのReportRequestクラスを使います。 req = gdata.apps.reporting.ReportRequest() req.token = token req.domain = urlparse(user.federated_identity()).hostname prev_day = datetime.now() - timedelta(days=1) #当日だと、まだレポートがないよ、って怒られる場合があるので一日前 req.date = prev_day.strftime('%Y-%m-%d') req.report_name = "summary" #なんでもいいのですが、summaryで #Query url query = service.Query() query.feed = ('https://www.google.com' '/hosted/services/v1.0/reports/ReportingData') try: #converterは、デフォルトのGDataEntryFromStringがエラーになります。 feed = srv.Post(req.ToXml(), query.ToUri() ,converter=str) self.response.out.write(feed) #これは別にいらないです。確認してるだけ #Exceptionが発生しなければDomain Adminと判断します。 except gdata.service.RequestError,e: #Domain Adminでは無い場合、RequestErrorが発生します。 #このとき、POSTの戻り値は、<hs:reason>AuthenticationFailure(1006)</hs:reason>を含んでいます。 logging.info(e) class OpenIDHandler(webapp.RequestHandler): def get(self): """Begins the OpenID flow and begins Google Apps discovery for the supplied domain.""" self.redirect(users.create_login_url(dest_url='http://***.appspot.com/', _auth_domain=None, federated_identity=self.request.get('domain'))) def main(): application = webapp.WSGIApplication([('/', MainHandler), ('/check_domain_admin', CheckDomainAdmin), ('/_ah/login_required', OpenIDHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main()
当然ですが、「http://***.appspot.com」は自分のアプリに合わせてくださいね
Reporting APIのpython クライアントライブラリは、↓ここにあります。
google-apps-reporting-api-client
ソースコードではgdata.apps.reportingとしてインポートしているやつです。
最初はこのライブラリのReportRunnerクラスを使おうと思ったのですが、上手くいきませんでした。
ReportRunner.GetReportDataを実行すると、400 BadRequestが返ってきます。run_on_appengineが関係してる?
上記のソースコードでは、ReportRequestクラスを使ってるだけです。
Reporting APIのpython クライアントライブラリは、↓ここにあります。
google-apps-reporting-api-client
ソースコードではgdata.apps.reportingとしてインポートしているやつです。
最初はこのライブラリのReportRunnerクラスを使おうと思ったのですが、上手くいきませんでした。
ReportRunner.GetReportDataを実行すると、400 BadRequestが返ってきます。run_on_appengineが関係してる?
上記のソースコードでは、ReportRequestクラスを使ってるだけです。
マーケットプレイスを使っているのであれば、2LOでProvisioning APIを使うのがシンプルかと思います。
返信削除おお!こんなところまで見て頂けるとは!初コメントありがとうございます。
返信削除Provisioningだと、ドメイン管理で許可されていない場合に使えないかなーと思ったんです
あれでも、2LOでReportingAPIを使わなかった理由はなんだっけ・・
もう一度調べてみます。この「ダサイ」方法は嫌なんですよね
マーケットプレイスが前提の時点で、manifestのscopeに https://apps-apis.google.com/a/feeds/user/#readonly を含めておけば、インストールした=Provisioning APIの使用も承認した、という事になります。そんなワケでマーケットプレイス2LOはとても便利です。
返信削除そんなことができるんですか!ありがとうございます!
返信削除できました!あっさりとwありがとうございます!
返信削除