Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/cherrypy/lib/auth.py
blob: 7d2f6dc2fbe9f2da3eee2229ecb04d8ab947673f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import cherrypy
from cherrypy.lib import httpauth


def check_auth(users, encrypt=None, realm=None):
    """If an authorization header contains credentials, return True, else False."""
    request = cherrypy.serving.request
    if 'authorization' in request.headers:
        # make sure the provided credentials are correctly set
        ah = httpauth.parseAuthorization(request.headers['authorization'])
        if ah is None:
            raise cherrypy.HTTPError(400, 'Bad Request')
        
        if not encrypt:
            encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5]
        
        if hasattr(users, '__call__'):
            try:
                # backward compatibility
                users = users() # expect it to return a dictionary
                
                if not isinstance(users, dict):
                    raise ValueError("Authentication users must be a dictionary")
                
                # fetch the user password
                password = users.get(ah["username"], None)
            except TypeError:
                # returns a password (encrypted or clear text)
                password = users(ah["username"])
        else:
            if not isinstance(users, dict):
                raise ValueError("Authentication users must be a dictionary")
            
            # fetch the user password
            password = users.get(ah["username"], None)
        
        # validate the authorization by re-computing it here
        # and compare it with what the user-agent provided
        if httpauth.checkResponse(ah, password, method=request.method,
                                  encrypt=encrypt, realm=realm):
            request.login = ah["username"]
            return True
        
        request.login = False
    return False

def basic_auth(realm, users, encrypt=None, debug=False):
    """If auth fails, raise 401 with a basic authentication header.
    
    realm
        A string containing the authentication realm.
        
    users
        A dict of the form: {username: password} or a callable returning a dict.
        
    encrypt
        callable used to encrypt the password returned from the user-agent.
        if None it defaults to a md5 encryption.
        
    """
    if check_auth(users, encrypt):
        if debug:
            cherrypy.log('Auth successful', 'TOOLS.BASIC_AUTH')
        return
    
    # inform the user-agent this path is protected
    cherrypy.serving.response.headers['www-authenticate'] = httpauth.basicAuth(realm)
    
    raise cherrypy.HTTPError(401, "You are not authorized to access that resource")

def digest_auth(realm, users, debug=False):
    """If auth fails, raise 401 with a digest authentication header.
    
    realm
        A string containing the authentication realm.
    users
        A dict of the form: {username: password} or a callable returning a dict.
    """
    if check_auth(users, realm=realm):
        if debug:
            cherrypy.log('Auth successful', 'TOOLS.DIGEST_AUTH')
        return
    
    # inform the user-agent this path is protected
    cherrypy.serving.response.headers['www-authenticate'] = httpauth.digestAuth(realm)
    
    raise cherrypy.HTTPError(401, "You are not authorized to access that resource")