def setUp(self): self.store = GoodAssocStore() self.consumer = GenericConsumer(self.store) self.server_url = "http://idp.unittest/" CatchLogs.setUp(self) claimed_id = 'bogus.claimed' self.message = Message.fromOpenIDArgs( {'mode': 'id_res', 'return_to': 'return_to (just anything)', 'identity': claimed_id, 'assoc_handle': 'does not matter', 'sig': GOODSIG, 'response_nonce': mkNonce(), 'signed': 'identity,return_to,response_nonce,assoc_handle,claimed_id,op_endpoint', 'claimed_id': claimed_id, 'op_endpoint': self.server_url, 'ns':OPENID2_NS, }) self.endpoint = OpenIDServiceEndpoint() self.endpoint.server_url = self.server_url self.endpoint.claimed_id = claimed_id self.consumer._checkReturnTo = lambda unused1, unused2 : True
def test_mkSplit(self): t = 42 nonce_str = mkNonce(t) self.failUnless(nonce_re.match(nonce_str)) et, salt = splitNonce(nonce_str) self.failUnlessEqual(len(salt), 6) self.failUnlessEqual(et, t)
def test_mkSplit(self): t = 42 nonce_str = mkNonce(t) self.assertTrue(nonce_re.match(nonce_str)) et, salt = splitNonce(nonce_str) self.assertEqual(len(salt), 6) self.assertEqual(et, t)
def test_consumerNonceOpenID2(self): """OpenID 2 does not use consumer-generated nonce""" self.return_to = 'http://rt.unittest/?nonce=%s' % (mkNonce(),) self.response = Message.fromOpenIDArgs( {'return_to': self.return_to, 'ns':OPENID2_NS}) self.failUnlessRaises(ProtocolError, self.consumer._idResCheckNonce, self.response, self.endpoint) self.failUnlessLogEmpty()
def test_openid1Success(self): """use consumer-generated nonce""" nonce_value = mkNonce() self.return_to = 'http://rt.unittest/?nonce=%s' % (nonce_value,) self.response = Message.fromOpenIDArgs({'return_to': self.return_to}) self.response.setArg(BARE_NS, 'nonce', nonce_value) self.consumer._idResCheckNonce(self.response, self.endpoint) self.failUnlessLogEmpty()
def test_successWithNoStore(self): """When there is no store, checking the nonce succeeds""" self.consumer.store = None self.response = Message.fromOpenIDArgs( {'response_nonce': mkNonce(), 'ns':OPENID2_NS, }) self.consumer._idResCheckNonce(self.response, self.endpoint) self.failUnlessLogEmpty()
def test_serverNonceOpenID1(self): """OpenID 1 does not use server-generated nonce""" self.response = Message.fromOpenIDArgs( {'ns':OPENID1_NS, 'return_to': 'http://return.to/', 'response_nonce': mkNonce(),}) self.failUnlessRaises(ProtocolError, self.consumer._idResCheckNonce, self.response, self.endpoint) self.failUnlessLogEmpty()
def test_badNonce(self): """remove the nonce from the store From "Checking the Nonce":: When the Relying Party checks the signature on an assertion, the Relying Party SHOULD ensure that an assertion has not yet been accepted with the same value for "openid.response_nonce" from the same OP Endpoint URL. """ nonce = mkNonce() stamp, salt = splitNonce(nonce) self.store.useNonce(self.server_url, stamp, salt) self.response = Message.fromOpenIDArgs( {'response_nonce': nonce, 'ns':OPENID2_NS, }) self.failUnlessRaises(ProtocolError, self.consumer._idResCheckNonce, self.response, self.endpoint)
def test_mkNonce(self): nonce = mkNonce() self.assertTrue(nonce_re.match(nonce)) self.assertTrue(len(nonce) == 26)
def test_mkNonce_when(self): nonce = mkNonce(0) self.assertTrue(nonce_re.match(nonce)) self.assertTrue(nonce.startswith('1970-01-01T00:00:00Z')) self.assertTrue(len(nonce) == 26)
def test_mkNonce_when(self): nonce = mkNonce(0) self.failUnless(nonce_re.match(nonce)) self.failUnless(nonce.startswith('1970-01-01T00:00:00Z')) self.failUnless(len(nonce) == 26)
def test_mkNonce(self): nonce = mkNonce() self.failUnless(nonce_re.match(nonce)) self.failUnless(len(nonce) == 26)
def test_mkNonce(self): nonce = mkNonce() self.assertIsNotNone(nonce_re.match(nonce)) self.assertEqual(len(nonce), 26)
store.storeAssociation(server_url + '3', assocValid2) cleaned = store.cleanupAssociations() assert cleaned == 2, cleaned ### Nonce functions def checkUseNonce(nonce, expected, server_url, msg=''): stamp, salt = split(nonce) actual = store.useNonce(server_url, stamp, salt) assert bool(actual) == bool(expected), "%r != %r: %s" % (actual, expected, msg) for url in [server_url, '']: # Random nonce (not in store) nonce1 = mkNonce() # A nonce is allowed by default checkUseNonce(nonce1, True, url) # Storing once causes useNonce to return True the first, and only # the first, time it is called after the store. checkUseNonce(nonce1, False, url) checkUseNonce(nonce1, False, url) # Nonces from when the universe was an hour old should not pass these days. old_nonce = mkNonce(3600) checkUseNonce(old_nonce, False, url, "Old nonce (%r) passed." % (old_nonce,)) old_nonce1 = mkNonce(now - 20000)
def test_serverNonce(self): """use server-generated nonce""" self.response = Message.fromOpenIDArgs( {'ns':OPENID2_NS, 'response_nonce': mkNonce(),}) self.consumer._idResCheckNonce(self.response, self.endpoint) self.failUnlessLogEmpty()
def testStore(store): """Make sure a given store has a minimum of API compliance. Call this function with an empty store. Raises AssertionError if the store does not work as expected. OpenIDStore -> NoneType """ ### Association functions now = int(time.time()) server_url = 'http://www.myopenid.com/openid' def genAssoc(issued, lifetime=600): sec = generateSecret(20) hdl = generateHandle(128) return Association(hdl, sec, now + issued, lifetime, 'HMAC-SHA1') def checkRetrieve(url, handle=None, expected=None): retrieved_assoc = store.getAssociation(url, handle) assert retrieved_assoc == expected, (retrieved_assoc, expected) if expected is not None: if retrieved_assoc is expected: print ('Unexpected: retrieved a reference to the expected ' 'value instead of a new object') assert retrieved_assoc.handle == expected.handle assert retrieved_assoc.secret == expected.secret def checkRemove(url, handle, expected): present = store.removeAssociation(url, handle) assert bool(expected) == bool(present) assoc = genAssoc(issued=0) # Make sure that a missing association returns no result checkRetrieve(server_url) # Check that after storage, getting returns the same result store.storeAssociation(server_url, assoc) checkRetrieve(server_url, None, assoc) # more than once checkRetrieve(server_url, None, assoc) # Storing more than once has no ill effect store.storeAssociation(server_url, assoc) checkRetrieve(server_url, None, assoc) # Removing an association that does not exist returns not present checkRemove(server_url, assoc.handle + 'x', False) # Removing an association that does not exist returns not present checkRemove(server_url + 'x', assoc.handle, False) # Removing an association that is present returns present checkRemove(server_url, assoc.handle, True) # but not present on subsequent calls checkRemove(server_url, assoc.handle, False) # Put assoc back in the store store.storeAssociation(server_url, assoc) # More recent and expires after assoc assoc2 = genAssoc(issued=1) store.storeAssociation(server_url, assoc2) # After storing an association with a different handle, but the # same server_url, the handle with the later issue date is returned. checkRetrieve(server_url, None, assoc2) # We can still retrieve the older association checkRetrieve(server_url, assoc.handle, assoc) # Plus we can retrieve the association with the later issue date # explicitly checkRetrieve(server_url, assoc2.handle, assoc2) # More recent, and expires earlier than assoc2 or assoc. Make sure # that we're picking the one with the latest issued date and not # taking into account the expiration. assoc3 = genAssoc(issued=2, lifetime=100) store.storeAssociation(server_url, assoc3) checkRetrieve(server_url, None, assoc3) checkRetrieve(server_url, assoc.handle, assoc) checkRetrieve(server_url, assoc2.handle, assoc2) checkRetrieve(server_url, assoc3.handle, assoc3) checkRemove(server_url, assoc2.handle, True) checkRetrieve(server_url, None, assoc3) checkRetrieve(server_url, assoc.handle, assoc) checkRetrieve(server_url, assoc2.handle, None) checkRetrieve(server_url, assoc3.handle, assoc3) checkRemove(server_url, assoc2.handle, False) checkRemove(server_url, assoc3.handle, True) checkRetrieve(server_url, None, assoc) checkRetrieve(server_url, assoc.handle, assoc) checkRetrieve(server_url, assoc2.handle, None) checkRetrieve(server_url, assoc3.handle, None) checkRemove(server_url, assoc2.handle, False) checkRemove(server_url, assoc.handle, True) checkRemove(server_url, assoc3.handle, False) checkRetrieve(server_url, None, None) checkRetrieve(server_url, assoc.handle, None) checkRetrieve(server_url, assoc2.handle, None) checkRetrieve(server_url, assoc3.handle, None) checkRemove(server_url, assoc2.handle, False) checkRemove(server_url, assoc.handle, False) checkRemove(server_url, assoc3.handle, False) ### test expired associations # assoc 1: server 1, valid # assoc 2: server 1, expired # assoc 3: server 2, expired # assoc 4: server 3, valid assocValid1 = genAssoc(issued=-3600,lifetime=7200) assocValid2 = genAssoc(issued=-5) assocExpired1 = genAssoc(issued=-7200,lifetime=3600) assocExpired2 = genAssoc(issued=-7200,lifetime=3600) store.cleanupAssociations() store.storeAssociation(server_url + '1', assocValid1) store.storeAssociation(server_url + '1', assocExpired1) store.storeAssociation(server_url + '2', assocExpired2) store.storeAssociation(server_url + '3', assocValid2) cleaned = store.cleanupAssociations() assert cleaned == 2, cleaned ### Nonce functions def checkUseNonce(nonce, expected, server_url, msg=''): stamp, salt = split(nonce) actual = store.useNonce(server_url, stamp, salt) assert bool(actual) == bool(expected), "%r != %r: %s" % (actual, expected, msg) for url in [server_url, '']: # Random nonce (not in store) nonce1 = mkNonce() # A nonce is allowed by default checkUseNonce(nonce1, True, url) # Storing once causes useNonce to return True the first, and only # the first, time it is called after the store. checkUseNonce(nonce1, False, url) checkUseNonce(nonce1, False, url) # Nonces from when the universe was an hour old should not pass these days. old_nonce = mkNonce(3600) checkUseNonce(old_nonce, False, url, "Old nonce (%r) passed." % (old_nonce,)) old_nonce1 = mkNonce(now - 20000) old_nonce2 = mkNonce(now - 10000) recent_nonce = mkNonce(now - 600) from openid.store import nonce as nonceModule orig_skew = nonceModule.SKEW try: nonceModule.SKEW = 0 store.cleanupNonces() # Set SKEW high so stores will keep our nonces. nonceModule.SKEW = 100000 assert store.useNonce(server_url, *split(old_nonce1)) assert store.useNonce(server_url, *split(old_nonce2)) assert store.useNonce(server_url, *split(recent_nonce)) nonceModule.SKEW = 3600 cleaned = store.cleanupNonces() assert cleaned == 2, "Cleaned %r nonces." % (cleaned,) nonceModule.SKEW = 100000 # A roundabout method of checking that the old nonces were cleaned is # to see if we're allowed to add them again. assert store.useNonce(server_url, *split(old_nonce1)) assert store.useNonce(server_url, *split(old_nonce2)) # The recent nonce wasn't cleaned, so it should still fail. assert not store.useNonce(server_url, *split(recent_nonce)) finally: nonceModule.SKEW = orig_skew