App Engine remote_api with OpenID

混江龙づ霸主 提交于 2019-12-02 23:57:34

This was a fun one.

Looking at remote_api, the flow for authentication seems to be something like this:

I couldn't find a lot of documentation on the new OpenID support, though Nick's blog entry was informative.

Here's the test app I wrote to see how things work:

app.yaml:

handlers:
- url: /remote_api
  script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
  login: admin
- url: /.*
  script: test.py

test.py:

class MainPage(webapp.RequestHandler):
  def get(self):
    user = users.get_current_user()
    if user:
      self.response.out.write("Hi, %s!<hr>admin is %s" % (user.user_id(),
        users.is_current_user_admin()))
    else:
      self.redirect(users.create_login_url('/', None,
        'https://www.google.com/accounts/o8/id'))

Flipping my auth mode between Google Accounts and Federated Login, I noticed a few things:

  • Admin users are correctly recognized by is_current_user_admin() with OpenID
  • Mixing modes doesn't work. With authentication set to Google Accounts, calling create_login_url with a federated_identity throws a NotAllowedError
  • An ACSID cookie is still produced at the end of the login process, only it comes from /_ah/openid_verify instead of /_ah/login

So what's happening with remote_api when using Federated Login? If we're using the default appengine_rpc.HttpRpcServer, it's dutifully following the same Google Account authentication process described at the top, only the app no longer considers the ACSID cookie returned by /_ah/login to be valid, so since you're still unauthenticated, you get a 302 redirect to the OpenID login page, /_ah/login_required.

I dunno what the right solution is here. Seems like it would require an API update. Maybe Nick or one of the other Googlers can weigh in.

For now, here's a hacky workaround:

  • Turn on Federated Login for your app
  • Make sure you're passing save_cookies=True when calling remote_api_stub.ConfigureRemoteDatastore for your console script
  • Attempt console authentication and get the 302 error
  • Login as an admin via your app's web interface
  • In your browser cookies, find the ACSID cookie for myapp.appspot.com
  • Find and edit your local ~/.appcfg_cookies file
  • Replace the ACSID cookie for myapp.appspot.com with the one from your browser

The next time you try to use remote_api, it should work without prompting for credentials. You'll have to repeat the last 4 steps every time the cookie expires, though. You can bump the expiration from 1 day to as high as 2 weeks in the admin console to minimize the annoyance. Have fun!

This is definitely an issue... mark your interest in getting Google to fix this by starring the ticket at http://code.google.com/p/googleappengine/issues/detail?id=3258 and feel free to add any of your workarounds there.

On a related note, we also recognize that the docs are somewhat sparse, so I'm working on an article which hopefully fills-in some of those holes... stay tuned and keep your eyes open at http://code.google.com/appengine/articles

Here's a workaround you can use until there's a more permanent solution in place.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!