Skip to content
Newer
Older
100644 123 lines (94 sloc) 4.02 KB
f1bfb32 @masklinn Fix WEP document titles so the root document displays their descripti…
masklinn authored Sep 11, 2011
1 A very basic description of authentication opportunities in WSGI
2 ================================================================
d46db41 @masklinn Import simple auth wep
masklinn authored Sep 11, 2011
3
4 :Title: Simple Authentication
5 :Author: Ian Bicking <ianb@colorstudy.com>
6 :Discussions-To: Python Web-SIG <web-sig@python.org>
7 :Status: Proposed
8 :Created: 13-Nov-2006
9
10 .. contents::
11
12 Abstract
13 --------
14
15 This describes a simple pattern for implementing authentication in
16 WSGI middleware. This does not propose any new features or
17 environment keys; it only describes a baseline recommended practice.
18
19 Rationale
20 ---------
21
22 Authentication is probably the most common detail that should be
23 abstracted away from an application, as it is a concern most often
24 bound to a *deployment*.
25
26 Specification
27 -------------
28
29 There are two components to authentication:
30
31 1. Indicating when a request is authenticated, and by who
32 2. Responding that authentication is necessary
33
34 There are already two conventions for this:
35
36 1. Put the username in ``REMOTE_USER``
37 2. Respond with ``401 Unauthorized``
38
39 .. note:: Please do not confused ``401 Unauthorized`` with "permission
40 denied". Permission denied should be indicated with ``403
41 Forbidden``.
42
43 ``REMOTE_USER``:
44 This should be the string username of the user, nothing more.
45 ``401 Unauthorized``:
46 Because middleware is handling the authentication, additional
47 information is not required. You do not (and should not) include
48 a ``WWW-Authenticate`` header. The middleware may include that
49 header, or may change the response in some other way to handle the
50 login.
51
52 Example
53 --------
54
55 The first example implements simple HTTP Basic authentication::
56
57 class HTTPBasic(object):
58
59 def __init__(self, app, user_database, realm='Website'):
60 self.app = app
61 self.user_database = user_database
62 self.realm = realm
63
64 def __call__(self, environ, start_response):
65 def repl_start_response(status, headers, exc_info=None):
66 if status.startswith('401'):
67 remove_header(headers, 'WWW-Authenticate')
68 headers.append(('WWW-Authenticate', 'Basic realm="%s"' % self.realm))
69 return start_response(status, headers)
70 auth = environ.get('HTTP_AUTHORIZATION')
71 if auth:
72 scheme, data = auth.split(None, 1)
73 assert scheme.lower() == 'basic'
74 username, password = data.decode('base64').split(':', 1)
75 if self.user_database.get(username) != password:
76 return self.bad_auth(environ, start_response)
77 environ['REMOTE_USER'] = username
78 del environ['HTTP_AUTHORIZATION']
79 return self.app(environ, repl_start_response)
80
81 def bad_auth(self, environ, start_response):
82 body = 'Please authenticate'
83 headers = [
84 ('content-type', 'text/plain'),
85 ('content-length', str(len(body))),
86 ('WWW-Authenticate', 'Basic realm="%s"' % self.realm)]
87 start_response('401 Unauthorized', headers)
88 return [body]
89
90 def remove_header(headers, name):
91 for header in headers:
92 if header[0].lower() == name.lower():
93 headers.remove(header)
94 break
95
96 Problems
97 --------
98
99 * Strictly speaking, it is illegal to send a ``401 Unauthorized``
100 response without the ``WWW-Authenticate header``. If no middleware
101 is installed, most browsers will treat it like a ``200 OK``. There
102 is also no way to detect if an appropriate middleware is installed.
103
104 * This doesn't give any other information about the user. That
105 information can go in other keys, but that is not addressed in this
106 specification currently.
107
108 * Some login methods will redirect the user, and any POST request data
109 will possibly be lost. (Note that a specification like
110 :doc:`handling_post_forms` helps address this problem.)
111
112 Other Possibilities
113 -------------------
114
115 * While you can add to this specification, I think it's the most
116 logical and useful way to do authentication and better efforts can
117 build on this base.
118
119 Open Issues
120 -----------
121
122 See Problems.
Something went wrong with that request. Please try again.