diff --git a/src/planet_auth_utils/__init__.py b/src/planet_auth_utils/__init__.py index f42441f..e45b5da 100644 --- a/src/planet_auth_utils/__init__.py +++ b/src/planet_auth_utils/__init__.py @@ -70,6 +70,8 @@ opt_extra, opt_human_readable, opt_issuer, + opt_key, + opt_key_file, opt_loglevel, opt_long, opt_open_browser, @@ -133,6 +135,8 @@ "opt_extra", "opt_human_readable", "opt_issuer", + "opt_key", + "opt_key_file", "opt_loglevel", "opt_long", "opt_open_browser", diff --git a/src/planet_auth_utils/commands/cli/jwt_cmd.py b/src/planet_auth_utils/commands/cli/jwt_cmd.py index 8b999d3..c67d358 100644 --- a/src/planet_auth_utils/commands/cli/jwt_cmd.py +++ b/src/planet_auth_utils/commands/cli/jwt_cmd.py @@ -14,6 +14,7 @@ import click import json +import jwt import pathlib import sys import textwrap @@ -30,6 +31,8 @@ from .options import ( opt_audience, opt_issuer, + opt_key, + opt_key_file, opt_token, opt_token_file, opt_human_readable, @@ -230,12 +233,45 @@ def cmd_jwt_validate_oauth(ctx, token, token_file, audience, issuer, human_reada @opt_human_readable @opt_token @opt_token_file +@opt_key +@opt_key_file @recast_exceptions_to_click(AuthException, FileNotFoundError, NotImplementedError) -def cmd_jwt_validate_rs256(ctx, token, token_file, human_readable): +def cmd_jwt_validate_rs256(ctx, token, token_file, key, key_file, human_readable): """ Validate a JWT signed with a RS256 signature """ - # token_to_validate = _get_token_or_fail(token_opt=token, token_file_opt=token_file) + # The TokenValidator is geared for OAuth2 JWTs. + # This helper is lower level, and doesn't make the same assumptions. + # TODO: it might be nice to still have this more adjacent to the TokenValidator + # to keep practices aligned. + # validator = TokenValidator() + token_to_validate = _get_token_or_fail(token_opt=token, token_file_opt=token_file) + signing_key: jwt.PyJWK = None + # required_claims = [] + validated_complete = jwt.decode_complete( # Throws when invalid. + token_to_validate, + signing_key, + algorithms=["rs256", "RS256"], + # issuer=issuer, + # audience=audience, + options={ + # "require": required_claims, + # "verify_aud": True, + "verify_exp": True, + # "verify_iss": True, + "verify_signature": True, + }, + ) + # XXX check - validation throws on error + click.echo("TOKEN OK") + print_jwt_parts( + raw=token_to_validate, + header=validated_complete["header"], + body=validated_complete["payload"], + signature=validated_complete["signature"], + human_readable=human_readable, + ) + raise NotImplementedError("Command not implemented") diff --git a/src/planet_auth_utils/commands/cli/options.py b/src/planet_auth_utils/commands/cli/options.py index 9767a47..067c4fb 100644 --- a/src/planet_auth_utils/commands/cli/options.py +++ b/src/planet_auth_utils/commands/cli/options.py @@ -295,6 +295,38 @@ def opt_token_file(function): return function +def opt_key(function): + """ + Click option for specifying a key literal. + """ + function = click.option( + "--key", + help="Key string.", + type=str, + # envvar=EnvironmentVariables.AUTH_KEY, + show_envvar=False, + show_default=False, + )(function) + return function + + +def opt_key_file(function): + """ + Click option for specifying a key file location for the + planet_auth package's click commands. + """ + function = click.option( + "--key-file", + type=click.Path(exists=True, file_okay=True, readable=True, path_type=pathlib.Path), + # envvar=EnvironmentVariables.AUTH_KEY_FILE, + help="File containing a key.", + default=None, + show_envvar=False, + show_default=True, + )(function) + return function + + def opt_issuer(required=False): def decorator(function): """