Skip to content

Commit 3c50751

Browse files
authored
Fluff updates. (#1177)
Tried out copilot to look at docs and tests. A few suggestions on making things more consistent - but nothing really worth the time spent.
1 parent c052aba commit 3c50751

24 files changed

+143
-122
lines changed

CHANGES.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ Backwards Compatibility Concerns
492492

493493
- To align with the W3C WebAuthn Level2 and 3 spec - transports are now part of the registration response.
494494
This has been changed BOTH in the server code (using webauthn data structures) as well as the sample
495-
javascript code. If an application has their own javascript front end code - it might need to be changed.
495+
JavaScript code. If an application has their own JavaScript front end code - it might need to be changed.
496496
- The tf_validity feature :py:data:`SECURITY_TWO_FACTOR_ALWAYS_VALIDATE` used to set a cookie if the request was
497497
form based, and return the token as part of a JSON response. Now, this feature is ONLY cookie based and the token
498498
is no longer returned as part of any response.

docs/api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ Utils
178178

179179
.. py:class:: OauthCbType[oauth: OAuth, token: t.Any]
180180
181-
This callback is called when the oauth
181+
This callback is called when the OAuth
182182
redirect happens. It must take the response from the provider and return
183183
a tuple of <user_model_field_name, value> - which will be used
184184
to look up the user in the datastore.

docs/configuration.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ These configuration keys are used globally across all features.
148148

149149
.. py:data:: SECURITY_REDIRECT_BEHAVIOR
150150
151-
Passwordless login, confirmation, reset password, unified signin, change_email, and oauth signin
151+
Passwordless login, confirmation, reset password, unified signin, change_email, and OAuth signin
152152
have GET endpoints that validate the passed token and redirect to an action form.
153153
For Single-Page-Applications style UIs which need to control their own internal URL routing these redirects
154154
need to not contain forms, but contain relevant information as query parameters.

docs/features.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ registered. They can be completely disabled or their names can be changed.
284284
Run ``flask --help`` and look for users and roles.
285285

286286

287-
Social/Oauth Authentication
287+
Social/OAuth Authentication
288288
----------------------------
289289
Flask-Security provides a thin layer which integrates `authlib`_ with Flask-Security
290290
views and features (such as two-factor authentication). Flask-Security is shipped

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Flask application. They include:
2222
6. Username management (configuration, recovery, change) (optional)
2323
7. Two-factor authentication via email, SMS, authenticator (optional)
2424
8. WebAuthn Support (optional)
25-
9. 'social'/Oauth for authentication (e.g. google, github, ..) (optional)
25+
9. 'social'/OAuth for authentication (e.g. google, github, ..) (optional)
2626
10. Change email (optional)
2727
11. Login tracking (optional)
2828
12. JSON/Ajax Support

docs/models.rst

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ The provided models are versioned since they represent actual DB models, and any
4040
changes require a schema migration (and perhaps a data migration). Applications
4141
must specifically import the version they want (and handle any required migration).
4242
43-
There are 2 available models - one when using Flask-SQLAlchemy and one when
43+
There are two available models - one when using Flask-SQLAlchemy and one when
4444
using 'raw' sqlalchemy or Flask-SQLAlchemy-Lite.
4545
4646
.. note::
@@ -49,7 +49,8 @@ using 'raw' sqlalchemy or Flask-SQLAlchemy-Lite.
4949
5050
Flask-SQLAlchemy
5151
^^^^^^^^^^^^^^^^
52-
Your application code should import just the required version e.g.::
52+
Your application code should import just the required version e.g.:
53+
.. code-block:: python
5354
5455
from flask_security.models import fsqla_v3 as fsqla
5556
from flask_sqlalchemy import SQLAlchemy
@@ -71,7 +72,9 @@ DB instance. This is only needed if you use the packaged models.
7172
7273
Flask-SQLAlchemy-Lite
7374
^^^^^^^^^^^^^^^^^^^^^
74-
Your application code should import just the required version e.g.::
75+
Your application code should import just the required version e.g.:
76+
77+
.. code-block:: python
7578
7679
from flask_security.models import sqla as sqla
7780
from flask_sqlalchemy_lite import SQLAlchemy
@@ -222,7 +225,12 @@ Flask-Security must be able to locate a User record based on a credential id.
222225
It is important that you maintain data consistency when deleting WebAuthn
223226
records or users.
224227
225-
The 'WebAuthn' model requires the following fields:
228+
The `User` model needs the following additional field:
229+
230+
* ``fs_webauthn_user_handle`` (string, 64 bytes, unique).
231+
This is used as the `PublicKeyCredentialUserEntity` `id` value.
232+
233+
The `WebAuthn` model requires the following fields:
226234
227235
* ``id`` (primary key)
228236
* ``credential_id`` (binary, 1024 bytes, indexed, non-nullable, unique)
@@ -239,58 +247,66 @@ The 'WebAuthn' model requires the following fields:
239247
There needs to be a bi-directional relationship between the WebAuthn record and
240248
the User record (since we need to look up the ``User`` based on a WebAuthn ``credential_id``.
241249
242-
**For SQLAlchemy**::
250+
**For SQLAlchemy**:
243251
244-
Add the following to the WebAuthn model (assuming your primary key is named ``id``):
252+
- Add the following to the WebAuthn model (assuming your primary key is named ``id``):
245253
246-
@declared_attr
247-
def user_id(cls) -> Mapped[int]:
248-
return mapped_column(
249-
ForeignKey("user.id", ondelete="CASCADE")
250-
)
254+
.. code-block:: python
251255
252-
Add the following to the User model:
256+
@declared_attr
257+
def user_id(cls) -> Mapped[int]:
258+
return mapped_column(
259+
ForeignKey("user.id", ondelete="CASCADE")
260+
)
253261
254-
@declared_attr
255-
def webauthn(cls):
256-
return relationship(
257-
"WebAuthn", back_populates="user", cascade="all, delete"
258-
)
262+
- Add the following to the User model:
259263
260-
**For mongoengine**::
264+
.. code-block:: python
261265
262-
Add the following to the WebAuthn model:
266+
@declared_attr
267+
def webauthn(cls):
268+
return relationship(
269+
"WebAuthn", back_populates="user", cascade="all, delete"
270+
)
271+
272+
**For mongoengine**:
263273
264-
user = ReferenceField("User")
265-
def get_user_mapping(self) -> dict[str, str]:
266-
"""Return the mapping from webauthn back to User"""
267-
return dict(id=self.user.id)
274+
- Add the following to the WebAuthn model:
268275
269-
Add the following to the User model:
276+
.. code-block:: python
270277
271-
webauthn = ListField(ReferenceField(WebAuthn, reverse_delete_rule=PULL), default=[])
278+
user = ReferenceField("User")
279+
def get_user_mapping(self) -> dict[str, str]:
280+
"""Return the mapping from webauthn back to User"""
281+
return dict(id=self.user.id)
272282
273-
To make sure all WebAuthn objects are deleted if the User is deleted:
283+
- Add the following to the User model:
274284
275-
User.register_delete_rule(WebAuthn, "user", CASCADE)
285+
.. code-block:: python
276286
287+
webauthn = ListField(ReferenceField(WebAuthn, reverse_delete_rule=PULL), default=[])
277288
278-
**For peewee**::
289+
- To make sure all WebAuthn objects are deleted if the User is deleted:
290+
291+
.. code-block:: python
292+
293+
User.register_delete_rule(WebAuthn, "user", CASCADE)
294+
295+
296+
**For peewee**:
279297
280298
Add the following to the WebAuthn model:
281299
282-
user = ForeignKeyField(User, backref="webauthn")
300+
.. code-block:: python
301+
302+
user = ForeignKeyField(User, backref="webauthn")
283303
284304
This will add a column called ``user_id`` that references the User model's
285305
``id`` primary key field. It will also create a virtual column ``webauthn``
286306
as part of the User model. Note that the default Peewee datastore implementation
287307
calls ``delete_instance(recursive=True)`` which correctly deals with ensuring
288308
that WebAuthn records get deleted if a User is deleted.
289309
290-
The `User` model needs the following additional fields:
291-
292-
* ``fs_webauthn_user_handle`` (string, 64 bytes, unique).
293-
This is used as the `PublicKeyCredentialUserEntity` `id` value.
294310
295311
Recovery Codes
296312
^^^^^^^^^^^^^^^

docs/patterns.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ of handling all authorization errors. A simple way to do this is to use a specia
4444
class that you can raise either in response to Flask-Security authorization failures, or in your
4545
own code. Then use Flask's ``errorhandler`` to catch that exception and create the appropriate API response::
4646

47-
Class MyForbiddenException(Exception):
47+
class MyForbiddenException(Exception):
4848
def __init__(self, msg='Not permitted with your privileges', status=http.HTTPStatus.FORBIDDEN):
4949
self.info = {'status': status, 'msgs': [msg]}
5050

@@ -262,7 +262,7 @@ with actually retrieving and using a CSRF token. There are 2 normal ways to do t
262262

263263
* Have the csrf-token available via a JSON GET request that can be attached as a
264264
header in every mutating request.
265-
* Have a cookie that can be read via javascript whose value is the csrf-token that
265+
* Have a cookie that can be read via JavaScript whose value is the csrf-token that
266266
can be attached as a header in every mutating request.
267267

268268
Flask-Security supports both solutions.
@@ -337,7 +337,7 @@ Using a Cookie
337337
--------------
338338
You can instruct Flask-Security to send a cookie that contains the csrf token.
339339
The cookie will be set on a call to ``GET /login`` or ``GET /us-signin`` - as well as after a successful authentication.
340-
This can be very convenient since various javascript AJAX packages are pre-configured to extract the contents of a cookie
340+
This can be very convenient since various JavaScript AJAX packages are pre-configured to extract the contents of a cookie
341341
and send it on every mutating request as an HTTP header. `axios`_ for example has a default configuration
342342
that it will look for a cookie named ``XSRF-TOKEN`` and will send the contents of that back
343343
in an HTTP header called ``X-XSRF-Token``. This means that if you use that package you don't need to make

docs/spa.rst

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Working with Single Page Applications
22
======================================
3-
`Single Page Applications (spa)`_ are a popular model for both separating
3+
`Single Page Applications (SPAs)`_ are a popular model for both separating
44
user interface from application/backend code as well as providing a responsive
5-
user experience. Angular and Vue are popular Javascript frameworks for writing SPAs.
5+
user experience. Angular and Vue are popular JavaScript frameworks for writing SPAs.
66
An added benefit is that the UI can be developed completely independently (in a separate repo)
7-
and take advantage of the latest Javascript packing and bundling technologies that are
7+
and take advantage of the latest JavaScript packing and bundling technologies that are
88
evolving rapidly, and not make the Flask application have to deal with things
99
like Flask-Webpack or webassets.
1010

@@ -26,7 +26,9 @@ For the purposes of this application note - this implies:
2626

2727
Configuration
2828
~~~~~~~~~~~~~
29-
An example configuration::
29+
An example configuration:
30+
31+
.. code-block:: python
3032
3133
# no forms so no concept of flashing
3234
SECURITY_FLASH_MESSAGES = False
@@ -77,7 +79,9 @@ An example configuration::
7779
security.unauthz_handler(<your unauth handler>)
7880
7981
When in development mode, the Flask application will run by default on port 5000.
80-
The UI might want to run on port 8080. In order to test redirects you need to set::
82+
The UI might want to run on port 8080. In order to test redirects you need to set:
83+
84+
.. code-block:: python
8185
8286
SECURITY_REDIRECT_HOST = 'localhost:8080'
8387
@@ -104,15 +108,15 @@ standard security headers such as:
104108
* ``X-XSS-Protection``
105109
* ``Referrer policy``
106110

107-
There are a lot of different ways to host a SPA as the javascript part itself is quit easily hosted from any static
111+
There are a lot of different ways to host a SPA as the JavaScript part itself is quit easily hosted from any static
108112
webserver. A couple of deployment options and their configurations will be describer here.
109113

110114
Nginx
111115
~~~~~
112116
When serving a SPA from a Nginx webserver the Flask backend, with Flask-Security, will probably be served via
113-
Nginx's reverse proxy feature. The javascript is served from Nginx itself and all calls to a certain path will be routed
117+
Nginx's reverse proxy feature. The JavaScript is served from Nginx itself and all calls to a certain path will be routed
114118
to the reversed proxy. The example below routes all http requests to *"/api/"* to the Flask backend and handles all other
115-
requests directly from javascript. This has a couple of benefits as all the requests happen within the same domain so you
119+
requests directly from JavaScript. This has a couple of benefits as all the requests happen within the same domain so you
116120
don't have to worry about `CORS`_ problems::
117121

118122
server {
@@ -164,11 +168,13 @@ Most Flask apps can be deployed to Amazon's lambda gateway without much hassle b
164168
You'll get automatic horizontal scaling, seamless upgrades, automatic SSL certificate renewal and a very cheap way of
165169
hosting a backend without being responsible for any infrastructure. Depending on how you design your app you could
166170
choose to host your backend from an api specific domain: e.g. *api.example.com*. When your SPA deployment structure is
167-
capable of routing the AJAX/XHR request from your javascript app to the separate backend; use it. When you want to use
171+
capable of routing the AJAX/XHR request from your JavaScript app to the separate backend; use it. When you want to use
168172
the backend from another e.g. *www.example.com* you have some deal with some `CORS`_ setup as your browser will block
169173
cross-domain POST requests. There is a Flask package for that: `Flask-CORS`_.
170174

171-
The setup of CORS is simple::
175+
The setup of CORS is simple:
176+
177+
.. code-block:: python
172178
173179
CORS(
174180
app,
@@ -179,7 +185,7 @@ The setup of CORS is simple::
179185
expose_headers="Authorization,Content-Type,Authentication-Token,XSRF-TOKEN",
180186
)
181187
182-
You can then host your javascript app from an S3 bucket, with or without Cloudfront, GH-pages or from any static webserver.
188+
You can then host your JavaScript app from an S3 bucket, with or without Cloudfront, GH-pages or from any static webserver.
183189

184190
Some background material:
185191

@@ -188,7 +194,7 @@ Some background material:
188194
* `Flask-Talisman`_ - useful if serving everything from your Flask application - also
189195
useful as a good list of things to consider.
190196

191-
.. _Single Page Applications (spa): https://en.wikipedia.org/wiki/Single-page_application
197+
.. _Single Page Applications (SPAs): https://en.wikipedia.org/wiki/Single-page_application
192198
.. _Nginx: https://www.nginx.com/
193199
.. _S3: https://www.savjee.be/2018/05/Content-security-policy-and-aws-s3-cloudfront/
194200
.. _Flask-Talisman: https://pypi.org/project/flask-talisman/

docs/two_factor_configurations.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Two-factor Application
3131
The following code sample illustrates how to get started as quickly as
3232
possible using SQLAlchemy:
3333

34-
::
34+
.. code-block:: python
3535
3636
import os
3737
from flask import Flask, current_app, render_template_string
@@ -133,7 +133,9 @@ You need to install additional packages::
133133

134134
pip install phonenumberslite twilio
135135

136-
And set additional configuration variables::
136+
And set additional configuration variables:
137+
138+
.. code-block:: python
137139
138140
app.config["SECURITY_TWO_FACTOR_ENABLED_METHODS"] = ['email',
139141
'authenticator', 'sms']
@@ -206,6 +208,6 @@ Fine-Grained Control of Two-Factor
206208
+++++++++++++++++++++++++++++++++++
207209
The decision whether to require a second factor after primary authentication is made in :py:meth:`.UserMixin.check_tf_required`.
208210
The default implementation returns True if :py:data:`SECURITY_TWO_FACTOR_REQUIRED` is set OR the user has a two-factor method already setup AND
209-
and recent two-factor authentication isn't 'valid' (see above).
211+
recent two-factor authentication isn't 'valid' (see above).
210212
211213
This method can be overridden in the applications User class. A common use case might be to require two-factor for any user with the 'admin' role.

docs/webauthn.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ there is at least one second-factor authentication method setup that is NOT plat
4040
Flask-Security requires that when registering a WebAuthn key, the user must specify whether the key
4141
will be used for first/primary authentication or for multi-factor/second authentication.
4242

43-
It should be noted the the current spec REQUIRES javascript to communicate from your front-end to the browser.
43+
It should be noted the the current spec REQUIRES JavaScript to communicate from your front-end to the browser.
4444
Flask-Security ships with the basic required JS (static/{webauthn.js,base64.js}).
45-
An application should be able to simply wire those into their templates or javascript.
45+
An application should be able to simply wire those into their templates or JavaScript.
4646

4747

4848
Configuration

0 commit comments

Comments
 (0)