commit | author | age
|
d9c4cb
|
1 |
.. _qtut_authentication: |
SP |
2 |
|
b1b922
|
3 |
============================== |
e5c279
|
4 |
20: Logins with authentication |
b1b922
|
5 |
============================== |
PE |
6 |
|
b92a5f
|
7 |
Login views that authenticate a username and password against a list of users. |
SP |
8 |
|
b1b922
|
9 |
|
PE |
10 |
Background |
|
11 |
========== |
|
12 |
|
b92a5f
|
13 |
Most web applications have URLs that allow people to add/edit/delete content |
SP |
14 |
via a web browser. Time to add :ref:`security <security_chapter>` to the |
|
15 |
application. In this first step we introduce authentication. That is, logging |
|
16 |
in and logging out, using Pyramid's rich facilities for pluggable user storage. |
b1b922
|
17 |
|
b92a5f
|
18 |
In the next step we will introduce protection of resources with authorization |
SP |
19 |
security statements. |
|
20 |
|
b1b922
|
21 |
|
PE |
22 |
Objectives |
|
23 |
========== |
|
24 |
|
b92a5f
|
25 |
- Introduce the Pyramid concepts of authentication. |
b1b922
|
26 |
|
b92a5f
|
27 |
- Create login and logout views. |
b1b922
|
28 |
|
PE |
29 |
Steps |
|
30 |
===== |
|
31 |
|
|
32 |
#. We are going to use the view classes step as our starting point: |
|
33 |
|
|
34 |
.. code-block:: bash |
|
35 |
|
cd648a
|
36 |
cd ..; cp -r view_classes authentication; cd authentication |
29d12c
|
37 |
|
e5c279
|
38 |
#. Add ``bcrypt`` as a dependency in ``authentication/setup.py``: |
29d12c
|
39 |
|
KY |
40 |
.. literalinclude:: authentication/setup.py |
e5c279
|
41 |
:language: python |
e73977
|
42 |
:emphasize-lines: 6 |
29d12c
|
43 |
:linenos: |
KY |
44 |
|
e5c279
|
45 |
#. We can now install our project in development mode: |
29d12c
|
46 |
|
KY |
47 |
.. code-block:: bash |
|
48 |
|
cd648a
|
49 |
$VENV/bin/pip install -e . |
b1b922
|
50 |
|
PE |
51 |
#. Put the security hash in the ``authentication/development.ini`` |
b92a5f
|
52 |
configuration file as ``tutorial.secret`` instead of putting it in the code: |
b1b922
|
53 |
|
PE |
54 |
.. literalinclude:: authentication/development.ini |
|
55 |
:language: ini |
|
56 |
:linenos: |
|
57 |
|
b92a5f
|
58 |
#. Get authentication (and for now, authorization policies) and login route |
SP |
59 |
into the :term:`configurator` in ``authentication/tutorial/__init__.py``: |
b1b922
|
60 |
|
PE |
61 |
.. literalinclude:: authentication/tutorial/__init__.py |
|
62 |
:linenos: |
|
63 |
|
b92a5f
|
64 |
#. Create an ``authentication/tutorial/security.py`` module that can find our |
SP |
65 |
user information by providing an *authentication policy callback*: |
b1b922
|
66 |
|
PE |
67 |
.. literalinclude:: authentication/tutorial/security.py |
|
68 |
:linenos: |
|
69 |
|
|
70 |
#. Update the views in ``authentication/tutorial/views.py``: |
|
71 |
|
|
72 |
.. literalinclude:: authentication/tutorial/views.py |
|
73 |
:linenos: |
|
74 |
|
|
75 |
#. Add a login template at ``authentication/tutorial/login.pt``: |
|
76 |
|
|
77 |
.. literalinclude:: authentication/tutorial/login.pt |
|
78 |
:language: html |
|
79 |
:linenos: |
|
80 |
|
b92a5f
|
81 |
#. Provide a login/logout box in ``authentication/tutorial/home.pt``: |
b1b922
|
82 |
|
PE |
83 |
.. literalinclude:: authentication/tutorial/home.pt |
|
84 |
:language: html |
|
85 |
:linenos: |
|
86 |
|
|
87 |
#. Run your Pyramid application with: |
|
88 |
|
|
89 |
.. code-block:: bash |
|
90 |
|
cd648a
|
91 |
$VENV/bin/pserve development.ini --reload |
b1b922
|
92 |
|
d749bf
|
93 |
#. Open http://localhost:6543/ in a browser. |
b1b922
|
94 |
|
PE |
95 |
#. Click the "Log In" link. |
|
96 |
|
e68e30
|
97 |
#. Submit the login form with the username ``editor`` and the password |
b1b922
|
98 |
``editor``. |
PE |
99 |
|
|
100 |
#. Note that the "Log In" link has changed to "Logout". |
|
101 |
|
|
102 |
#. Click the "Logout" link. |
|
103 |
|
|
104 |
Analysis |
|
105 |
======== |
|
106 |
|
b92a5f
|
107 |
Unlike many web frameworks, Pyramid includes a built-in but optional security |
SP |
108 |
model for authentication and authorization. This security system is intended to |
|
109 |
be flexible and support many needs. In this security model, authentication (who |
|
110 |
are you) and authorization (what are you allowed to do) are not just pluggable, |
e5c279
|
111 |
but decoupled. To learn one step at a time, we provide a system that identifies |
SP |
112 |
users and lets them log out. |
b1b922
|
113 |
|
b92a5f
|
114 |
In this example we chose to use the bundled :ref:`AuthTktAuthenticationPolicy |
SP |
115 |
<authentication_module>` policy. We enabled it in our configuration and |
|
116 |
provided a ticket-signing secret in our INI file. |
b1b922
|
117 |
|
b92a5f
|
118 |
Our view class grew a login view. When you reached it via a ``GET`` request, it |
SP |
119 |
returned a login form. When reached via ``POST``, it processed the submitted |
|
120 |
username and password against the "groupfinder" callable that we registered in |
|
121 |
the configuration. |
e5c279
|
122 |
|
SP |
123 |
The function ``hash_password`` uses a one-way hashing algorithm with a salt on |
|
124 |
the user's password via ``bcrypt``, instead of storing the password in plain |
|
125 |
text. This is considered to be a "best practice" for security. |
|
126 |
|
|
127 |
.. note:: |
|
128 |
There are alternative libraries to ``bcrypt`` if it is an issue on your |
|
129 |
system. Just make sure that the library uses an algorithm approved for |
|
130 |
storing passwords securely. |
|
131 |
|
|
132 |
The function ``check_password`` will compare the two hashed values of the |
|
133 |
submitted password and the user's password stored in the database. If the |
|
134 |
hashed values are equivalent, then the user is authenticated, else |
|
135 |
authentication fails. |
b1b922
|
136 |
|
b92a5f
|
137 |
In our template, we fetched the ``logged_in`` value from the view class. We use |
SP |
138 |
this to calculate the logged-in user, if any. In the template we can then |
|
139 |
choose to show a login link to anonymous visitors or a logout link to logged-in |
|
140 |
users. |
b1b922
|
141 |
|
b92a5f
|
142 |
|
SP |
143 |
Extra credit |
b1b922
|
144 |
============ |
PE |
145 |
|
|
146 |
#. What is the difference between a user and a principal? |
|
147 |
|
|
148 |
#. Can I use a database behind my ``groupfinder`` to look up principals? |
|
149 |
|
b92a5f
|
150 |
#. Once I am logged in, does any user-centric information get jammed onto each |
SP |
151 |
request? Use ``import pdb; pdb.set_trace()`` to answer this. |
b1b922
|
152 |
|
2033ee
|
153 |
.. seealso:: See also :ref:`security_chapter`, |
e5c279
|
154 |
:ref:`AuthTktAuthenticationPolicy <authentication_module>`, `bcrypt |
8bd6f7
|
155 |
<https://pypi.org/project/bcrypt/>`_ |