1 """Unit tests for verification of return_to URLs for a realm
4 __all__
= ['TestBuildDiscoveryURL']
6 from openid
.yadis
.discover
import DiscoveryResult
, DiscoveryFailure
7 from openid
.yadis
import services
8 from openid
.server
import trustroot
9 from openid
.test
.support
import CatchLogs
12 # Too many methods does not apply to unit test objects
13 #pylint:disable-msg=R0904
14 class TestBuildDiscoveryURL(unittest
.TestCase
):
15 """Tests for building the discovery URL from a realm and a
19 def failUnlessDiscoURL(self
, realm
, expected_discovery_url
):
20 """Build a discovery URL out of the realm and a return_to and
21 make sure that it matches the expected discovery URL
23 realm_obj
= trustroot
.TrustRoot
.parse(realm
)
24 actual_discovery_url
= realm_obj
.buildDiscoveryURL()
25 self
.failUnlessEqual(expected_discovery_url
, actual_discovery_url
)
27 def test_trivial(self
):
28 """There is no wildcard and the realm is the same as the return_to URL
30 self
.failUnlessDiscoURL('http://example.com/foo',
31 'http://example.com/foo')
33 def test_wildcard(self
):
34 """There is a wildcard
36 self
.failUnlessDiscoURL('http://*.example.com/foo',
37 'http://www.example.com/foo')
39 class TestExtractReturnToURLs(unittest
.TestCase
):
40 disco_url
= 'http://example.com/'
43 self
.original_discover
= services
.discover
44 services
.discover
= self
.mockDiscover
48 services
.discover
= self
.original_discover
50 def mockDiscover(self
, uri
):
51 result
= DiscoveryResult(uri
)
52 result
.response_text
= self
.data
53 result
.normalized_uri
= uri
56 def failUnlessFileHasReturnURLs(self
, filename
, expected_return_urls
):
57 self
.failUnlessXRDSHasReturnURLs(file(filename
).read(),
60 def failUnlessXRDSHasReturnURLs(self
, data
, expected_return_urls
):
62 actual_return_urls
= list(trustroot
.getAllowedReturnURLs(
65 self
.failUnlessEqual(expected_return_urls
, actual_return_urls
)
67 def failUnlessDiscoveryFailure(self
, text
):
69 self
.failUnlessRaises(
70 DiscoveryFailure
, trustroot
.getAllowedReturnURLs
, self
.disco_url
)
73 self
.failUnlessDiscoveryFailure('')
75 def test_badXML(self
):
76 self
.failUnlessDiscoveryFailure('>')
78 def test_noEntries(self
):
79 self
.failUnlessXRDSHasReturnURLs('''\
80 <?xml version="1.0" encoding="UTF-8"?>
81 <xrds:XRDS xmlns:xrds="xri://$xrds"
82 xmlns="xri://$xrd*($v*2.0)"
89 def test_noReturnToEntries(self
):
90 self
.failUnlessXRDSHasReturnURLs('''\
91 <?xml version="1.0" encoding="UTF-8"?>
92 <xrds:XRDS xmlns:xrds="xri://$xrds"
93 xmlns="xri://$xrd*($v*2.0)"
96 <Service priority="10">
97 <Type>http://specs.openid.net/auth/2.0/server</Type>
98 <URI>http://www.myopenid.com/server</URI>
104 def test_oneEntry(self
):
105 self
.failUnlessXRDSHasReturnURLs('''\
106 <?xml version="1.0" encoding="UTF-8"?>
107 <xrds:XRDS xmlns:xrds="xri://$xrds"
108 xmlns="xri://$xrd*($v*2.0)"
112 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
113 <URI>http://rp.example.com/return</URI>
117 ''', ['http://rp.example.com/return'])
119 def test_twoEntries(self
):
120 self
.failUnlessXRDSHasReturnURLs('''\
121 <?xml version="1.0" encoding="UTF-8"?>
122 <xrds:XRDS xmlns:xrds="xri://$xrds"
123 xmlns="xri://$xrd*($v*2.0)"
126 <Service priority="0">
127 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
128 <URI>http://rp.example.com/return</URI>
130 <Service priority="1">
131 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
132 <URI>http://other.rp.example.com/return</URI>
136 ''', ['http://rp.example.com/return',
137 'http://other.rp.example.com/return'])
139 def test_twoEntries_withOther(self
):
140 self
.failUnlessXRDSHasReturnURLs('''\
141 <?xml version="1.0" encoding="UTF-8"?>
142 <xrds:XRDS xmlns:xrds="xri://$xrds"
143 xmlns="xri://$xrd*($v*2.0)"
146 <Service priority="0">
147 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
148 <URI>http://rp.example.com/return</URI>
150 <Service priority="1">
151 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
152 <URI>http://other.rp.example.com/return</URI>
154 <Service priority="0">
155 <Type>http://example.com/LOLCATS</Type>
156 <URI>http://example.com/invisible+uri</URI>
160 ''', ['http://rp.example.com/return',
161 'http://other.rp.example.com/return'])
165 class TestReturnToMatches(unittest
.TestCase
):
166 def test_noEntries(self
):
167 self
.failIf(trustroot
.returnToMatches([], 'anything'))
169 def test_exactMatch(self
):
170 r
= 'http://example.com/return.to'
171 self
.failUnless(trustroot
.returnToMatches([r
], r
))
173 def test_garbageMatch(self
):
174 r
= 'http://example.com/return.to'
175 self
.failUnless(trustroot
.returnToMatches(
176 ['This is not a URL at all. In fact, it has characters, '
177 'like "<" that are not allowed in URLs',
181 def test_descendant(self
):
182 r
= 'http://example.com/return.to'
183 self
.failUnless(trustroot
.returnToMatches(
185 'http://example.com/return.to/user:joe'))
187 def test_wildcard(self
):
188 self
.failIf(trustroot
.returnToMatches(
189 ['http://*.example.com/return.to'],
190 'http://example.com/return.to'))
192 def test_noMatch(self
):
193 r
= 'http://example.com/return.to'
194 self
.failIf(trustroot
.returnToMatches(
196 'http://example.com/xss_exploit'))
198 class TestVerifyReturnTo(unittest
.TestCase
, CatchLogs
):
201 CatchLogs
.setUp(self
)
204 CatchLogs
.tearDown(self
)
206 def test_bogusRealm(self
):
207 self
.failIf(trustroot
.verifyReturnTo('', 'http://example.com/'))
209 def test_verifyWithDiscoveryCalled(self
):
210 realm
= 'http://*.example.com/'
211 return_to
= 'http://www.example.com/foo'
214 self
.failUnlessEqual('http://www.example.com/', disco_url
)
218 trustroot
.verifyReturnTo(realm
, return_to
, _vrfy
=vrfy
))
219 self
.failUnlessLogEmpty()
221 def test_verifyFailWithDiscoveryCalled(self
):
222 realm
= 'http://*.example.com/'
223 return_to
= 'http://www.example.com/foo'
226 self
.failUnlessEqual('http://www.example.com/', disco_url
)
227 return ['http://something-else.invalid/']
230 trustroot
.verifyReturnTo(realm
, return_to
, _vrfy
=vrfy
))
231 self
.failUnlessLogMatches("Failed to validate return_to")
233 def test_verifyFailIfDiscoveryRedirects(self
):
234 realm
= 'http://*.example.com/'
235 return_to
= 'http://www.example.com/foo'
238 raise trustroot
.RealmVerificationRedirected(
239 disco_url
, "http://redirected.invalid")
242 trustroot
.verifyReturnTo(realm
, return_to
, _vrfy
=vrfy
))
243 self
.failUnlessLogMatches("Attempting to verify")
245 if __name__
== '__main__':