Skip to content

Commit

Permalink
Merge pull request #858 from asfadmin/rew/auth-header-bad-request
Browse files Browse the repository at this point in the history
Add error handling for malformed auth headers
  • Loading branch information
reweeden authored Jan 13, 2025
2 parents 3e03634 + 936f709 commit fa681ac
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
16 changes: 16 additions & 0 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,22 @@ def test_request_authorizer_no_headers(current_request, mock_get_urs_url):
assert authorizer.get_success_response_headers() == {}


def test_request_authorizer_malformed_header(current_request):
current_request.headers = {
"Authorization": "token",
"x-origin-request-id": "origin_request_id",
}
authorizer = app.RequestAuthorizer()

assert authorizer.get_profile() is None
response = authorizer.get_error_response()
assert response.status_code == 400
assert response.body == {
"status_code": 400,
"error_description": "Malformed Authorization header",
}


@mock.patch(f"{MODULE}.get_profile_with_jwt_bearer", autospec=True)
def test_request_authorizer_bearer_header(
mock_get_profile_with_jwt_bearer,
Expand Down
35 changes: 33 additions & 2 deletions thin_egress_app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,14 @@ def get_profile(self) -> Optional[UserProfile]:
self._response = do_auth_and_return(app.current_request.context)
return None

method, token, *_ = authorization.split()
method = method.lower()
parsed_auth = self._parse_auth_header(authorization)
if parsed_auth is None:
return None

method, args = parsed_auth

if method == "bearer":
token, *_ = args
# we will deal with "bearer" auth here. "Basic" auth will be handled by do_auth_and_return()
log.debug("we got an Authorization header. %s", authorization)
user_profile, self._response = self._get_profile_and_response_from_bearer(token)
Expand All @@ -203,6 +207,33 @@ def get_profile(self) -> Optional[UserProfile]:
self._response = do_auth_and_return(app.current_request.context)
return None

def _parse_auth_header(self, authorization: str):
try:
method, token, *args = authorization.split()
method = method.lower()
return method, (token, *args)
except Exception:
status_code = 400
if check_for_browser(app.current_request.headers):
template_vars = {
"title": "Bad Request",
"status_code": status_code,
"contentstring": "Malformed Authorization header",
"requestid": get_request_id(),
}

self._response = make_html_response(template_vars, {}, status_code, "error.html")
else:
self._response = Response(
body={
"status_code": status_code,
"error_description": "Malformed Authorization header",
},
status_code=status_code,
headers={},
)
return None

@with_trace()
@cachetools.cached(
cachetools.TTLCache(maxsize=32, ttl=1 * 60),
Expand Down

0 comments on commit fa681ac

Please sign in to comment.