1
# django-openid-auth - OpenID integration for django.contrib.auth
3
# Copyright (C) 2009 Canonical Ltd.
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions
9
# * Redistributions of source code must retain the above copyright
10
# notice, this list of conditions and the following disclaimer.
12
# * Redistributions in binary form must reproduce the above copyright
13
# notice, this list of conditions and the following disclaimer in the
14
# documentation and/or other materials provided with the distribution.
16
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
32
from django.test import TestCase
33
from openid.association import Association as OIDAssociation
34
from openid.store.nonce import SKEW
36
from django_openid_auth.models import Association, Nonce
37
from django_openid_auth.store import DjangoOpenIDStore
40
class OpenIDStoreTests(TestCase):
43
super(OpenIDStoreTests, self).setUp()
44
self.store = DjangoOpenIDStore()
46
def test_storeAssociation(self):
47
assoc = OIDAssociation('handle', 'secret', 42, 600, 'HMAC-SHA1')
48
self.store.storeAssociation('server-url', assoc)
50
dbassoc = Association.objects.get(
51
server_url='server-url', handle='handle')
52
self.assertEquals(dbassoc.server_url, 'server-url')
53
self.assertEquals(dbassoc.handle, 'handle')
54
self.assertEquals(dbassoc.secret, 'secret'.encode('base-64'))
55
self.assertEquals(dbassoc.issued, 42)
56
self.assertEquals(dbassoc.lifetime, 600)
57
self.assertEquals(dbassoc.assoc_type, 'HMAC-SHA1')
59
def test_storeAssociation_update_existing(self):
60
assoc = OIDAssociation('handle', 'secret', 42, 600, 'HMAC-SHA1')
61
self.store.storeAssociation('server-url', assoc)
63
# Now update the association with new information.
64
assoc = OIDAssociation('handle', 'secret2', 420, 900, 'HMAC-SHA256')
65
self.store.storeAssociation('server-url', assoc)
66
dbassoc = Association.objects.get(
67
server_url='server-url', handle='handle')
68
self.assertEqual(dbassoc.secret, 'secret2'.encode('base-64'))
69
self.assertEqual(dbassoc.issued, 420)
70
self.assertEqual(dbassoc.lifetime, 900)
71
self.assertEqual(dbassoc.assoc_type, 'HMAC-SHA256')
73
def test_getAssociation(self):
74
timestamp = int(time.time())
75
self.store.storeAssociation(
76
'server-url', OIDAssociation('handle', 'secret', timestamp, 600,
78
assoc = self.store.getAssociation('server-url', 'handle')
79
self.assertTrue(isinstance(assoc, OIDAssociation))
81
self.assertEquals(assoc.handle, 'handle')
82
self.assertEquals(assoc.secret, 'secret')
83
self.assertEquals(assoc.issued, timestamp)
84
self.assertEquals(assoc.lifetime, 600)
85
self.assertEquals(assoc.assoc_type, 'HMAC-SHA1')
87
def test_getAssociation_unknown(self):
88
assoc = self.store.getAssociation('server-url', 'unknown')
89
self.assertEquals(assoc, None)
91
def test_getAssociation_expired(self):
93
timestamp = int(time.time()) - 2 * lifetime
94
self.store.storeAssociation(
95
'server-url', OIDAssociation('handle', 'secret', timestamp,
96
lifetime, 'HMAC-SHA1'))
98
# The association is not returned, and is removed from the database.
99
assoc = self.store.getAssociation('server-url', 'handle')
100
self.assertEquals(assoc, None)
101
self.assertRaises(Association.DoesNotExist, Association.objects.get,
102
server_url='server-url', handle='handle')
104
def test_getAssociation_no_handle(self):
105
timestamp = int(time.time())
107
self.store.storeAssociation(
108
'server-url', OIDAssociation('handle1', 'secret', timestamp + 1,
110
self.store.storeAssociation(
111
'server-url', OIDAssociation('handle2', 'secret', timestamp,
114
# The newest handle is returned.
115
assoc = self.store.getAssociation('server-url', None)
116
self.assertNotEquals(assoc, None)
117
self.assertEquals(assoc.handle, 'handle1')
118
self.assertEquals(assoc.issued, timestamp + 1)
120
def test_removeAssociation(self):
121
timestamp = int(time.time())
122
self.store.storeAssociation(
123
'server-url', OIDAssociation('handle', 'secret', timestamp, 600,
126
self.store.removeAssociation('server-url', 'handle'), True)
128
self.store.getAssociation('server-url', 'handle'), None)
130
def test_removeAssociation_unknown(self):
132
self.store.removeAssociation('server-url', 'unknown'), False)
134
def test_useNonce(self):
135
timestamp = time.time()
136
# The nonce can only be used once.
138
self.store.useNonce('server-url', timestamp, 'salt'), True)
140
self.store.useNonce('server-url', timestamp, 'salt'), False)
142
self.store.useNonce('server-url', timestamp, 'salt'), False)
144
def test_useNonce_expired(self):
145
timestamp = time.time() - 2 * SKEW
147
self.store.useNonce('server-url', timestamp, 'salt'), False)
149
def test_useNonce_future(self):
150
timestamp = time.time() + 2 * SKEW
152
self.store.useNonce('server-url', timestamp, 'salt'), False)
154
def test_cleanupNonces(self):
155
timestamp = time.time()
157
self.store.useNonce('server1', timestamp, 'salt1'), True)
159
self.store.useNonce('server2', timestamp, 'salt2'), True)
161
self.store.useNonce('server3', timestamp, 'salt3'), True)
162
self.assertEqual(Nonce.objects.count(), 3)
165
self.store.cleanupNonces(_now=timestamp + 2 * SKEW), 3)
166
self.assertEqual(Nonce.objects.count(), 0)
168
# The nonces have now been cleared:
170
self.store.useNonce('server1', timestamp, 'salt1'), True)
172
self.store.cleanupNonces(_now=timestamp + 2 * SKEW), 1)
174
self.store.cleanupNonces(_now=timestamp + 2 * SKEW), 0)
176
def test_cleanupAssociations(self):
177
timestamp = int(time.time()) - 100
178
self.store.storeAssociation(
179
'server-url', OIDAssociation('handle1', 'secret', timestamp,
181
self.store.storeAssociation(
182
'server-url', OIDAssociation('handle2', 'secret', timestamp,
185
self.assertEquals(self.store.cleanupAssociations(), 1)
187
# The second (non-expired) association is left behind.
188
self.assertNotEqual(self.store.getAssociation('server-url', 'handle2'),
193
return unittest.TestLoader().loadTestsFromName(__name__)