Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-Flask-HTTPAuth for
openSUSE:Factory checked in at 2021-07-23 23:41:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Flask-HTTPAuth (Old)
and /work/SRC/openSUSE:Factory/.python-Flask-HTTPAuth.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Flask-HTTPAuth"
Fri Jul 23 23:41:12 2021 rev:6 rq:907906 version:4.4.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-Flask-HTTPAuth/python-Flask-HTTPAuth.changes
2021-06-01 10:41:43.881249191 +0200
+++
/work/SRC/openSUSE:Factory/.python-Flask-HTTPAuth.new.1899/python-Flask-HTTPAuth.changes
2021-07-23 23:41:31.357807503 +0200
@@ -1,0 +2,22 @@
+Sun Jul 4 00:41:02 UTC 2021 - Arun Persaud <[email protected]>
+
+- specfile:
+ * update copyright year
+ * require importlib-metadata
+ * skip python 2
+
+- update to version 4.4.0:
+ * Replace safe_str_cmp with hmac.compare_digest to avoid a
+ deprecation warning from Werkzeug #126 (commit) (thanks Federico
+ Martinez!)
+ * Drop Python 2 support (commit)
+
+- changes from version 4.3.0 :
+ * Support token auth with custom header in MultiAuth class #125
+ (commit)
+ * Catch UnicodeDecodeError when passing malformed data in
+ authorization header #122 (commit) (thanks Bastian Raschke!)
+ * Fixes typo #116 (commit) (thanks Renato Oliveira!)
+ * Move builds to GitHub actions (commit)
+
+-------------------------------------------------------------------
Old:
----
Flask-HTTPAuth-4.2.0.tar.gz
New:
----
Flask-HTTPAuth-4.4.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-Flask-HTTPAuth.spec ++++++
--- /var/tmp/diff_new_pack.g4Z68V/_old 2021-07-23 23:41:31.829806900 +0200
+++ /var/tmp/diff_new_pack.g4Z68V/_new 2021-07-23 23:41:31.833806895 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-Flask-HTTPAuth
#
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
# Copyright (c) 2017 Dr. Axel Braun
#
# All modifications and additions to the file contributed by third parties
@@ -18,8 +18,9 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%define skip_python2 1
Name: python-Flask-HTTPAuth
-Version: 4.2.0
+Version: 4.4.0
Release: 0
Summary: Basic and Digest HTTP authentication for Flask routes
License: MIT
@@ -27,6 +28,7 @@
URL: https://github.com/miguelgrinberg/flask-httpauth/
Source:
https://files.pythonhosted.org/packages/source/F/Flask-HTTPAuth/Flask-HTTPAuth-%{version}.tar.gz
BuildRequires: %{python_module Flask}
+BuildRequires: %{python_module importlib-metadata}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
++++++ Flask-HTTPAuth-4.2.0.tar.gz -> Flask-HTTPAuth-4.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Flask-HTTPAuth-4.2.0/Flask_HTTPAuth.egg-info/PKG-INFO
new/Flask-HTTPAuth-4.4.0/Flask_HTTPAuth.egg-info/PKG-INFO
--- old/Flask-HTTPAuth-4.2.0/Flask_HTTPAuth.egg-info/PKG-INFO 2020-11-16
12:52:39.000000000 +0100
+++ new/Flask-HTTPAuth-4.4.0/Flask_HTTPAuth.egg-info/PKG-INFO 2021-05-13
20:32:42.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Flask-HTTPAuth
-Version: 4.2.0
+Version: 4.4.0
Summary: Basic and Digest HTTP authentication for Flask routes
Home-page: http://github.com/miguelgrinberg/flask-httpauth/
Author: Miguel Grinberg
@@ -18,7 +18,6 @@
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Flask-HTTPAuth-4.2.0/Flask_HTTPAuth.egg-info/SOURCES.txt
new/Flask-HTTPAuth-4.4.0/Flask_HTTPAuth.egg-info/SOURCES.txt
--- old/Flask-HTTPAuth-4.2.0/Flask_HTTPAuth.egg-info/SOURCES.txt
2020-11-16 12:52:40.000000000 +0100
+++ new/Flask-HTTPAuth-4.4.0/Flask_HTTPAuth.egg-info/SOURCES.txt
2021-05-13 20:32:42.000000000 +0200
@@ -62,4 +62,5 @@
tests/test_error_responses.py
tests/test_multi.py
tests/test_roles.py
-tests/test_token.py
\ No newline at end of file
+tests/test_token.py
+tests/test_x.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-HTTPAuth-4.2.0/PKG-INFO
new/Flask-HTTPAuth-4.4.0/PKG-INFO
--- old/Flask-HTTPAuth-4.2.0/PKG-INFO 2020-11-16 12:52:40.275509400 +0100
+++ new/Flask-HTTPAuth-4.4.0/PKG-INFO 2021-05-13 20:32:43.185671300 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Flask-HTTPAuth
-Version: 4.2.0
+Version: 4.4.0
Summary: Basic and Digest HTTP authentication for Flask routes
Home-page: http://github.com/miguelgrinberg/flask-httpauth/
Author: Miguel Grinberg
@@ -18,7 +18,6 @@
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-HTTPAuth-4.2.0/README.md
new/Flask-HTTPAuth-4.4.0/README.md
--- old/Flask-HTTPAuth-4.2.0/README.md 2020-04-23 01:16:10.000000000 +0200
+++ new/Flask-HTTPAuth-4.4.0/README.md 2021-02-21 14:13:02.000000000 +0100
@@ -1,7 +1,7 @@
Flask-HTTPAuth
==============
-[](https://travis-ci.org/miguelgrinberg/Flask-HTTPAuth)
+[](https://github.com/miguelgrinberg/Flask-HTTPAuth/actions)
[](https://codecov.io/gh/miguelgrinberg/Flask-HTTPAuth)
Simple extension that provides Basic and Digest HTTP authentication for Flask
routes.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-HTTPAuth-4.2.0/docs/index.rst
new/Flask-HTTPAuth-4.4.0/docs/index.rst
--- old/Flask-HTTPAuth-4.2.0/docs/index.rst 2020-04-26 19:51:16.000000000
+0200
+++ new/Flask-HTTPAuth-4.4.0/docs/index.rst 2021-02-01 01:04:55.000000000
+0100
@@ -39,7 +39,7 @@
if __name__ == '__main__':
app.run()
-The function decorated with the ``verify_password`` decorator receives the
username and password sent by the client. If the credentials belong to a user,
then the function should return the user object. If the credentials are invalid
the functon can return ``None`` or ``False``. The user object can then be
queries from the ``current_user()`` method of the authentication instance.
+The function decorated with the ``verify_password`` decorator receives the
username and password sent by the client. If the credentials belong to a user,
then the function should return the user object. If the credentials are invalid
the functon can return ``None`` or ``False``. The user object can then be
queried from the ``current_user()`` method of the authentication instance.
Digest authentication example
-----------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-HTTPAuth-4.2.0/flask_httpauth.py
new/Flask-HTTPAuth-4.4.0/flask_httpauth.py
--- old/Flask-HTTPAuth-4.2.0/flask_httpauth.py 2020-11-16 12:52:31.000000000
+0100
+++ new/Flask-HTTPAuth-4.4.0/flask_httpauth.py 2021-05-13 20:32:40.000000000
+0200
@@ -7,16 +7,16 @@
:copyright: (C) 2014 by Miguel Grinberg.
:license: MIT, see LICENSE for more details.
"""
-
+import hmac
from base64 import b64decode
from functools import wraps
from hashlib import md5
from random import Random, SystemRandom
from flask import request, make_response, session, g, Response
from werkzeug.datastructures import Authorization
-from werkzeug.security import safe_str_cmp
-__version__ = '4.2.0'
+
+__version__ = '4.4.0'
class HTTPAuth(object):
@@ -37,6 +37,18 @@
self.get_password(default_get_password)
self.error_handler(default_auth_error)
+ def is_compatible_auth(self, headers):
+ if self.header is None or self.header == 'Authorization':
+ try:
+ scheme, _ = request.headers.get('Authorization', '').split(
+ None, 1)
+ except ValueError:
+ # malformed Authorization header
+ return False
+ return scheme == self.scheme
+ else:
+ return self.header in headers
+
def get_password(self, f):
self.get_password_callback = f
return f
@@ -169,9 +181,10 @@
return login_required_internal
def username(self):
- if not request.authorization:
+ auth = self.get_auth()
+ if not auth:
return ""
- return request.authorization.username
+ return auth.username
def current_user(self):
if hasattr(g, 'flask_httpauth_user'):
@@ -205,9 +218,14 @@
username, password = b64decode(credentials).split(b':', 1)
except (ValueError, TypeError):
return None
+ try:
+ username = username.decode('utf-8')
+ password = password.decode('utf-8')
+ except UnicodeDecodeError:
+ username = None
+ password = None
return Authorization(
- scheme, {'username': username.decode('utf-8'),
- 'password': password.decode('utf-8')})
+ scheme, {'username': username, 'password': password})
def authenticate(self, auth, stored_password):
if auth:
@@ -228,7 +246,7 @@
client_password)
return auth.username if client_password is not None and \
stored_password is not None and \
- safe_str_cmp(client_password, stored_password) else None
+ hmac.compare_digest(client_password, stored_password) else None
class HTTPDigestAuth(HTTPAuth):
@@ -257,7 +275,7 @@
session_nonce = session.get("auth_nonce")
if nonce is None or session_nonce is None:
return False
- return safe_str_cmp(nonce, session_nonce)
+ return hmac.compare_digest(nonce, session_nonce)
def default_generate_opaque():
session["auth_opaque"] = _generate_random()
@@ -267,7 +285,7 @@
session_opaque = session.get("auth_opaque")
if opaque is None or session_opaque is None: # pragma: no cover
return False
- return safe_str_cmp(opaque, session_opaque)
+ return hmac.compare_digest(opaque, session_opaque)
self.generate_nonce(default_generate_nonce)
self.generate_opaque(default_generate_opaque)
@@ -326,7 +344,7 @@
ha2 = md5(a2.encode('utf-8')).hexdigest()
a3 = ha1 + ":" + auth.nonce + ":" + ha2
response = md5(a3.encode('utf-8')).hexdigest()
- return safe_str_cmp(response, auth.response)
+ return hmac.compare_digest(response, auth.response)
class HTTPTokenAuth(HTTPAuth):
@@ -362,21 +380,12 @@
def login_required_internal(f):
@wraps(f)
def decorated(*args, **kwargs):
- selected_auth = None
- if 'Authorization' in request.headers:
- try:
- scheme, creds = request.headers[
- 'Authorization'].split(None, 1)
- except ValueError:
- # malformed Authorization header
- pass
- else:
- for auth in self.additional_auth:
- if auth.scheme == scheme:
- selected_auth = auth
- break
- if selected_auth is None:
- selected_auth = self.main_auth
+ selected_auth = self.main_auth
+ if not self.main_auth.is_compatible_auth(request.headers):
+ for auth in self.additional_auth:
+ if auth.is_compatible_auth(request.headers):
+ selected_auth = auth
+ break
return selected_auth.login_required(role=role,
optional=optional
)(f)(*args, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-HTTPAuth-4.2.0/setup.py
new/Flask-HTTPAuth-4.4.0/setup.py
--- old/Flask-HTTPAuth-4.2.0/setup.py 2020-04-19 18:49:09.000000000 +0200
+++ new/Flask-HTTPAuth-4.4.0/setup.py 2021-05-13 20:26:17.000000000 +0200
@@ -34,7 +34,6 @@
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries :: Python Modules'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Flask-HTTPAuth-4.2.0/tests/test_basic_verify_password.py
new/Flask-HTTPAuth-4.4.0/tests/test_basic_verify_password.py
--- old/Flask-HTTPAuth-4.2.0/tests/test_basic_verify_password.py
2020-06-04 11:42:04.000000000 +0200
+++ new/Flask-HTTPAuth-4.4.0/tests/test_basic_verify_password.py
2021-02-21 14:12:46.000000000 +0100
@@ -75,6 +75,13 @@
self.assertEqual(response.status_code, 403)
self.assertTrue('WWW-Authenticate' in response.headers)
+ def test_verify_auth_login_malformed_password(self):
+ creds = 'eyJhbGciOieyJp=='
+ response = self.client.get('/basic-verify',
+ headers={'Authorization': 'Basic ' + creds})
+ self.assertEqual(response.status_code, 403)
+ self.assertTrue('WWW-Authenticate' in response.headers)
+
class HTTPAuthTestCaseOldStyle(HTTPAuthTestCase):
use_old_style_callback = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-HTTPAuth-4.2.0/tests/test_multi.py
new/Flask-HTTPAuth-4.4.0/tests/test_multi.py
--- old/Flask-HTTPAuth-4.2.0/tests/test_multi.py 2020-04-23
01:11:02.000000000 +0200
+++ new/Flask-HTTPAuth-4.4.0/tests/test_multi.py 2021-05-01
16:19:05.000000000 +0200
@@ -11,7 +11,8 @@
basic_auth = HTTPBasicAuth()
token_auth = HTTPTokenAuth('MyToken')
- multi_auth = MultiAuth(basic_auth, token_auth)
+ custom_token_auth = HTTPTokenAuth(header='X-Token')
+ multi_auth = MultiAuth(basic_auth, token_auth, custom_token_auth)
@basic_auth.verify_password
def verify_password(username, password):
@@ -37,6 +38,16 @@
def error_handler():
return 'error', 401, {'WWW-Authenticate': 'MyToken realm="Foo"'}
+ @custom_token_auth.verify_token
+ def verify_custom_token(token):
+ return token == 'this-is-the-custom-token!'
+
+ @custom_token_auth.get_user_roles
+ def get_custom_token_role(auth):
+ if auth['token'] == 'this-is-the-custom-token!':
+ return 'foo'
+ return
+
@app.route('/')
def index():
return 'index'
@@ -91,6 +102,19 @@
self.assertEqual(response.headers['WWW-Authenticate'],
'MyToken realm="Foo"')
+ def test_multi_auth_login_valid_custom_token(self):
+ response = self.client.get(
+ '/protected', headers={'X-Token': 'this-is-the-custom-token!'})
+ self.assertEqual(response.data.decode('utf-8'), 'access granted:None')
+
+ def test_multi_auth_login_invalid_custom_token(self):
+ response = self.client.get(
+ '/protected', headers={'X-Token': 'this-is-not-the-token!'})
+ self.assertEqual(response.status_code, 401)
+ self.assertTrue('WWW-Authenticate' in response.headers)
+ self.assertEqual(response.headers['WWW-Authenticate'],
+ 'Bearer realm="Authentication Required"')
+
def test_multi_auth_login_invalid_scheme(self):
response = self.client.get(
'/protected', headers={'Authorization': 'Foo this-is-the-token!'})
@@ -116,3 +140,9 @@
'/protected-with-role', headers={'Authorization':
'MyToken this-is-the-token!'})
self.assertEqual(response.data.decode('utf-8'), 'role access granted')
+
+ def test_multi_auth_login_valid_custom_token_role(self):
+ response = self.client.get(
+ '/protected-with-role', headers={'X-Token':
+ 'this-is-the-custom-token!'})
+ self.assertEqual(response.data.decode('utf-8'), 'role access granted')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Flask-HTTPAuth-4.2.0/tests/test_x.py
new/Flask-HTTPAuth-4.4.0/tests/test_x.py
--- old/Flask-HTTPAuth-4.2.0/tests/test_x.py 1970-01-01 01:00:00.000000000
+0100
+++ new/Flask-HTTPAuth-4.4.0/tests/test_x.py 2021-01-30 00:00:53.000000000
+0100
@@ -0,0 +1,26 @@
+import unittest
+from flask import Flask
+from flask_httpauth import HTTPBasicAuth
+
+
+class HTTPAuthTestCase(unittest.TestCase):
+
+ def setUp(self):
+ app = Flask(__name__)
+ app.config['SECRET_KEY'] = 'my secret'
+
+ basic_verify_auth = HTTPBasicAuth()
+
+ @app.route('/')
+ @basic_verify_auth.login_required
+ def index():
+ return 'index'
+
+ self.app = app
+ self.basic_verify_auth = basic_verify_auth
+ self.client = app.test_client()
+
+ def test_verify_auth_login_malformed_password(self):
+ creds = 'eyJhbGciOieyJp=='
+ response = self.client.get('/', headers={'Authorization': 'Basic ' +
creds})
+ self.assertEqual(response.status_code, 401)