Skip to content

Commit

Permalink
auth: allow rs384 in jwt (PROJQUAY-4148) (#1449)
Browse files Browse the repository at this point in the history
Allow the use of RS384 for jwt and oidc.
  • Loading branch information
kleesc committed Jul 18, 2022
1 parent a527998 commit 6ed0bcd
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
2 changes: 1 addition & 1 deletion oauth/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

OIDC_WELLKNOWN = ".well-known/openid-configuration"
PUBLIC_KEY_CACHE_TTL = 3600 # 1 hour
ALLOWED_ALGORITHMS = ["RS256"]
ALLOWED_ALGORITHMS = ["RS256", "RS384"]
JWT_CLOCK_SKEW_SECONDS = 30


Expand Down
2 changes: 1 addition & 1 deletion util/security/jwtutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

# ALGORITHM_WHITELIST defines a whitelist of allowed algorithms to be used in JWTs. DO NOT ADD
# `none` here!
ALGORITHM_WHITELIST = ["rs256", "hs256"]
ALGORITHM_WHITELIST = ["rs256", "hs256", "rs384"]


class _StrictJWT(PyJWT):
Expand Down
36 changes: 24 additions & 12 deletions util/security/test/test_jwtutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def _token_data(audience, subject, iss, iat=None, exp=None, nbf=None):
}


@pytest.mark.parametrize("algorithm", [pytest.param("RS256"), pytest.param("RS384")])
@pytest.mark.parametrize(
"aud, iss, nbf, iat, exp, expected_exception",
[
Expand Down Expand Up @@ -133,17 +134,25 @@ def _token_data(audience, subject, iss, iat=None, exp=None, nbf=None):
],
)
def test_decode_jwt_validation(
aud, iss, nbf, iat, exp, expected_exception, private_key_pem, public_key
aud,
iss,
nbf,
iat,
exp,
expected_exception,
private_key_pem,
public_key,
algorithm,
):
token = jwt.encode(_token_data(aud, "subject", iss, iat, exp, nbf), private_key_pem, "RS256")
token = jwt.encode(_token_data(aud, "subject", iss, iat, exp, nbf), private_key_pem, algorithm)

if expected_exception is not None:
with pytest.raises(InvalidTokenError) as ite:
max_exp = exp_max_s_option(3600)
decode(
token,
public_key,
algorithms=["RS256"],
algorithms=[algorithm],
audience="someaudience",
issuer="someissuer",
options=max_exp,
Expand All @@ -155,17 +164,18 @@ def test_decode_jwt_validation(
decode(
token,
public_key,
algorithms=["RS256"],
algorithms=[algorithm],
audience="someaudience",
issuer="someissuer",
options=max_exp,
leeway=60,
)


def test_decode_jwt_invalid_key(private_key_pem):
@pytest.mark.parametrize("algorithm", [pytest.param("RS256"), pytest.param("RS384")])
def test_decode_jwt_invalid_key(private_key_pem, algorithm):
# Encode with the test private key.
token = jwt.encode(_token_data("aud", "subject", "someissuer"), private_key_pem, "RS256")
token = jwt.encode(_token_data("aud", "subject", "someissuer"), private_key_pem, algorithm)

# Try to decode with a different public key.
another_public_key = (
Expand All @@ -184,7 +194,7 @@ def test_decode_jwt_invalid_key(private_key_pem):
decode(
token,
another_public_key,
algorithms=["RS256"],
algorithms=[algorithm],
audience="aud",
issuer="someissuer",
options=max_exp,
Expand All @@ -193,9 +203,10 @@ def test_decode_jwt_invalid_key(private_key_pem):
assert ite.match("Signature verification failed")


def test_decode_jwt_invalid_algorithm(private_key_pem, public_key):
@pytest.mark.parametrize("algorithm", [pytest.param("RS256"), pytest.param("RS384")])
def test_decode_jwt_invalid_algorithm(private_key_pem, public_key, algorithm):
# Encode with the test private key.
token = jwt.encode(_token_data("aud", "subject", "someissuer"), private_key_pem, "RS256")
token = jwt.encode(_token_data("aud", "subject", "someissuer"), private_key_pem, algorithm)

# Attempt to decode but only with a different algorithm than that used.
with pytest.raises(InvalidAlgorithmError) as ite:
Expand All @@ -212,7 +223,8 @@ def test_decode_jwt_invalid_algorithm(private_key_pem, public_key):
assert ite.match("are not whitelisted")


def test_jwk_dict_to_public_key(private_key, private_key_pem):
@pytest.mark.parametrize("algorithm", [pytest.param("RS256"), pytest.param("RS384")])
def test_jwk_dict_to_public_key(private_key, private_key_pem, algorithm):
public_key = private_key.public_key()
key_dict = jwk.dumps(
public_key.public_bytes(
Expand All @@ -223,14 +235,14 @@ def test_jwk_dict_to_public_key(private_key, private_key_pem):
converted = jwk_dict_to_public_key(key_dict)

# Encode with the test private key.
token = jwt.encode(_token_data("aud", "subject", "someissuer"), private_key_pem, "RS256")
token = jwt.encode(_token_data("aud", "subject", "someissuer"), private_key_pem, algorithm)

# Decode with the converted key.
max_exp = exp_max_s_option(3600)
decode(
token,
converted,
algorithms=["RS256"],
algorithms=[algorithm],
audience="aud",
issuer="someissuer",
options=max_exp,
Expand Down

0 comments on commit 6ed0bcd

Please sign in to comment.