Compare commits

...

6 Commits

7 changed files with 66 additions and 67 deletions

View File

@ -6,13 +6,13 @@ Flask HTTP Digest Authentication
Description Description
=========== ===========
*Flask-Digest-Auth* is an `HTTP Digest Authentication`_ implementation *Flask-DigestAuth* is an `HTTP Digest Authentication`_ implementation
for Flask_ applications. It authenticates the user for the protected for Flask_ applications. It authenticates the user for the protected
views. views.
HTTP Digest Authentication is specified in `RFC 2617`_. HTTP Digest Authentication is specified in `RFC 2617`_.
Refer to the full `Flask-Digest-Auth readthedocs documentation`_. Refer to the full `Flask-DigestAuth readthedocs documentation`_.
Why HTTP Digest Authentication? Why HTTP Digest Authentication?
@ -30,7 +30,7 @@ own challenge-response log in form, but then you are reinventing the
wheels. If a pretty log in form is not critical to your project, HTTP wheels. If a pretty log in form is not critical to your project, HTTP
Digest Authentication should be a good choice. Digest Authentication should be a good choice.
Flask-Digest-Auth works with Flask-Login_. Log in protection can be Flask-DigestAuth works with Flask-Login_. Log in protection can be
separated with the authentication mechanism. You can create protected separated with the authentication mechanism. You can create protected
Flask modules without knowing the actual authentication mechanisms. Flask modules without knowing the actual authentication mechanisms.
@ -38,18 +38,18 @@ Flask modules without knowing the actual authentication mechanisms.
Installation Installation
============ ============
You can install Flask-Digest-Auth with ``pip``: You can install Flask-DigestAuth with ``pip``:
:: ::
pip install Flask-Digest-Auth pip install Flask-DigestAuth
You may also install the latest source from the You may also install the latest source from the
`Flask-Digest-Auth GitHub repository`_. `Flask-DigestAuth GitHub repository`_.
:: ::
pip install git+https://github.com/imacat/flask-digest-auth.git pip install git+https://github.com/imacat/flask-digestauth.git
Setting the Password Setting the Password
@ -70,14 +70,14 @@ you need to ask their password, to generate and store the new password
hash. hash.
Flask-Digest-Auth Alone Flask-DigestAuth Alone
======================= ======================
Flask-Digest-Auth can authenticate the users alone. Flask-DigestAuth can authenticate the users alone.
Simple Applications with Flask-Digest-Auth Alone Simple Applications with Flask-DigestAuth Alone
------------------------------------------------ -----------------------------------------------
In your ``my_app.py``: In your ``my_app.py``:
@ -112,8 +112,8 @@ In your ``my_app.py``:
return redirect(request.form.get("next")) return redirect(request.form.get("next"))
Larger Applications with ``create_app()`` with Flask-Digest-Auth Alone Larger Applications with ``create_app()`` with Flask-DigestAuth Alone
---------------------------------------------------------------------- ---------------------------------------------------------------------
In your ``my_app/__init__.py``: In your ``my_app/__init__.py``:
@ -169,19 +169,19 @@ In your ``my_app/views.py``:
Flask-Login Integration Flask-Login Integration
======================= =======================
Flask-Digest-Auth works with Flask-Login_. You can write a Flask Flask-DigestAuth works with Flask-Login_. You can write a Flask
module that requires log in, without specifying how to log in. The module that requires log in, without specifying how to log in. The
application can use either HTTP Digest Authentication, or the log in application can use either HTTP Digest Authentication, or the log in
forms, as needed. forms, as needed.
To use Flask-Login with Flask-Digest-Auth, To use Flask-Login with Flask-DigestAuth,
``login_manager.init_app(app)`` must be called before ``login_manager.init_app(app)`` must be called before
``auth.init_app(app)``. ``auth.init_app(app)``.
The currently logged-in user can be retrieved at The currently logged-in user can be retrieved at
``flask_login.current_user``, if any. ``flask_login.current_user``, if any.
The views only depend on Flask-Login, but not the Flask-Digest-Auth. The views only depend on Flask-Login, but not the Flask-DigestAuth.
You can change the actual authentication mechanism without changing You can change the actual authentication mechanism without changing
the views. the views.
@ -293,7 +293,7 @@ mechanism without changing the views.
Session Integration Session Integration
=================== ===================
Flask-Digest-Auth features session integration. The user log in Flask-DigestAuth features session integration. The user log in
is remembered in the session. The authentication information is not is remembered in the session. The authentication information is not
requested again. This is different to the practice of the HTTP Digest requested again. This is different to the practice of the HTTP Digest
Authentication, but is convenient for the log in accounting. Authentication, but is convenient for the log in accounting.
@ -315,14 +315,14 @@ logging the log in event, adding the log in counter, etc.
Log Out Log Out
======= =======
Flask-Digest-Auth supports log out. The user will be prompted for the Flask-DigestAuth supports log out. The user will be prompted for the
new username and password. new username and password.
Test Client Test Client
=========== ===========
Flask-Digest-Auth comes with a test client that supports HTTP digest Flask-DigestAuth comes with a test client that supports HTTP digest
authentication. authentication.
@ -389,7 +389,7 @@ A pytest Test
Copyright Copyright
========= =========
Copyright (c) 2022 imacat. Copyright (c) 2022-2023 imacat.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -414,6 +414,6 @@ Authors
.. _HTTP Digest Authentication: https://en.wikipedia.org/wiki/Digest_access_authentication .. _HTTP Digest Authentication: https://en.wikipedia.org/wiki/Digest_access_authentication
.. _RFC 2617: https://www.rfc-editor.org/rfc/rfc2617 .. _RFC 2617: https://www.rfc-editor.org/rfc/rfc2617
.. _Flask: https://flask.palletsprojects.com .. _Flask: https://flask.palletsprojects.com
.. _Flask-Digest-Auth GitHub repository: https://github.com/imacat/flask-digest-auth .. _Flask-DigestAuth GitHub repository: https://github.com/imacat/flask-digestauth
.. _Flask-Digest-Auth readthedocs documentation: https://flask-digest-auth.readthedocs.io .. _Flask-DigestAuth readthedocs documentation: https://flask-digestauth.readthedocs.io
.. _Flask-Login: https://flask-login.readthedocs.io .. _Flask-Login: https://flask-login.readthedocs.io

View File

@ -10,10 +10,10 @@ sys.path.insert(0, os.path.abspath('../../src/'))
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'Flask-Digest-Auth' project = 'Flask-DigestAuth'
copyright = '2022, imacat' copyright = '2022-2023, imacat'
author = 'imacat' author = 'imacat'
release = '0.3.1' release = '0.4.0'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

View File

@ -4,8 +4,8 @@ Examples
.. _example-alone-simple: .. _example-alone-simple:
Simple Applications with Flask-Digest-Auth Alone Simple Applications with Flask-DigestAuth Alone
------------------------------------------------ -----------------------------------------------
In your ``my_app.py``: In your ``my_app.py``:
@ -42,8 +42,8 @@ In your ``my_app.py``:
.. _example-alone-large: .. _example-alone-large:
Larger Applications with ``create_app()`` with Flask-Digest-Auth Alone Larger Applications with ``create_app()`` with Flask-DigestAuth Alone
---------------------------------------------------------------------- ---------------------------------------------------------------------
In your ``my_app/__init__.py``: In your ``my_app/__init__.py``:

View File

@ -1,12 +1,12 @@
.. Flask-Digest-Auth documentation master file, created by .. Flask-DigestAuth documentation master file, created by
sphinx-quickstart on Wed Dec 7 09:40:48 2022. sphinx-quickstart on Wed Dec 7 09:40:48 2022.
You can adapt this file completely to your liking, but it should at least You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive. contain the root `toctree` directive.
Welcome to Flask-Digest-Auth's documentation! Welcome to Flask-DigestAuth's documentation!
============================================= ============================================
*Flask-Digest-Auth* is an `HTTP Digest Authentication`_ implementation *Flask-DigestAuth* is an `HTTP Digest Authentication`_ implementation
for Flask_ applications. It authenticates the user for the protected for Flask_ applications. It authenticates the user for the protected
views. views.

View File

@ -2,7 +2,7 @@ Introduction
============ ============
*Flask-Digest-Auth* is an `HTTP Digest Authentication`_ implementation *Flask-DigestAuth* is an `HTTP Digest Authentication`_ implementation
for Flask_ applications. It authenticates the user for the protected for Flask_ applications. It authenticates the user for the protected
views. views.
@ -24,7 +24,7 @@ own challenge-response log in form, but then you are reinventing the
wheels. If a pretty log in form is not critical to your project, HTTP wheels. If a pretty log in form is not critical to your project, HTTP
Digest Authentication should be a good choice. Digest Authentication should be a good choice.
Flask-Digest-Auth works with Flask-Login_. Log in protection can be Flask-DigestAuth works with Flask-Login_. Log in protection can be
separated with the authentication mechanism. You can create protected separated with the authentication mechanism. You can create protected
Flask modules without knowing the actual authentication mechanisms. Flask modules without knowing the actual authentication mechanisms.
@ -32,18 +32,18 @@ Flask modules without knowing the actual authentication mechanisms.
Installation Installation
------------ ------------
You can install Flask-Digest-Auth with ``pip``: You can install Flask-DigestAuth with ``pip``:
:: ::
pip install Flask-Digest-Auth pip install Flask-DigestAuth
You may also install the latest source from the You may also install the latest source from the
`Flask-Digest-Auth GitHub repository`_. `Flask-DigestAuth GitHub repository`_.
:: ::
pip install git+https://github.com/imacat/flask-digest-auth.git pip install git+https://github.com/imacat/flask-digestauth.git
Setting the Password Setting the Password
@ -66,10 +66,10 @@ hash.
See :func:`flask_digest_auth.algo.make_password_hash`. See :func:`flask_digest_auth.algo.make_password_hash`.
Flask-Digest-Auth Alone Flask-DigestAuth Alone
----------------------- ----------------------
Flask-Digest-Auth can authenticate the users alone. Flask-DigestAuth can authenticate the users alone.
See :ref:`example-alone-simple` and :ref:`example-alone-large`. See :ref:`example-alone-simple` and :ref:`example-alone-large`.
@ -77,12 +77,12 @@ See :ref:`example-alone-simple` and :ref:`example-alone-large`.
Flask-Login Integration Flask-Login Integration
----------------------- -----------------------
Flask-Digest-Auth works with Flask-Login_. You can write a Flask Flask-DigestAuth works with Flask-Login_. You can write a Flask
module that requires log in, without specifying how to log in. The module that requires log in, without specifying how to log in. The
application can use either HTTP Digest Authentication, or the log in application can use either HTTP Digest Authentication, or the log in
forms, as needed. forms, as needed.
To use Flask-Login with Flask-Digest-Auth, To use Flask-Login with Flask-DigestAuth,
``login_manager.init_app(app)`` must be called before ``login_manager.init_app(app)`` must be called before
``auth.init_app(app)``. ``auth.init_app(app)``.
@ -92,7 +92,7 @@ The currently logged-in user can be retrieved at
See :ref:`example-flask-login-simple` and See :ref:`example-flask-login-simple` and
:ref:`example-flask-login-large`. :ref:`example-flask-login-large`.
The views only depend on Flask-Login, but not the Flask-Digest-Auth. The views only depend on Flask-Login, but not the Flask-DigestAuth.
You can change the actual authentication mechanism without changing You can change the actual authentication mechanism without changing
the views. the views.
@ -100,7 +100,7 @@ the views.
Session Integration Session Integration
------------------- -------------------
Flask-Digest-Auth features session integration. The user log in Flask-DigestAuth features session integration. The user log in
is remembered in the session. The authentication information is not is remembered in the session. The authentication information is not
requested again. This is different to the practice of the HTTP Digest requested again. This is different to the practice of the HTTP Digest
Authentication, but is convenient for the log in accounting. Authentication, but is convenient for the log in accounting.
@ -124,7 +124,7 @@ See :meth:`flask_digest_auth.auth.DigestAuth.register_on_login`.
Log Out Log Out
------- -------
Flask-Digest-Auth supports log out. The user will be prompted for the Flask-DigestAuth supports log out. The user will be prompted for the
new username and password. new username and password.
See :meth:`flask_digest_auth.auth.DigestAuth.logout`. See :meth:`flask_digest_auth.auth.DigestAuth.logout`.
@ -133,7 +133,7 @@ See :meth:`flask_digest_auth.auth.DigestAuth.logout`.
Test Client Test Client
----------- -----------
Flask-Digest-Auth comes with a test client that supports HTTP digest Flask-DigestAuth comes with a test client that supports HTTP digest
authentication. authentication.
See :class:`flask_digest_auth.test.Client`. See :class:`flask_digest_auth.test.Client`.
@ -145,4 +145,4 @@ Also see :ref:`example-unittest` and :ref:`example-pytest`.
.. _RFC 2617: https://www.rfc-editor.org/rfc/rfc2617 .. _RFC 2617: https://www.rfc-editor.org/rfc/rfc2617
.. _Flask: https://flask.palletsprojects.com .. _Flask: https://flask.palletsprojects.com
.. _Flask-Login: https://flask-login.readthedocs.io .. _Flask-Login: https://flask-login.readthedocs.io
.. _Flask-Digest-Auth GitHub repository: https://github.com/imacat/flask-digest-auth .. _Flask-DigestAuth GitHub repository: https://github.com/imacat/flask-digestauth

View File

@ -1,7 +1,7 @@
# The Flask HTTP Digest Authentication Project. # The Flask HTTP Digest Authentication Project.
# Author: imacat@mail.imacat.idv.tw (imacat), 2022/11/23 # Author: imacat@mail.imacat.idv.tw (imacat), 2022/11/23
# Copyright (c) 2022 imacat. # Copyright (c) 2022-2023 imacat.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -16,16 +16,16 @@
# limitations under the License. # limitations under the License.
[metadata] [metadata]
name = flask-digest-auth name = Flask-DigestAuth
version = 0.3.1 version = 0.4.0
author = imacat author = imacat
author_email = imacat@mail.imacat.idv.tw author_email = imacat@mail.imacat.idv.tw
description = The Flask HTTP Digest Authentication project. description = The Flask HTTP Digest Authentication project.
long_description = file: README.rst long_description = file: README.rst
long_description_content_type = text/x-rst long_description_content_type = text/x-rst
url = https://github.com/imacat/flask-digest-auth url = https://github.com/imacat/flask-digestauth
project_urls = project_urls =
Bug Tracker = https://github.com/imacat/flask-digest-auth/issues Bug Tracker = https://github.com/imacat/flask-digestauth/issues
classifiers = classifiers =
Programming Language :: Python :: 3 Programming Language :: Python :: 3
License :: OSI Approved :: Apache Software License License :: OSI Approved :: Apache Software License

View File

@ -1,7 +1,7 @@
# The Flask HTTP Digest Authentication Project. # The Flask HTTP Digest Authentication Project.
# Author: imacat@mail.imacat.idv.tw (imacat), 2022/10/22 # Author: imacat@mail.imacat.idv.tw (imacat), 2022/10/22
# Copyright (c) 2022 imacat. # Copyright (c) 2022-2023 imacat.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -27,7 +27,8 @@ import typing as t
from functools import wraps from functools import wraps
from secrets import token_urlsafe, randbits from secrets import token_urlsafe, randbits
from flask import g, request, Response, session, abort, Flask, Request from flask import g, request, Response, session, abort, Flask, Request, \
current_app
from itsdangerous import URLSafeTimedSerializer, BadData from itsdangerous import URLSafeTimedSerializer, BadData
from werkzeug.datastructures import Authorization from werkzeug.datastructures import Authorization
@ -59,8 +60,6 @@ class DigestAuth:
= ["auth", "auth-int"] = ["auth", "auth-int"]
"""A list of supported quality of protection supported, either """A list of supported quality of protection supported, either
``qop``, ``auth-int``, both, or empty. Default is both.""" ``qop``, ``auth-int``, both, or empty. Default is both."""
self.app: t.Optional[Flask] = None
"""The current Flask application."""
self.__get_password_hash: BasePasswordHashGetter \ self.__get_password_hash: BasePasswordHashGetter \
= BasePasswordHashGetter() = BasePasswordHashGetter()
"""The callback to return the password hash.""" """The callback to return the password hash."""
@ -328,7 +327,8 @@ class DigestAuth:
self.__on_login = OnLogInCallback() self.__on_login = OnLogInCallback()
def init_app(self, app: Flask) -> None: def init_app(self, app: Flask) -> None:
"""Initializes the Flask application. """Initializes the Flask application. The DigestAuth instance will
be stored in ``app.extensions["digest_auth"]``.
:Example: :Example:
@ -342,8 +342,7 @@ class DigestAuth:
:param app: The Flask application. :param app: The Flask application.
:return: None. :return: None.
""" """
app.digest_auth = self app.extensions["digest_auth"] = self
self.app = app
if hasattr(app, "login_manager"): if hasattr(app, "login_manager"):
from flask_login import LoginManager, login_user from flask_login import LoginManager, login_user
@ -356,8 +355,8 @@ class DigestAuth:
:return: None. :return: None.
""" """
state: AuthState = request.digest_auth_state \ state: AuthState = getattr(request, "_digest_auth_state") \
if hasattr(request, "digest_auth_state") \ if hasattr(request, "_digest_auth_state") \
else AuthState() else AuthState()
response: Response = Response() response: Response = Response()
response.status = 401 response.status = 401
@ -373,7 +372,7 @@ class DigestAuth:
:return: The authenticated user, or None if the :return: The authenticated user, or None if the
authentication fails authentication fails
""" """
request.digest_auth_state = AuthState() request._digest_auth_state = AuthState()
authorization: Authorization = req.authorization authorization: Authorization = req.authorization
try: try:
if authorization is None: if authorization is None:
@ -381,7 +380,7 @@ class DigestAuth:
if authorization.type != "digest": if authorization.type != "digest":
raise UnauthorizedException( raise UnauthorizedException(
"Not an HTTP digest authorization") "Not an HTTP digest authorization")
self.__authenticate(request.digest_auth_state) self.__authenticate(request._digest_auth_state)
user = login_manager.user_callback( user = login_manager.user_callback(
authorization.username) authorization.username)
login_user(user) login_user(user)
@ -412,7 +411,7 @@ class DigestAuth:
if "user" in session: if "user" in session:
del session["user"] del session["user"]
try: try:
if hasattr(self.app, "login_manager"): if hasattr(current_app, "login_manager"):
from flask_login import logout_user from flask_login import logout_user
logout_user() logout_user()
except ModuleNotFoundError: except ModuleNotFoundError: