This was a fun one.
Looking at remote_api, the flow for authentication seems to be something like this:
- Prompt the user for Google credentials
- Post the credentials to https://www.google.com/accounts/ClientLogin
- Parse the
auth token out of the response body
- Pass the token to https://myapp.appspot.com/_ah/login
ACSID cookie set in the response
- Pass the
ACSID cookie in subsequent requests that require authorization
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:
handlers: - url: /remote_api script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py login: admin - url: /.* script: 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
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!