Joseph Jude

Technology, Psychology, and Story Telling

Authenticating in GAE

Posted: Tags: my-apps

Having successfully created a desktop application in IronPython, I wanted to go a step further - integrate desktop and web environment. Data can be captured in desktop and passed on to web; and analysis can be done on the web.

To start with it, I need to authenticate the incoming request. Hmm...when I started reading about authentication I read so many jargons that scared me - openid, openauth, authsub, basicauth. It took me a while to understand the basics of each (still I don't claim that I've understood them; probably whatever I've understood is wrong too)

To some extent, I understood 'Basic Authentication' and this is how I went about implementing it.

Authenticating in GAE

First of all, I am going with Google Account Authentication, assuming all the users will have a Google account; getting one is not a big deal.

IronPython Desktop Application will pass userid, password to AppEngine Application, which in turn will validate with Google Accounts Authentication service. If authenticated, AppEngine application will proceed; else it will pass the error back to the desktop application.

Having discussed the concepts, here are the code snippets. I'm sharing with a hope that it will be useful to someone; or if this is wrong, someone will raise an alarm; or if there is a better way to do it, someone will comment.

AppEngine

Here the expectation is that the incoming request will have a header ('HTTP_AUTHORIZATION') with userid and password in Base64 format.

from google.appengine.api import users import urllib import base64 from google.appengine.api import urlfetch from django.http import HttpResponse

def authenticate(request): response_vals={} resp = HttpResponse() try: (method, encoded) = request.META['HTTP_AUTHORIZATION'].split() response_vals['method'] = method response_vals['encoded'] = encoded if method.lower() == 'basic': (username, password) = base64.b64decode(encoded).split(':')

      request_body = urllib.urlencode({'Email': username,
                                       'Passwd': password,
                                       'accountType': 'HOSTED_OR_GOOGLE',
                                       'service': 'ah',
                                       'source': 'test'})
      auth_response = urlfetch.fetch('https://www.google.com/accounts/ClientLogin',
                                     method=urlfetch.POST,
                                     headers={'Content-type':'application/x-www-form-urlencoded',
                                              'Content-Length':
                                               str(len(request_body))},
                                     payload=request_body)
      resp.status_code = auth_response.status_code
except:
  resp.status_code = 401
  return resp
return resp
Desktop - Python

Encode the user id, password and call the particular URL (/auth?). And handle the response.

import urllib import urllib2 import base64

url = 'http://localhost:8000/api/auth/' username = [email protected]' password = 'mysecspwd' USER_AGENT = 'mySecsWndClient'

request = urllib2.Request(url) base64string = base64.encodestring('%s:%s' % (username,password)) authheader = "Basic %s" % base64string request.add_header('USER_AGENT', USER_AGENT) request.add_header('AUTHORIZATION', authheader)

try: response = urllib2.urlopen(request).read() print response except urllib2.HTTPError, e: print e.code print e.read() except urllib2.URLError, e: if hasattr(e, 'reason'): print e.reason elif hasattr(e,'code'): print e.code

Desktop - IronPython

Since I've written mySecs in IronPython, I've to translate the above into IronPython. As ipy is a relatively new entrant, there is not much of documentation on how to do it. Here is what I've done.

import System from System.IO import StreamReader from System.Net import HttpWebRequest, NetworkCredential, WebException

url = 'http://localhost:8000/api/auth/' username = [email protected]' password = 'mysecspwd' USER_AGENT = 'mySecsWndClient'

req = HttpWebRequest.Create(url) req.UserAgent = USER_AGENT auth_string = '%s:%s' % (username,password) authheader = "Basic %s" % System.Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(auth_string)) req.Headers.Add('AUTHORIZATION', authheader)

try: rsp = req.GetResponse() response = StreamReader(rsp.GetResponseStream()).ReadToEnd() print response rsp.Close() except (Exception, WebException), e: print 'Error: %s' % e

Applies to: GAE 1.1.1; Django 0.96 with helper; IronPython 1.1

Reference:

AuthSub Authentication for Web Applications

Basic Authentication - Authentication with Python


Comments

comments powered by Disqus