OAuth2 Login, Step #1 Complete… Now, Learn Webapp2!

by Mike Levin SEO & Datamaster, 10/08/2013

Now at long last, the OAuth 2 code login example on Levinux, using the GAE-like webapp2 Python web framework, and the Google API Python Client… but not the Google App Engine itself! My mission at this moment is to make all the URLs in the flow make sense, and to work off of my http://localhost:8888 location. Levinux always grabs http://localhost:8080 for itself for its built-in documentation being served by httpd (the BusyBox HTTP daemon). So Levinux now technically had 3 different web-serving environments: httpd on local port 8080, and the Python web framework of your choice (bottle.py or webapp2) on local port 8888. And this suits me just fine - as I think it will the burgeoning Levinux community for reasons that will become clear as we go.

Now, in the 1, 2, 3 steps process for productivity that I force myself to do by this time in the day, step 1? …

Well, I have the hello world of immediate redirection using the OAuth2 login URL working, but it doesn’t handle the different possible states. It just always shuttles you over to the login URL - I suspect, even once you’re logged in. And so, I have to build a web app into something that can actually receive and respond to requests from the Mirror API. It may be a bit hard to reach in localhost:8888. But that’s no big deal. Just GET TO THE POINT WHERE THAT’S THE NEXT HURDLE. You can quickly zap your app onto Rackspace where you can use one of the many domains you have as the place for the Mirror API to make requests to.

Hmmmm. The Mirror API knows to make a request of my Glassware because of an action made by the user of Glass… who what? Is or isn’t OAuth 2 logged into my app? The mental model here is really unusual. The Mirror API is the man in the middle. Glass communicates only directly with the Mirror API. And my server app only communicates directly with the Mirror API. It’s almost like the Mirror API is a proxy server or gateway, receiving, translating, and routing along requests and commands between my server and the user with Glasses. VERY new programming paradigm for me - mostly because of OAuth 2.

And so, my current knowledge deficit is on webapp2. I am going to begin documenting the code to the public to shift my focus from rambling to coding. But I have to externalize my OAuth2 client_id and client_secret. This is where the simplicity of Python really starts to shine. You just set a bunch of assignments in a file, as if it were in the same file, then import it at “current file” scope. It’s a great python trick, and starts with a line like this at the top of your code where you’re trying to keep secrets:

from loginsecrets import *

…and then you make a file that contains your client_id and client_secret that looks like this in the same directory as where your “hello world” getting started file is located (your working directory):

clientid = ‘[your client id]’ clientsecret = ‘[your client secret]’

And with that done, I can actually move the code onto distributed revisions control and examples into my posts here. So, here’s how you get to the OAuth 2 login screen WITH NO CHECK to whether you’re already logged in yet and with no graceful handling of the callback. This is actually possible to run today on Levinux, if you choose to install webapp2 and the Google API Python Client and registered your app at https://code.google.com/apis/console/

import webapp2 from loginsecrets import * from oauth2client.client import OAuth2WebServerFlow

gapiscope = ‘https://www.googleapis.com/auth/glass.timeline ‘ gapiscope += ‘https://www.googleapis.com/auth/glass.location ‘ gapiscope += ‘https://www.googleapis.com/auth/userinfo.profile’

flow = OAuth2WebServerFlow(client_id=clientid, client_secret=clientsecret, scope=gapiscope, redirect_uri=’http://localhost:8888/oauth2callback’)

auth_uri = flow.step1_get_authorize_url()

class GoLogin(webapp2.RequestHandler): def get(self): self.redirect(auth_uri) #self.response.write(‘Hello World!’)

app = webapp2.WSGIApplication([(‘/’, GoLogin),], debug=True)

def main(): from paste import httpserver httpserver.serve(app, host=’10.0.2.15’, port=’81’)

if __name__ == ‘__main__’: main()