From 282061cb41d680b98ef99e67afc5d757616251dc Mon Sep 17 00:00:00 2001 From: Nicolas Simonds Date: Mon, 1 May 2023 11:05:41 -0700 Subject: [PATCH] Authorization.from_header handles base64 padding in token co-authored-by: David Lord --- CHANGES.rst | 3 +++ src/werkzeug/datastructures/auth.py | 11 +++++------ tests/test_http.py | 13 +++++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 402d3bbae..0a37fd896 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Version 2.3.4 Unreleased +- ``Authorization.from_header`` detects tokens that end with base64 padding (``=``). + :issue:`2685` + Version 2.3.3 ------------- diff --git a/src/werkzeug/datastructures/auth.py b/src/werkzeug/datastructures/auth.py index afc719c75..7d36a7ff3 100644 --- a/src/werkzeug/datastructures/auth.py +++ b/src/werkzeug/datastructures/auth.py @@ -112,13 +112,12 @@ def from_header(cls, value: str | None) -> te.Self | None: return cls(scheme, {"username": username, "password": password}) - parameters = parse_dict_header(rest) + if "=" in rest.rstrip("="): + # = that is not trailing, this is parameters. + return cls(scheme, parse_dict_header(rest), None) - if len(parameters) == 1 and parameters[next(iter(parameters))] is None: - # There is one parameter with no value, was actually a token. - return cls(scheme, None, rest) - - return cls(scheme, parameters, None) + # No = or only trailing =, this is a token. + return cls(scheme, None, rest) def to_header(self) -> str: """Produce an ``Authorization`` header value representing this data. diff --git a/tests/test_http.py b/tests/test_http.py index 5ceb7ef5e..8f21c12a3 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -203,6 +203,19 @@ def test_authorization_header(self): assert Authorization.from_header(None) is None assert Authorization.from_header("foo").type == "foo" + def test_authorization_token_padding(self): + # padded with = + token = base64.b64encode(b"This has base64 padding").decode() + a = Authorization.from_header(f"Token {token}") + assert a.type == "token" + assert a.token == token + + # padded with == + token = base64.b64encode(b"This has base64 padding..").decode() + a = Authorization.from_header(f"Token {token}") + assert a.type == "token" + assert a.token == token + def test_bad_authorization_header_encoding(self): """If the base64 encoded bytes can't be decoded as UTF-8""" content = base64.b64encode(b"\xffser:pass").decode()