27
27
For more information, see the README in the root of the library
28
28
distribution or http://www.openidenabled.com/
32
from openid import oidutil
32
from openid import sreg
33
33
from openid.server import server
34
34
from openid.store.filestore import FileOpenIDStore
35
from openid.consumer import discover
36
37
class OpenIDHTTPServer(HTTPServer):
38
39
http server that contains a reference to an OpenID Server and
39
40
knows its base URL.
41
def __init__(self, oidserver, *args, **kwargs):
42
def __init__(self, *args, **kwargs):
42
43
HTTPServer.__init__(self, *args, **kwargs)
44
45
if self.server_port != 80:
48
49
self.base_url = 'http://%s/' % (self.server_name,)
50
self.openid = oidserver
52
53
self.lastCheckIDRequest = {}
55
def setOpenIDServer(self, oidserver):
56
self.openid = oidserver
54
59
class ServerHandler(BaseHTTPRequestHandler):
55
60
def __init__(self, *args, **kwargs):
77
82
self.showLoginPage('/', '/')
78
83
elif path == '/loginsubmit':
85
elif path.startswith('/id/'):
81
86
self.showIdPage(path)
87
elif path.startswith('/yadis/'):
88
self.showYadis(path[7:])
89
elif path == '/serveryadis':
90
self.showServerYadis()
92
self.send_response(404)
83
95
except (KeyboardInterrupt, SystemExit):
124
136
request = self.server.lastCheckIDRequest.get(self.user)
126
138
if 'yes' in query:
127
identity = request.identity
139
if 'login_as' in query:
140
self.user = self.query['login_as']
142
if request.idSelect():
143
identity = self.server.base_url + 'id/' + query['identifier']
145
identity = request.identity
128
147
trust_root = request.trust_root
129
148
if self.query.get('remember', 'no') == 'yes':
134
self.server.approved[(identity, trust_root)] = duration
136
if 'login_as' in query:
137
self.user = self.query['login_as']
139
response = request.answer(True)
149
self.server.approved[(identity, trust_root)] = 'always'
151
response = self.approved(request, identity)
141
153
elif 'no' in query:
142
154
response = request.answer(False)
158
170
if self.user is None:
161
if identity_url != self.server.base_url + self.user:
173
if identity_url != self.server.base_url + 'id/' + self.user:
164
176
key = (identity_url, trust_root)
165
approval = self.server.approved.get(key)
166
if approval == 'once':
167
del self.server.approved[key]
169
return approval is not None
177
return self.server.approved.get(key) is not None
171
179
def serverEndPoint(self, query):
183
191
if request.mode in ["checkid_immediate", "checkid_setup"]:
185
self.isAuthorized(request.identity, request.trust_root)):
186
response = request.answer(True)
187
elif request.immediate:
188
response = request.answer(
189
False, server_url=self.server.base_url + 'openidserver')
191
self.server.lastCheckIDRequest[self.user] = request
192
self.showDecidePage(request)
192
self.handleCheckIDRequest(request)
195
194
response = self.server.openid.handleRequest(request)
196
self.displayResponse(response)
195
self.displayResponse(response)
197
def addSRegResponse(self, request, response):
198
sreg_req = sreg.SRegRequest.fromOpenIDRequest(request)
200
# In a real application, this data would be user-specific,
201
# and the user should be asked for permission to release
207
sreg_resp = sreg.SRegResponse.extractResponse(sreg_req, sreg_data)
208
response.addExtension(sreg_resp)
210
def approved(self, request, identifier=None):
211
response = request.answer(True, identity=identifier)
212
self.addSRegResponse(request, response)
215
def handleCheckIDRequest(self, request):
216
is_authorized = self.isAuthorized(request.identity, request.trust_root)
218
response = self.approved(request)
219
self.displayResponse(response)
220
elif request.immediate:
221
response = request.answer(False)
222
self.displayResponse(response)
224
self.server.lastCheckIDRequest[self.user] = request
225
self.showDecidePage(request)
198
227
def displayResponse(self, response):
305
334
''' % error_message)
307
336
def showDecidePage(self, request):
308
expected_user = request.identity[len(self.server.base_url):]
337
id_url_base = self.server.base_url+'id/'
338
# XXX: This may break if there are any synonyms for id_url_base,
339
# such as referring to it by IP address or a CNAME.
340
assert request.identity.startswith(id_url_base)
341
expected_user = request.identity[len(id_url_base):]
310
if expected_user == self.user:
312
<p>A new site has asked for your identity. If you
343
if request.idSelect(): # We are being asked to select an ID
345
<p>A site has asked for your identity. You may select an
346
identifier by which you would like this site to know you.
347
On a production site this would likely be a drop down list
348
of pre-created accounts or have the facility to generate
349
a random anonymous identifier.
353
'id_url_base': id_url_base,
354
'trust_root': request.trust_root,
357
<form method="POST" action="/allow">
359
<tr><td>Identity:</td>
360
<td>%(id_url_base)s<input type='text' name='identifier'></td></tr>
361
<tr><td>Trust Root:</td><td>%(trust_root)s</td></tr>
363
<p>Allow this authentication to proceed?</p>
364
<input type="checkbox" id="remember" name="remember" value="yes"
365
/><label for="remember">Remember this
366
decision</label><br />
367
<input type="submit" name="yes" value="yes" />
368
<input type="submit" name="no" value="no" />
371
elif expected_user == self.user:
373
<p>A new site has asked to confirm your identity. If you
313
374
approve, the site represented by the trust root below will
314
375
be told that you control identity URL listed below. (If
315
376
you are using a delegated identity, the site will take
327
388
<p>Allow this authentication to proceed?</p>
328
389
<form method="POST" action="/allow">
329
390
<input type="checkbox" id="remember" name="remember" value="yes"
330
checked="checked" /><label for="remember">Remember this
391
/><label for="remember">Remember this
331
392
decision</label><br />
332
393
<input type="submit" name="yes" value="yes" />
333
394
<input type="submit" name="no" value="no" />
357
418
<p>Allow this authentication to proceed?</p>
358
419
<form method="POST" action="/allow">
359
420
<input type="checkbox" id="remember" name="remember" value="yes"
360
checked="checked" /><label for="remember">Remember this
421
/><label for="remember">Remember this
361
422
decision</label><br />
362
423
<input type="hidden" name="login_as" value="%(expected_user)s"/>
363
424
<input type="submit" name="yes" value="yes" />
367
428
self.showPage(200, 'Approve OpenID request?', msg=msg, form=form)
369
430
def showIdPage(self, path):
370
tag = '<link rel="openid.server" href="%sopenidserver">' %\
431
link_tag = '<link rel="openid.server" href="%sopenidserver">' %\
371
432
self.server.base_url
433
yadis_loc_tag = '<meta http-equiv="x-xrds-location" content="%s">'%\
434
(self.server.base_url+'yadis/'+path[4:])
435
disco_tags = link_tag + yadis_loc_tag
372
436
ident = self.server.base_url + path[1:]
374
438
approved_trust_roots = []
388
self.showPage(200, 'An Identity Page', link_tag=tag, msg='''\
452
self.showPage(200, 'An Identity Page', head_extras=disco_tags, msg='''\
389
453
<p>This is an identity page for %s.</p>
391
455
''' % (ident, msg))
457
def showYadis(self, user):
458
self.send_response(200)
459
self.send_header('Content-type', 'application/xrds+xml')
462
endpoint_url = self.server.base_url + 'openidserver'
463
user_url = self.server.base_url + 'id/' + user
464
self.wfile.write("""\
465
<?xml version="1.0" encoding="UTF-8"?>
467
xmlns:xrds="xri://$xrds"
468
xmlns="xri://$xrd*($v*2.0)">
471
<Service priority="0">
475
<LocalID>%s</LocalID>
480
"""%(discover.OPENID_2_0_TYPE, discover.OPENID_1_0_TYPE,
481
endpoint_url, user_url))
483
def showServerYadis(self):
484
self.send_response(200)
485
self.send_header('Content-type', 'application/xrds+xml')
488
endpoint_url = self.server.base_url + 'openidserver'
489
self.wfile.write("""\
490
<?xml version="1.0" encoding="UTF-8"?>
492
xmlns:xrds="xri://$xrds"
493
xmlns="xri://$xrd*($v*2.0)">
496
<Service priority="0">
503
"""%(discover.OPENID_IDP_2_0_TYPE, endpoint_url,))
393
505
def showMainPage(self):
506
yadis_tag = '<meta http-equiv="x-xrds-location" content="%s">'%\
507
(self.server.base_url + 'serveryadis')
395
openid_url = self.server.base_url + self.user
509
openid_url = self.server.base_url + 'id/' + self.user
396
510
user_message = """\
397
511
<p>You are logged in as %s. Your OpenID identity URL is
398
512
<tt><a href=%s>%s</a></tt>. Enter that URL at an OpenID
404
518
order to simulate a standard Web user experience. You are
405
519
not <a href='/login'>logged in</a>.</p>"""
407
self.showPage(200, 'Main Page', msg='''\
521
self.showPage(200, 'Main Page', head_extras = yadis_tag, msg='''\
408
522
<p>This is a simple OpenID server implemented using the <a
409
523
href="http://openid.schtuff.com/">Python OpenID
435
549
''' % (success_to, fail_to))
437
551
def showPage(self, response_code, title,
438
link_tag='', msg=None, err=None, form=None):
552
head_extras='', msg=None, err=None, form=None):
440
554
if self.user is None:
441
555
user_link = '<a href="/login">not logged in</a>.'
443
user_link = 'logged in as <a href="/%s">%s</a>.<br /><a href="/loginsubmit?submit=true&success_to=/login">Log out</a>' % \
557
user_link = 'logged in as <a href="/id/%s">%s</a>.<br /><a href="/loginsubmit?submit=true&success_to=/login">Log out</a>' % \
444
558
(self.user, self.user)
470
584
'title': 'Python OpenID Server Example - ' + title,
471
'link_tag': link_tag,
585
'head_extras': head_extras,
473
587
'user_link': user_link,
476
590
self.send_response(response_code)
477
591
self.writeUserHeader()
479
self.wfile.write('''\
480
Content-type: text/html
592
self.send_header('Content-type', 'text/html')
595
self.wfile.write('''<html>
484
597
<title>%(title)s</title>
487
600
<style type="text/css">
560
673
def main(host, port, data_path):
675
httpserver = OpenIDHTTPServer(addr, ServerHandler)
561
677
# Instantiate OpenID consumer store and OpenID consumer. If you
562
678
# were connecting to a database, you would create the database
563
679
# connection and instantiate an appropriate store here.
565
server_url = 'http://%s/openidserver' % host
567
server_url = 'http://%s:%s/openidserver' % (host, port)
568
680
store = FileOpenIDStore(data_path)
569
oidserver = server.Server(store)
681
oidserver = server.Server(store, httpserver.base_url + 'openidserver')
572
httpserver = OpenIDHTTPServer(oidserver, addr, ServerHandler)
683
httpserver.setOpenIDServer(oidserver)
574
685
print 'Server running at:'
575
686
print httpserver.base_url