~gary/python-openid/python-openid-2.2.1-patched

« back to all changes in this revision

Viewing changes to examples/server.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2007-11-30 02:46:28 UTC
  • mfrom: (1.1.1 pyopenid-2.0)
  • Revision ID: launchpad@pqm.canonical.com-20071130024628-qktwsew3383iawmq
[rs=SteveA] upgrade to python-openid-2.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
try:
19
19
    import openid
20
20
except ImportError:
21
 
    print >>sys.stderr, """
 
21
    sys.stderr.write("""
22
22
Failed to import the OpenID library. In order to use this example, you
23
23
must either install the library (see INSTALL in the root of the
24
24
distribution) or else add the library to python's import path (the
26
26
 
27
27
For more information, see the README in the root of the library
28
28
distribution or http://www.openidenabled.com/
29
 
"""
 
29
""")
30
30
    sys.exit(1)
31
31
 
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
35
36
 
36
37
class OpenIDHTTPServer(HTTPServer):
37
38
    """
38
39
    http server that contains a reference to an OpenID Server and
39
40
    knows its base URL.
40
41
    """
41
 
    def __init__(self, oidserver, *args, **kwargs):
 
42
    def __init__(self, *args, **kwargs):
42
43
        HTTPServer.__init__(self, *args, **kwargs)
43
44
 
44
45
        if self.server_port != 80:
47
48
        else:
48
49
            self.base_url = 'http://%s/' % (self.server_name,)
49
50
 
50
 
        self.openid = oidserver
 
51
        self.openid = None
51
52
        self.approved = {}
52
53
        self.lastCheckIDRequest = {}
53
54
 
 
55
    def setOpenIDServer(self, oidserver):
 
56
        self.openid = oidserver
 
57
 
 
58
 
54
59
class ServerHandler(BaseHTTPRequestHandler):
55
60
    def __init__(self, *args, **kwargs):
56
61
        self.user = None
77
82
                self.showLoginPage('/', '/')
78
83
            elif path == '/loginsubmit':
79
84
                self.doLogin()
80
 
            else:
 
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()
 
91
            else:
 
92
                self.send_response(404)
 
93
                self.end_headers()
82
94
 
83
95
        except (KeyboardInterrupt, SystemExit):
84
96
            raise
124
136
        request = self.server.lastCheckIDRequest.get(self.user)
125
137
 
126
138
        if 'yes' in query:
127
 
            identity = request.identity
 
139
            if 'login_as' in query:
 
140
                self.user = self.query['login_as']
 
141
 
 
142
            if request.idSelect():
 
143
                identity = self.server.base_url + 'id/' + query['identifier']
 
144
            else:
 
145
                identity = request.identity
 
146
 
128
147
            trust_root = request.trust_root
129
148
            if self.query.get('remember', 'no') == 'yes':
130
 
                duration = 'always'
131
 
            else:
132
 
                duration = 'once'
133
 
 
134
 
            self.server.approved[(identity, trust_root)] = duration
135
 
 
136
 
            if 'login_as' in query:
137
 
                self.user = self.query['login_as']
138
 
 
139
 
            response = request.answer(True)
 
149
                self.server.approved[(identity, trust_root)] = 'always'
 
150
 
 
151
            response = self.approved(request, identity)
140
152
 
141
153
        elif 'no' in query:
142
154
            response = request.answer(False)
158
170
        if self.user is None:
159
171
            return False
160
172
 
161
 
        if identity_url != self.server.base_url + self.user:
 
173
        if identity_url != self.server.base_url + 'id/' + self.user:
162
174
            return False
163
175
 
164
176
        key = (identity_url, trust_root)
165
 
        approval = self.server.approved.get(key)
166
 
        if approval == 'once':
167
 
            del self.server.approved[key]
168
 
 
169
 
        return approval is not None
 
177
        return self.server.approved.get(key) is not None
170
178
 
171
179
    def serverEndPoint(self, query):
172
180
        try:
181
189
            return
182
190
 
183
191
        if request.mode in ["checkid_immediate", "checkid_setup"]:
184
 
            if (self.user and
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')
190
 
            else:
191
 
                self.server.lastCheckIDRequest[self.user] = request
192
 
                self.showDecidePage(request)
193
 
                return
 
192
            self.handleCheckIDRequest(request)
194
193
        else:
195
194
            response = self.server.openid.handleRequest(request)
196
 
        self.displayResponse(response)
 
195
            self.displayResponse(response)
 
196
 
 
197
    def addSRegResponse(self, request, response):
 
198
        sreg_req = sreg.SRegRequest.fromOpenIDRequest(request)
 
199
 
 
200
        # In a real application, this data would be user-specific,
 
201
        # and the user should be asked for permission to release
 
202
        # it.
 
203
        sreg_data = {
 
204
            'nickname':self.user
 
205
            }
 
206
 
 
207
        sreg_resp = sreg.SRegResponse.extractResponse(sreg_req, sreg_data)
 
208
        response.addExtension(sreg_resp)
 
209
 
 
210
    def approved(self, request, identifier=None):
 
211
        response = request.answer(True, identity=identifier)
 
212
        self.addSRegResponse(request, response)
 
213
        return response
 
214
 
 
215
    def handleCheckIDRequest(self, request):
 
216
        is_authorized = self.isAuthorized(request.identity, request.trust_root)
 
217
        if is_authorized:
 
218
            response = self.approved(request)
 
219
            self.displayResponse(response)
 
220
        elif request.immediate:
 
221
            response = request.answer(False)
 
222
            self.displayResponse(response)
 
223
        else:
 
224
            self.server.lastCheckIDRequest[self.user] = request
 
225
            self.showDecidePage(request)
197
226
 
198
227
    def displayResponse(self, response):
199
228
        try:
305
334
        ''' % error_message)
306
335
 
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):]
309
342
 
310
 
        if expected_user == self.user:
311
 
            msg = '''\
312
 
            <p>A new site has asked for your identity.  If you
 
343
        if request.idSelect(): # We are being asked to select an ID
 
344
            msg = '''\
 
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.
 
350
            </p>
 
351
            '''
 
352
            fdata = {
 
353
                'id_url_base': id_url_base,
 
354
                'trust_root': request.trust_root,
 
355
                }
 
356
            form = '''\
 
357
            <form method="POST" action="/allow">
 
358
            <table>
 
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>
 
362
            </table>
 
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" />
 
369
            </form>
 
370
            '''%fdata
 
371
        elif expected_user == self.user:
 
372
            msg = '''\
 
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)
368
429
 
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:]
373
437
 
374
438
        approved_trust_roots = []
385
449
        else:
386
450
            msg = ''
387
451
 
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>
390
454
        %s
391
455
        ''' % (ident, msg))
392
456
 
 
457
    def showYadis(self, user):
 
458
        self.send_response(200)
 
459
        self.send_header('Content-type', 'application/xrds+xml')
 
460
        self.end_headers()
 
461
 
 
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"?>
 
466
<xrds:XRDS
 
467
    xmlns:xrds="xri://$xrds"
 
468
    xmlns="xri://$xrd*($v*2.0)">
 
469
  <XRD>
 
470
 
 
471
    <Service priority="0">
 
472
      <Type>%s</Type>
 
473
      <Type>%s</Type>
 
474
      <URI>%s</URI>
 
475
      <LocalID>%s</LocalID>
 
476
    </Service>
 
477
 
 
478
  </XRD>
 
479
</xrds:XRDS>
 
480
"""%(discover.OPENID_2_0_TYPE, discover.OPENID_1_0_TYPE,
 
481
     endpoint_url, user_url))
 
482
 
 
483
    def showServerYadis(self):
 
484
        self.send_response(200)
 
485
        self.send_header('Content-type', 'application/xrds+xml')
 
486
        self.end_headers()
 
487
 
 
488
        endpoint_url = self.server.base_url + 'openidserver'
 
489
        self.wfile.write("""\
 
490
<?xml version="1.0" encoding="UTF-8"?>
 
491
<xrds:XRDS
 
492
    xmlns:xrds="xri://$xrds"
 
493
    xmlns="xri://$xrd*($v*2.0)">
 
494
  <XRD>
 
495
 
 
496
    <Service priority="0">
 
497
      <Type>%s</Type>
 
498
      <URI>%s</URI>
 
499
    </Service>
 
500
 
 
501
  </XRD>
 
502
</xrds:XRDS>
 
503
"""%(discover.OPENID_IDP_2_0_TYPE, endpoint_url,))
 
504
 
393
505
    def showMainPage(self):
 
506
        yadis_tag = '<meta http-equiv="x-xrds-location" content="%s">'%\
 
507
            (self.server.base_url + 'serveryadis')
394
508
        if self.user:
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>"""
406
520
 
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
410
524
        library</a>.</p>
435
549
        ''' % (success_to, fail_to))
436
550
 
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):
439
553
 
440
554
        if self.user is None:
441
555
            user_link = '<a href="/login">not logged in</a>.'
442
556
        else:
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)
445
559
 
446
560
        body = ''
468
582
 
469
583
        contents = {
470
584
            'title': 'Python OpenID Server Example - ' + title,
471
 
            'link_tag': link_tag,
 
585
            'head_extras': head_extras,
472
586
            'body': body,
473
587
            'user_link': user_link,
474
588
            }
475
589
 
476
590
        self.send_response(response_code)
477
591
        self.writeUserHeader()
478
 
 
479
 
        self.wfile.write('''\
480
 
Content-type: text/html
481
 
 
482
 
<html>
 
592
        self.send_header('Content-type', 'text/html')
 
593
        self.end_headers()
 
594
 
 
595
        self.wfile.write('''<html>
483
596
  <head>
484
597
    <title>%(title)s</title>
485
 
    %(link_tag)s
 
598
    %(head_extras)s
486
599
  </head>
487
600
  <style type="text/css">
488
601
      h1 a:link {
558
671
 
559
672
 
560
673
def main(host, port, data_path):
 
674
    addr = (host, port)
 
675
    httpserver = OpenIDHTTPServer(addr, ServerHandler)
 
676
 
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.
564
 
    if port == 80:
565
 
        server_url = 'http://%s/openidserver' % host
566
 
    else:
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')
570
682
 
571
 
    addr = (host, port)
572
 
    httpserver = OpenIDHTTPServer(oidserver, addr, ServerHandler)
 
683
    httpserver.setOpenIDServer(oidserver)
573
684
 
574
685
    print 'Server running at:'
575
686
    print httpserver.base_url