views:

523

answers:

3

When you call a web service like this:

   username = 'test12'
   password = 'test34' 
   client = httplib2.Http(".cache") 
   client.add_credentials(username,password)
   URL = "http://localhost:8080/wyWebServiceTest"
   response, content = client.request(URL)

How do you get the username/password into variables on the server side (i.e. in the web-service that I'm writing). I checked the self.request.headers and self.request.environ and couldn't find them.

(I'm not using Google Login, need to bounce this userid/pass against my own database to verify security.)

I was trying to ideas from this page: http://pythonpaste.org/webob/reference.html#headers

Thanks,

Neal Walters

Slight enhancement to Peter's code below:

 auth = None 
 if 'Authorization' in self.request.headers: 
    auth = self.request.headers['Authorization']
 if not auth:
+1  A: 

httplib2 will only pass the credentials after a 401 response from the web server, after which the credentials should be sent in an Authorization: header.

Wooble
I'm confused. So you are saying first call is no credentials, then server returns 401, then client automatically sends user/pass? But anyway - the user/pass is available to the web-service right? The code fragment above is a non-GAE program running on my machine that calls a GAE web-service. It's in the web-service I want to check the user/pass. (Good to see your pic - I see you Google-Group all the time).
NealWalters
Got it now after the other answers. Thanks.
NealWalters
+2  A: 

The credentials will appear in the Authorization header. The steps work like this:

  1. Client makes a request to your app with no attempt at authorization
  2. Server responds with a "401 Authorization Required" response, and the "WWW-Authenticate" header set to 'Basic realm="something"' (for basic auth).
  3. Client responds with an Authorization header set appropriately (see below).

The exact content of the client's Authorization header in step 3 depends on the authorization method used. For HTTP Basic auth, it's the base64-encoded user credentials - see here. For HTTP digest auth, both the server's header and the response from the client are a bit more complicated - see here.

Nick Johnson
Thanks for the response and especially the link that explains the encoding.
NealWalters
Great idea on the decorator - but it's over my head without stopping to spend a day on it. Here's my crude attempt: http://stackoverflow.com/questions/1500982/python-decorator-for-gae-web-service-security-check
NealWalters
+2  A: 

I haven't tested this code (insert smiley) but I think this is the sort of thing you need. Basically your credentials won't be in the header if your server hasn't bounced a 401 back to your client (the client needs to know the realm to know what credentials to provide).

class MYREALM_securepage(webapp.RequestHandler):
  def get(self):
      if not 'Authorization' in self.request.headers:
          self.response.headers['WWW-Authenticate'] = 'Basic realm="MYREALM"'
          self.response.set_status(401)
          self.response.out.write("Authorization required")
      else:
          auth = self.request.headers['Authorization']
          (username, password) = base64.b64decode(auth.split(' ')[1]).split(':')
          # Check the username and password, and proceed ...
Peter S Magnusson
Exactly what the doctor ordered! Thanks!!! I added "import base64" and made one minor change - see edit of my original post.
NealWalters
One nitpick: This would be better as a decorator. :)
Nick Johnson
it should totally be done as a decorator. i just wanted to show the core code.
Peter S Magnusson