Search code examples
pythonparameter-passingjwtdrycode-duplication

How to avoid repeating work in Python without pass by reference?


I am writing web endpoints that take a JSON Web Token (JWT) and have to check the signature on the token. Since I am going to check the signature every time it makes the most sense to me that I should break this step out into a function because DRY.

However, the only way to check whether a JWT is signed correctly is to decode it with its secret key and catch an error. This leads me to the following function:

def is_valid_token(token_string, secret_key):
    try:
        jwt.decode(token_string, secret_key)
        return True
    except jwt.DecodeError:
        return False

This works fine in terms of validating the tokens, however it seems really wasteful that I have this function that will check if the token is valid by decoding and then immediately after this function I am going to have to decode again. That is to say I would do:

if not is_valid_token(token_string, secret_key):
    # Respond with an error to the client
else:
    token_data = jwt.decode(token_string, secret_key)

In this case I am decoding to check if it's valid and then if it is I'm decoding again. In C/C++ I would pass a variable by reference to capture the decoded data and then return true or false. Is there any way to do such a thing in Python?

It occurred to me that I might be able to get away with this by passing in an empty list to capture the decoded data but that seems really inelegant. Is there a Pythonic way to do this?


Solution

  • After discussing with Nullman we've come to the following solution

    def is_valid_token(jwt_string, secret_key, reference_list):
        try:
            data = jwt.decode(jwt_string, secret_key)
            reference_list.append(data) 
            return True
        except:
            return False
    
    reference_var = []
    if not is_valid_token(jwt_string, secret_key, reference_var):
        # Respond with an error to the client
    else:
        data = reference_var[0]