David Tulloh
2016-04-20 d7df42ae13a2a9bfb73a76ed96997dad88a794a9
commit | author | age
359fe8 1 :mod:`repoze.who` Use Cases
TS 2 ===========================
3
4 How should an application interact with :mod:`repoze.who`?  There are three
5 main scenarios:
6
7 Middleware-Only Use Cases
8 -------------------------
9
10 Examples of using the :mod:`repoze.who` middleware, without explicitly
11 using its API.
12
13
14 Simple:  Bug Tracker with ``REMOTE_USER``
15 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16
17 This application expects the ``REMOTE_USER`` variable to be set by
18 the middleware for authenticated requests.  It allows the middleware to
19 handle challenging the user when needed.
20
21 In protected views, such as those which allow creating or following up
22 to bug reports:
23
24 - Check ``environ['REMOTE_USER']`` to get the authenticated user, and apply
25   any application-specific policy (who is allowed to edit).
26
27   - If the access check fails because the user is not yet authenticated,
28     return an 401 Unauthorized response.
29
30   - If the access check fails for authenticated users, return a
31     403 Forbidden response.
32
33 Note that the application here doesn't depend on :mod:`repoze.who` at
34 all:  it would work identically if run behind Apache's ``mod_auth``.  The
35 ``Trac`` application works exactly this way.
36
37 The middleware can be configured to suit the policy required for the
38 site, e.g.:
39
40 - challenge / identify using HTTP basic authentication
41
42 - authorize via an ``.htaccces``-style file.
43
44
45 More complex:  Wiki with ``repoze.who.identity``
46 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47
48 This application use the ``repoze.who.identity`` variable set in the
49 WSGI environment by the middleware for authenticated requests.  The application
50 still allows the middleware to handle challenging the user when needed.
51
52 The only difference from the previous example is that protected views,
53 such as those which allow adding or editing wiki pages, can use the extra
54 metadata stored inside ``environ['repoze.who.identity']`` (a mapping) to
55 make authorization decisions:  such metadata might include groups or roles
56 mapped by the middleware onto the user.
57
58
59 API-Only Use Cases
60 ------------------
61
62 Examples of using the :mod:`repoze.who` API without its middleware.
63
64
65 Simple:   Wiki with its own login and logout views.
66 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67
68 This application uses the :mod:`repoze.who` API to compute the authenticated
69 user, as well as using its ``remember`` API to set headers for cookie-based
70 authentication.
71
72 In each view:
73
74 - Call ``api.authenticate`` to get the authenticated user.
75
76 - Show a ``login`` link for non-authenticated requests.
77
78 - Show a ``logout`` link for authenticated requests.
79
80 - Don't show "protected" links for non-authenticated requests.
81
82 In protected views, such as those which allow adding or editing
83 wiki pages:
84
85 - Call ``api.authenticate`` to get the authenticated user;  check
86   the metadata about the user (e.g., any appropriate roles or groups)
87   to verify access.
88
89   - If the access check fails because the user is not yet authenticated,
90     redirect to the ``login`` view, with a ``came_from`` value of the
91     current URL.
92
93   - If the access check fails for authenticated users, return a
94     403 Forbidden response.
95
96 In the login view:
97
98 - For ``GET`` requests, show the login form.
99
100 - For ``POST`` requests, validate the login and password from the form.
101   If successful, call ``api.remember``, and append the returned headers to
102   your response, which may also contain, e.g., a ``Location`` header for
103   a redirect to the ``came_from`` URL.  In this case, there will be
104   no authenticator plugin which knows about the login / password at all.
105
106 In the logout view:
107
108 - Call ``api.forget`` and append the headers to your response, which may
109   also contain, e.g., a ``Location`` header for a redirect to the
110   ``came_from`` URL after logging out.
111
112
113 More complex:  multiple applications with "single sign-on"
114 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115
116 In this scenario, authentication is "federated" across multiple applications,
117 which delegate to a central "login application."  This application verifies
118 credentials from the user, and then uses headers or other tokens to
119 communicate the verified identity to the delegating application.
120
121 In the login application:
122
123 - The SSO login application works just like the login view described above:
124   the difference is that the configured identifier plugins must emit
125   headers from ``remember`` which can be recognized by their counterparts
126   in the other apps.
127
128 In the non-login applications:
129
130 - Challenge plugins here must be configured to implement the specific
131   SSO protocol, e.g. redirect to the login app with information in the
132   query string (other protocols might differ).
133
134 - Identifer plugins must be able to "crack" / consume whatever tokens are
135   returned by the SSO login app.
136
137 - Authenticators will normally be no-ops (e.g., the ``auth_tkt`` plugin
138   used as an authenticator).
139
140 Hybrid Use Cases
141 ----------------
142
143 Examples of using the :mod:`repoze.who` API in conjuntion with its middleware.
144
145 Most complex:  integrate Trac and the wiki behind SSO
146 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
147
148 This example extends the previous one, but adds into the mix the
149 requirement that one or more of the non-login applications (e.g., Trac)
150 be used "off the shelf," without modifying them.  Such applications can
151 be plugged into the same SSO regime, with the addition of the
152 :mod:``repoze.who`` middleware as an adapter to bridge the gap (e.g.,
153 to turn the SSO tokens into the ``REMOTE_USER`` required by Trac).
154
155 In this scenario, the middleware would be configured identically to the
156 API used in applications which do not need the middleware shim.