OpenSecurity/install/web.py-0.37/web/webopenid.py
author om
Mon, 02 Dec 2013 14:02:05 +0100
changeset 3 65432e6c6042
permissions -rwxr-xr-x
initial deployment and project layout commit
om@3
     1
"""openid.py: an openid library for web.py
om@3
     2
om@3
     3
Notes:
om@3
     4
om@3
     5
 - This will create a file called .openid_secret_key in the 
om@3
     6
   current directory with your secret key in it. If someone 
om@3
     7
   has access to this file they can log in as any user. And 
om@3
     8
   if the app can't find this file for any reason (e.g. you 
om@3
     9
   moved the app somewhere else) then each currently logged 
om@3
    10
   in user will get logged out.
om@3
    11
om@3
    12
 - State must be maintained through the entire auth process 
om@3
    13
   -- this means that if you have multiple web.py processes 
om@3
    14
   serving one set of URLs or if you restart your app often 
om@3
    15
   then log ins will fail. You have to replace sessions and 
om@3
    16
   store for things to work.
om@3
    17
om@3
    18
 - We set cookies starting with "openid_".
om@3
    19
om@3
    20
"""
om@3
    21
om@3
    22
import os
om@3
    23
import random
om@3
    24
import hmac
om@3
    25
import __init__ as web
om@3
    26
import openid.consumer.consumer
om@3
    27
import openid.store.memstore
om@3
    28
om@3
    29
sessions = {}
om@3
    30
store = openid.store.memstore.MemoryStore()
om@3
    31
om@3
    32
def _secret():
om@3
    33
    try:
om@3
    34
        secret = file('.openid_secret_key').read()
om@3
    35
    except IOError:
om@3
    36
        # file doesn't exist
om@3
    37
        secret = os.urandom(20)
om@3
    38
        file('.openid_secret_key', 'w').write(secret)
om@3
    39
    return secret
om@3
    40
om@3
    41
def _hmac(identity_url):
om@3
    42
    return hmac.new(_secret(), identity_url).hexdigest()
om@3
    43
om@3
    44
def _random_session():
om@3
    45
    n = random.random()
om@3
    46
    while n in sessions:
om@3
    47
        n = random.random()
om@3
    48
    n = str(n)
om@3
    49
    return n
om@3
    50
om@3
    51
def status():
om@3
    52
    oid_hash = web.cookies().get('openid_identity_hash', '').split(',', 1)
om@3
    53
    if len(oid_hash) > 1:
om@3
    54
        oid_hash, identity_url = oid_hash
om@3
    55
        if oid_hash == _hmac(identity_url):
om@3
    56
            return identity_url
om@3
    57
    return None
om@3
    58
om@3
    59
def form(openid_loc):
om@3
    60
    oid = status()
om@3
    61
    if oid:
om@3
    62
        return '''
om@3
    63
        <form method="post" action="%s">
om@3
    64
          <img src="http://openid.net/login-bg.gif" alt="OpenID" />
om@3
    65
          <strong>%s</strong>
om@3
    66
          <input type="hidden" name="action" value="logout" />
om@3
    67
          <input type="hidden" name="return_to" value="%s" />
om@3
    68
          <button type="submit">log out</button>
om@3
    69
        </form>''' % (openid_loc, oid, web.ctx.fullpath)
om@3
    70
    else:
om@3
    71
        return '''
om@3
    72
        <form method="post" action="%s">
om@3
    73
          <input type="text" name="openid" value="" 
om@3
    74
            style="background: url(http://openid.net/login-bg.gif) no-repeat; padding-left: 18px; background-position: 0 50%%;" />
om@3
    75
          <input type="hidden" name="return_to" value="%s" />
om@3
    76
          <button type="submit">log in</button>
om@3
    77
        </form>''' % (openid_loc, web.ctx.fullpath)
om@3
    78
om@3
    79
def logout():
om@3
    80
    web.setcookie('openid_identity_hash', '', expires=-1)
om@3
    81
om@3
    82
class host:
om@3
    83
    def POST(self):
om@3
    84
        # unlike the usual scheme of things, the POST is actually called
om@3
    85
        # first here
om@3
    86
        i = web.input(return_to='/')
om@3
    87
        if i.get('action') == 'logout':
om@3
    88
            logout()
om@3
    89
            return web.redirect(i.return_to)
om@3
    90
om@3
    91
        i = web.input('openid', return_to='/')
om@3
    92
om@3
    93
        n = _random_session()
om@3
    94
        sessions[n] = {'webpy_return_to': i.return_to}
om@3
    95
        
om@3
    96
        c = openid.consumer.consumer.Consumer(sessions[n], store)
om@3
    97
        a = c.begin(i.openid)
om@3
    98
        f = a.redirectURL(web.ctx.home, web.ctx.home + web.ctx.fullpath)
om@3
    99
om@3
   100
        web.setcookie('openid_session_id', n)
om@3
   101
        return web.redirect(f)
om@3
   102
om@3
   103
    def GET(self):
om@3
   104
        n = web.cookies('openid_session_id').openid_session_id
om@3
   105
        web.setcookie('openid_session_id', '', expires=-1)
om@3
   106
        return_to = sessions[n]['webpy_return_to']
om@3
   107
om@3
   108
        c = openid.consumer.consumer.Consumer(sessions[n], store)
om@3
   109
        a = c.complete(web.input(), web.ctx.home + web.ctx.fullpath)
om@3
   110
om@3
   111
        if a.status.lower() == 'success':
om@3
   112
            web.setcookie('openid_identity_hash', _hmac(a.identity_url) + ',' + a.identity_url)
om@3
   113
om@3
   114
        del sessions[n]
om@3
   115
        return web.redirect(return_to)