Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR-3242 Improve handling of JWT bearer tokens #853

Draft
wants to merge 1 commit into
base: devel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 29 additions & 26 deletions requirements/requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,40 @@
#
# pip-compile requirements/requirements-dev.in
#
boto3==1.35.23
boto3==1.35.87
# via
# -r requirements/requirements-dev.in
# moto
botocore==1.35.23
botocore==1.35.87
# via
# -c requirements/requirements.txt
# boto3
# moto
# s3transfer
build==1.2.2
build==1.2.2.post1
# via pip-tools
certifi==2024.8.30
certifi==2024.12.14
# via requests
cffi==1.17.1
# via
# -c requirements/requirements.txt
# cryptography
charset-normalizer==3.3.2
charset-normalizer==3.4.1
# via requests
click==8.1.7
click==8.1.8
# via
# -c requirements/requirements.txt
# pip-tools
coverage[toml]==7.6.1
coverage[toml]==7.6.10
# via pytest-cov
cryptography==43.0.1
cryptography==44.0.0
# via
# -c requirements/requirements.txt
# moto
deprecated==1.2.14
# via opentelemetry-api
deprecated==1.2.15
# via
# opentelemetry-api
# opentelemetry-semantic-conventions
docker==7.1.0
# via moto
exceptiongroup==1.2.2
Expand All @@ -46,7 +48,7 @@ importlib-metadata==7.1.0
# via opentelemetry-api
iniconfig==2.0.0
# via pytest
jinja2==3.1.4
jinja2==3.1.5
# via
# -c requirements/requirements.txt
# moto
Expand All @@ -55,22 +57,23 @@ jmespath==1.0.1
# -c requirements/requirements.txt
# boto3
# botocore
markupsafe==2.1.5
markupsafe==3.0.2
# via
# -c requirements/requirements.txt
# jinja2
# werkzeug
moto[awslambda]==5.0.14
moto[awslambda]==5.0.24
# via -r requirements/requirements-dev.in
opentelemetry-api==1.25.0
# via
# -c requirements/constraints.txt
# opentelemetry-instrumentation
opentelemetry-instrumentation==0.48b0
# via -r requirements/requirements-dev.in
packaging==24.1
packaging==24.2
# via
# build
# opentelemetry-instrumentation
# pytest
pip-tools==7.4.1
# via -r requirements/requirements-dev.in
Expand All @@ -80,15 +83,15 @@ pycparser==2.22
# via
# -c requirements/requirements.txt
# cffi
pyproject-hooks==1.1.0
pyproject-hooks==1.2.0
# via
# build
# pip-tools
pytest==8.3.3
pytest==8.3.4
# via
# -r requirements/requirements-dev.in
# pytest-cov
pytest-cov==5.0.0
pytest-cov==6.0.0
# via -r requirements/requirements-dev.in
python-dateutil==2.9.0.post0
# via
Expand All @@ -107,38 +110,38 @@ requests==2.32.3
# responses
responses==0.25.3
# via moto
s3transfer==0.10.2
s3transfer==0.10.4
# via boto3
six==1.16.0
six==1.17.0
# via
# -c requirements/requirements.txt
# python-dateutil
tomli==2.0.1
tomli==2.2.1
# via
# build
# coverage
# pip-tools
# pytest
urllib3==2.2.3
urllib3==2.3.0
# via
# -c requirements/requirements.txt
# botocore
# docker
# requests
# responses
werkzeug==3.0.4
werkzeug==3.1.3
# via moto
wheel==0.44.0
wheel==0.45.1
# via
# -c requirements/requirements.txt
# pip-tools
wrapt==1.16.0
wrapt==1.17.0
# via
# deprecated
# opentelemetry-instrumentation
xmltodict==0.13.0
xmltodict==0.14.2
# via moto
zipp==3.20.2
zipp==3.21.0
# via importlib-metadata

# The following packages are considered to be unsafe in a requirements file:
Expand Down
3 changes: 2 additions & 1 deletion requirements/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
cachetools
cfnresponse
chalice
git+https://github.com/asfadmin/rain-api-core.git@f5186c00c8e9d576f710eac62e6ca1e51516d6d7
git+https://github.com/asfadmin/rain-api-core.git@rew/pr-3242-reduce-edl-calls
netaddr
pyjwt
36 changes: 21 additions & 15 deletions requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
blessed==1.20.0
# via inquirer
botocore==1.35.23
botocore==1.35.87
# via chalice
cachetools==5.5.0
# via
Expand All @@ -16,55 +16,61 @@ cffi==1.17.1
# via cryptography
cfnresponse==1.1.5
# via -r requirements/requirements.in
chalice==1.31.2
chalice==1.31.3
# via -r requirements/requirements.in
click==8.1.7
click==8.1.8
# via chalice
cryptography==43.0.1
cryptography==44.0.0
# via pyjwt
inquirer==2.10.1
editor==1.6.6
# via inquirer
inquirer==3.4.0
# via chalice
jinja2==3.1.4
jinja2==3.1.5
# via rain-api-core
jmespath==1.0.1
# via
# botocore
# chalice
markupsafe==2.1.5
markupsafe==3.0.2
# via jinja2
netaddr==1.3.0
# via
# -r requirements/requirements.in
# rain-api-core
pycparser==2.22
# via cffi
pyjwt[crypto]==2.9.0
pyjwt[crypto]==2.10.1
# via rain-api-core
python-dateutil==2.9.0.post0
# via botocore
python-editor==1.0.4
# via inquirer
pyyaml==6.0.2
# via
# chalice
# rain-api-core
rain-api-core @ git+https://github.com/asfadmin/rain-api-core.git@f5186c00c8e9d576f710eac62e6ca1e51516d6d7
rain-api-core @ git+https://github.com/asfadmin/rain-api-core.git@rew/pr-3242-reduce-edl-calls
# via -r requirements/requirements.in
readchar==4.2.0
readchar==4.2.1
# via inquirer
six==1.16.0
runs==1.2.2
# via editor
six==1.17.0
# via
# blessed
# chalice
# python-dateutil
urllib3==2.2.3
urllib3==2.3.0
# via
# botocore
# cfnresponse
wcwidth==0.2.13
# via blessed
wheel==0.44.0
wheel==0.45.1
# via chalice
xmod==1.8.1
# via
# editor
# runs

# The following packages are considered to be unsafe in a requirements file:
# pip
Expand Down
41 changes: 39 additions & 2 deletions thin_egress_app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import boto3
import cachetools
import chalice
import jwt
from botocore.config import Config as bc_Config
from botocore.exceptions import ClientError
from cachetools.func import ttl_cache
Expand Down Expand Up @@ -48,6 +49,7 @@
from rain_api_core.urs_util import (
do_login,
get_new_token_and_profile,
get_profile,
get_urs_creds,
get_urs_url,
user_in_group,
Expand Down Expand Up @@ -188,6 +190,9 @@
self._response = do_auth_and_return(app.current_request.context)
return None

# TODO(reweeden): Causes internal server error if auth header set
# withouth the 'method portion' such as
# Authorization: <token>
method, token, *_ = authorization.split()
method = method.lower()

Expand All @@ -214,12 +219,18 @@
@with_trace()
def _handle_auth_bearer_header(self, token) -> Optional[UserProfile]:
"""
Will handle the output from get_user_from_token in context of a chalice function. If user_id is determined,
returns it. If user_id is not determined returns data to be returned
Will handle the output from get_user_from_token in context of a chalice
function. If user_id is determined, returns it. If user_id is not
determined returns data to be returned.

:param token:
:return: action, data
"""
profile = get_profile_with_jwt_bearer(token)
if profile is not None:
log.debug("Shortcut profile fetching by using the users bearer token directly")
return profile

Check warning on line 232 in thin_egress_app/app.py

View check run for this annotation

Codecov / codecov/patch

thin_egress_app/app.py#L231-L232

Added lines #L231 - L232 were not covered by tests

try:
user_id = get_user_from_token(token)
except EulaException as e:
Expand Down Expand Up @@ -297,6 +308,32 @@
return "user-agent" in hdrs and hdrs["user-agent"].lower().startswith("mozilla")


@with_trace()
def get_profile_with_jwt_bearer(token):
try:
# TODO(reweeden): We could verify with the EDL pub key here to
# potentially save an extra call to EDL on expired or invalid tokens.

# We don't need to verify the signature as EDL will do this for us
# anyway in the call to `get_profile`.
claims = jwt.decode(token, options={"verify_signature": False})
except jwt.DecodeError as e:
log.error("Unable to verify jwt bearer token: %s", e)
return None

user_id = claims.get("uid")

Check warning on line 324 in thin_egress_app/app.py

View check run for this annotation

Codecov / codecov/patch

thin_egress_app/app.py#L324

Added line #L324 was not covered by tests

if user_id is None:
return None

Check warning on line 327 in thin_egress_app/app.py

View check run for this annotation

Codecov / codecov/patch

thin_egress_app/app.py#L327

Added line #L327 was not covered by tests

log_context(user_id=user_id)
aux_headers = get_aux_request_headers()
params = {

Check warning on line 331 in thin_egress_app/app.py

View check run for this annotation

Codecov / codecov/patch

thin_egress_app/app.py#L329-L331

Added lines #L329 - L331 were not covered by tests
"client_id": get_urs_creds()["UrsId"]
}
return get_profile(user_id, "fake", token, aux_headers, params)

Check warning on line 334 in thin_egress_app/app.py

View check run for this annotation

Codecov / codecov/patch

thin_egress_app/app.py#L334

Added line #L334 was not covered by tests


@with_trace()
def get_user_from_token(token):
"""
Expand Down
Loading