p@21
|
1 """
|
p@21
|
2 The MIT License
|
p@21
|
3
|
p@21
|
4 Copyright (c) 2010 Justin Plock
|
p@21
|
5
|
p@21
|
6 Permission is hereby granted, free of charge, to any person obtaining a copy
|
p@21
|
7 of this software and associated documentation files (the "Software"), to deal
|
p@21
|
8 in the Software without restriction, including without limitation the rights
|
p@21
|
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
p@21
|
10 copies of the Software, and to permit persons to whom the Software is
|
p@21
|
11 furnished to do so, subject to the following conditions:
|
p@21
|
12
|
p@21
|
13 The above copyright notice and this permission notice shall be included in
|
p@21
|
14 all copies or substantial portions of the Software.
|
p@21
|
15
|
p@21
|
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
p@21
|
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
p@21
|
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
p@21
|
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
p@21
|
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
p@21
|
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
p@21
|
22 THE SOFTWARE.
|
p@21
|
23 """
|
p@21
|
24
|
p@21
|
25 import os
|
p@21
|
26
|
p@21
|
27 from google.appengine.ext import webapp
|
p@21
|
28 from google.appengine.ext import db
|
p@21
|
29 from google.appengine.ext.webapp import util
|
p@21
|
30 import oauth2 as oauth # httplib2 is required for this to work on AppEngine
|
p@21
|
31
|
p@21
|
32 class Client(db.Model):
|
p@21
|
33 # oauth_key is the Model's key_name field
|
p@21
|
34 oauth_secret = db.StringProperty() # str(uuid.uuid4()) works well for this
|
p@21
|
35 first_name = db.StringProperty()
|
p@21
|
36 last_name = db.StringProperty()
|
p@21
|
37 email_address = db.EmailProperty(required=True)
|
p@21
|
38 password = db.StringProperty(required=True)
|
p@21
|
39
|
p@21
|
40 @property
|
p@21
|
41 def secret(self):
|
p@21
|
42 return self.oauth_secret
|
p@21
|
43
|
p@21
|
44 class OAuthHandler(webapp.RequestHandler):
|
p@21
|
45
|
p@21
|
46 def __init__(self):
|
p@21
|
47 self._server = oauth.Server()
|
p@21
|
48 self._server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
|
p@21
|
49 self._server.add_signature_method(oauth.SignatureMethod_PLAINTEXT())
|
p@21
|
50
|
p@21
|
51 def get_oauth_request(self):
|
p@21
|
52 """Return an OAuth Request object for the current request."""
|
p@21
|
53
|
p@21
|
54 try:
|
p@21
|
55 method = os.environ['REQUEST_METHOD']
|
p@21
|
56 except:
|
p@21
|
57 method = 'GET'
|
p@21
|
58
|
p@21
|
59 postdata = None
|
p@21
|
60 if method in ('POST', 'PUT'):
|
p@21
|
61 postdata = self.request.body
|
p@21
|
62
|
p@21
|
63 return oauth.Request.from_request(method, self.request.uri,
|
p@21
|
64 headers=self.request.headers, query_string=postdata)
|
p@21
|
65
|
p@21
|
66 def get_client(self, request=None):
|
p@21
|
67 """Return the client from the OAuth parameters."""
|
p@21
|
68
|
p@21
|
69 if not isinstance(request, oauth.Request):
|
p@21
|
70 request = self.get_oauth_request()
|
p@21
|
71 client_key = request.get_parameter('oauth_consumer_key')
|
p@21
|
72 if not client_key:
|
p@21
|
73 raise Exception('Missing "oauth_consumer_key" parameter in ' \
|
p@21
|
74 'OAuth "Authorization" header')
|
p@21
|
75
|
p@21
|
76 client = models.Client.get_by_key_name(client_key)
|
p@21
|
77 if not client:
|
p@21
|
78 raise Exception('Client "%s" not found.' % client_key)
|
p@21
|
79
|
p@21
|
80 return client
|
p@21
|
81
|
p@21
|
82 def is_valid(self):
|
p@21
|
83 """Returns a Client object if this is a valid OAuth request."""
|
p@21
|
84
|
p@21
|
85 try:
|
p@21
|
86 request = self.get_oauth_request()
|
p@21
|
87 client = self.get_client(request)
|
p@21
|
88 params = self._server.verify_request(request, client, None)
|
p@21
|
89 except Exception, e:
|
p@21
|
90 raise e
|
p@21
|
91
|
p@21
|
92 return client
|
p@21
|
93
|
p@21
|
94 class SampleHandler(OAuthHandler):
|
p@21
|
95 def get(self):
|
p@21
|
96 try:
|
p@21
|
97 client = self.is_valid()
|
p@21
|
98 except Exception, e:
|
p@21
|
99 self.error(500)
|
p@21
|
100 self.response.out.write(e)
|
p@21
|
101
|
p@21
|
102 def main():
|
p@21
|
103 application = webapp.WSGIApplication([(r'/sample', SampleHandler)],
|
p@21
|
104 debug=False)
|
p@21
|
105 util.run_wsgi_app(application)
|
p@21
|
106
|
p@21
|
107 if __name__ == '__main__':
|
p@21
|
108 main()
|