Pergunta

I'm trying to setup SSO with my gmail gadget, but I'm stuck. It seems that even though the log in succeeds in the popup window, retrying the request to get the user still can't find the user.

Here are my handlers:

EDIT: Updated code. See comment from answer below.

# /
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='/'))

And the javscript (based on this guide):

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);

So far, the popup launches, then I sign in, then redirects to my app's home page, showing the user's email address if he's logged in.

But when the popup is closed, thus retrying fetchData(), users.get_current_user() still returns None even if it returns the correct user in the redirect to the home page in the popup.

What am I missing?

Foi útil?

Solução

You cannot use OpenId in a contextual gadget, because the gagdet lives in a gadget container that proxies all requests. That is the exact reason that the guide shows you the workaround with the popup.

A user within a gadget is uniquely defined by a ID.

From within the popup, you can send an OpenId request to the server, because you break out of the gadget container. Send along the unique ID to the server so you can link the unique ID to the OpenId user on the server;

From then on, you can send requests from within your gadget using the unique ID. The server will know the idenity of the user because you linked the unique ID and the identity when you did the call through the popup.

You only have to establish the relation unique ID <> identity once with the popup if you persist this somehow on the server.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top