1

GmailガジェットでSSOを設定しようとしていますが、行き詰まります。ポップアップウィンドウでログインに成功しても、ユーザーを取得するためのリクエストを再試行しても、ユーザーを見つけることができないようです。

これが私のハンドラーです:

編集:更新されたコード。以下の回答からのコメントを参照してください。

# /
class MainPage(BaseHandler):
    def get(self):
        user = users.get_current_user()
        openid = self.request.get('opensocial_viewer_id')
        self.response.headers['Content-Type'] = 'text/plain'
        if user:
            if openid:
                logging.info('Pairing %s with OpenID %s' % (user.email(), openid))
                my_user = MyUser.query(MyUser.openid == openid).get()
                if not my_user:
                    my_user = MyUser(key=ndb.Key('MyUser', user.email()),
                                           email=user.email(),
                                           username=user.email().split('@')[0])
                my_user.openid = openid
                my_user.put()
            self.response.write('Hello, %s! You can close this window.' % user.email())
            return
        self.response.write('Hello, webapp2 World!')

# /openid/get_user
class OpenIdGetUserHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'application/json'
        openid = self.request.get('opensocial_viewer_id')
        user = MyUser.query(MyUser.openid == openid).get()
        if user:
            logging.info('MyUser with OpenID %s found' % openid)
            self.response.out.write(json.dumps({
                'user_exists': True,
                'user_email': user.email
            }))
            return
        logging.info('MyUser with OpenID %s not found. Checking if logged in.' % openid)
        self.response.out.write(json.dumps({
            'user_exists': False,
            'popup': 'https://myapp.appspot.com/openid/sign_in',
            'opensocial_viewer_id': openid
        }))

# /openid/sign_in
class OpenIdSignInHandler(webapp2.RequestHandler):
    def get(self):
        openid = self.request.get('opensocial_viewer_id')
        self.redirect(users.create_login_url(dest_url='/?opensocial_viewer_id=%s' % openid))

# /openid/sign_out
class OpenIdSignOutHandler(webapp2.RequestHandler):
    def get(self):
        self.redirect(users.create_logout_url(dest_url='/'))

そして、javscript(このガイドに基づく):

function fetchData() {
  // Hit the server, passing in a signed request (and OpenSocial ID), to see if we know who the user is.
  osapi.http.get({
    'href' : 'https://wmp-sugarcrm-gadget.appspot.com/openid/get_user',
    'format' : 'json',
    'authz' : 'signed'
  }).execute(handleLoadResponse);
}

function handleLoadResponse(data) {
  // User exists, OpenID must have occurred previously.
  if (data.content.user_exists) {
    //document.getElementById('output').innerHTML = 'user exists';
    showOneSection('main');
    console.log('Logged in');
    init();
  // User doesn't exist, need to do OpenID to match user ID to OpenID.
  } else {
    showOneSection('approval')
    var url_root = data.content.popup;
    // Retrieve the domain of the current user. gadgets.util.getUrlParameters()['parent'] returns a value
    // of of the form: http(s)://mail.google.com/mail/domain.com/html for Gmail (other containers are similar).
    // The example below shows a regular expression for use with Gmail. For Calendar, use this regular
    // expression instead: /calendar\/hosted\/([^\/]+)/
    var domain = gadgets.util.getUrlParameters()['parent'].match(/.+\/a\/(.+)\/html/)[1];

    var url = url_root + '?domain=' + domain;
        url += url + '&opensocial_viewer_id=' + encodeURIComponent(data.content.opensocial_viewer_id);

    var button = document.getElementById('personalize');
    button.setAttribute('href', 'javascript:void(0);');
    button.setAttribute('onclick', 'openPopup("' + url + '")');

  }
}

function openPopup(url) {
  var popup = window.open(url, 'OpenID','height=800,width=600');

  // Check every 100 ms if the popup is closed.
  finishedInterval = setInterval(function() {
    // If the popup is closed, we've either finished OpenID, or the user closed it. Verify with the server in case the
    // user closed the popup.
    if (popup.closed) {
      console.log('popup closed');
      osapi.http.get({
        'href' : 'https://myapp.appspot.com/openid/get_user',
        'format' : 'json',
        'authz' : 'signed'
      }).execute(handleLoadResponse);

      clearInterval(finishedInterval);
    }
  }, 100);
}

// Call fetchData() when gadget loads.
gadgets.util.registerOnLoadHandler(fetchData);

これまでのところ、ポップアップが起動し、サインインしてからアプリのホームページにリダイレクトし、ユーザーがログインしている場合はユーザーのメールアドレスを表示します。

ただし、ポップアップを閉じて再試行すると、ポップアップのホームページへのリダイレクトで正しいユーザーが返された場合でもfetchData()users.get_current_user()が返されます。None

私は何が欠けていますか?

4

1 に答える 1

2

コンテキスト ガジェットでは OpenId を使用できません。これは、ガジェットがすべてのリクエストをプロキシするガジェット コンテナ内に存在するためです。これが、ガイドが popupの回避策を示している正確な理由です。

ガジェット内のユーザーはID によって一意に定義されます

ポップアップ内から、OpenId 要求をサーバーに送信できます。これは、ガジェット コンテナーから抜け出すためです。一意の ID をサーバーに送信して、一意の ID をサーバー上の OpenId ユーザーにリンクできるようにします。

それ以降は、一意の ID を使用してガジェット内からリクエストを送信できます。ポップアップを介して呼び出しを行ったときに一意の ID と ID をリンクしたため、サーバーはユーザーの ID を認識します。

サーバー上で何らかの方法でこれを永続化する場合は、ポップアップで一意の ID <> ID の関係を 1 回だけ確立する必要があります。

于 2012-12-03T16:11:50.827 に答える