update to reflect API changes
[gae-samples.git] / openid-provider / store.py
bloba4419fd7910f8fe8f2a52abf83dcca2e89c52ca6
1 #!/usr/bin/python
3 # Copyright 2007, Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """
18 An OpenIDStore implementation that uses the datastore as its backing store.
19 Stores associations, nonces, and authentication tokens.
21 OpenIDStore is an interface from JanRain's OpenID python library:
22 http://openidenabled.com/python-openid/
24 For more, see openid/store/interface.py in that library.
25 """
27 import datetime
29 from openid.association import Association
30 from openid.store.interface import OpenIDStore
31 from google.appengine.api import datastore
34 class DatastoreStore(OpenIDStore):
35 """An OpenIDStore implementation that uses the datastore. See
36 openid/store/interface.py for in-depth descriptions of the methods.
38 They follow the OpenID python library's style, not Google's style, since
39 they override methods defined in the OpenIDStore class.
40 """
42 def storeAssociation(self, server_url, association):
43 """
44 This method puts a C{L{Association <openid.association.Association>}}
45 object into storage, retrievable by server URL and handle.
46 """
47 entity = datastore.Entity('Association')
48 entity['url'] = server_url
49 entity['handle'] = association.handle
50 entity['association'] = association.serialize()
51 datastore.Put(entity)
53 def getAssociation(self, server_url, handle=None):
54 """
55 This method returns an C{L{Association <openid.association.Association>}}
56 object from storage that matches the server URL and, if specified, handle.
57 It returns C{None} if no such association is found or if the matching
58 association is expired.
60 If no handle is specified, the store may return any association which
61 matches the server URL. If multiple associations are valid, the
62 recommended return value for this method is the one that will remain valid
63 for the longest duration.
64 """
65 query = datastore.Query('Association', {'url =': server_url})
66 if handle:
67 query['handle ='] = handle
69 results = query.Get(1)
70 if results:
71 association = Association.deserialize(results[0]['association'])
72 if association.getExpiresIn() > 0:
73 # hasn't expired yet
74 return association
76 return None
78 def removeAssociation(self, server_url, handle):
79 """
80 This method removes the matching association if it's found, and returns
81 whether the association was removed or not.
82 """
83 query = datastore.Query('Association',
84 {'url =': server_url, 'handle =': handle})
86 results = query.Get(1)
87 if results:
88 datastore.Delete(results[0].key())
90 def storeNonce(self, nonce):
91 """
92 Stores a nonce. This is used by the consumer to prevent replay attacks.
93 """
94 entity = datastore.Entity('Nonce')
95 entity['nonce'] = nonce
96 entity['created'] = datetime.datetime.now()
97 datastore.Put(entity)
99 def useNonce(self, nonce):
101 This method is called when the library is attempting to use a nonce. If
102 the nonce is in the store, this method removes it and returns a value
103 which evaluates as true. Otherwise it returns a value which evaluates as
104 false.
106 This method is allowed and encouraged to treat nonces older than some
107 period (a very conservative window would be 6 hours, for example) as no
108 longer existing, and return False and remove them.
110 query = datastore.Query('Nonce')
111 query['nonce ='] = nonce
112 query['created >='] = (datetime.datetime.now() -
113 datetime.timedelta(hours=6))
115 results = query.Get(1)
116 if results:
117 datastore.Delete(results[0].key())
118 return True
119 else:
120 return False
122 def getAuthKey(self):
124 This method returns a key used to sign the tokens, to ensure that they
125 haven't been tampered with in transit. It should return the same key every
126 time it is called. The key returned should be C{L{AUTH_KEY_LEN}} bytes
127 long.
129 auth_key = 'My Insecure Auth Key'
130 assert len(auth_key) == self.AUTH_KEY_LEN
131 return auth_key