JSON Web Tokens authentication method.
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
JwtAuthentication allows to decode, verify and generate JWT.
JSON Web Tokens authentication method.
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
JwtAuthentication allows to decode, verify and generate JWT.
Create a JwtAuthentication instance.
def __init__(self, secret_key: str, **kwargs):
"""Create a JwtAuthentication instance.
:param secret_key: (str) The secret key
"""
super(JwtAuthentication, self).__init__(**kwargs)
self._available = JWT
if self._available is False:
logging.warning("JwtAuthentication was not initialized: requirement to 'jwt' module is not satisfied.")
else:
if isinstance(secret_key, str) is False:
raise TypeError(f"JwtAuthentication secret key must be a 'str'. Got '{type(secret_key).__name__}' instead.")
self.__secret_key = secret_key
Override. Return the name of the authentication method.
@staticmethod
def name() -> str:
"""Override. Return the name of the authentication method.
:return: (str) The name of the authentication method.
"""
return BaseAuthentication._get_default_name(JwtAuthentication)
Return the secret key of the JWT.
def get_args(self) -> list:
"""Return the secret key of the JWT.
:return: (list) The secret key or an empty list if JWT is not available
"""
if self._available is True:
return [self.__secret_key]
return []
Verify a token.
Verify by decoding the given token, and checking both its validity and expiration date.
def authenticate(self, token: str) -> tuple[bool, str]:
"""Verify a token.
Verify by decoding the given token, and checking both its validity
and expiration date.
:param token: (str) The token to verify
:return: (bool) True if the token is valid, False otherwise)
"""
if self._available is False:
return (False, 'JwtAuthentication unavailable')
if isinstance(token, str) is False:
raise TypeError(f"JwtAuthentication.authenticate: Token must be a 'string'. Got a '{type(token).__name__}' instead.")
if len(token) == 0:
return (False, 'Token is empty')
try:
return (True, self.decode_token(token))
except KeyError:
return (False, 'Token is invalid')
Generate a JWT token from the given parameter.
def generate_token(self, entry: str, validity: int=30) -> str | None:
"""Generate a JWT token from the given parameter.
:param entry: (str) The string to encode in the token
:param validity: (int) The amount of time in seconds that the token should expire
:return: (str | None) A coded token or None if JWT is not available
:raises: TypeError: if the entry is invalid
"""
if self._available is False:
return None
if isinstance(entry, str) is False:
raise TypeError(f'Entry to generate a token must be a string.Got {type(entry).__name__} instead.')
if isinstance(validity, int) is False:
logging.error("JwtAuthentication.generate_token: validity must be a 'int'. Set to 30 minutes.")
validity = 30
payload = {'exp': datetime.now(tz=timezone.utc) + timedelta(minutes=validity), 'iat': datetime.now(tz=timezone.utc), 'sub': entry}
return jwt.encode(payload, self.__secret_key, algorithm='HS256')
Decode a JWT token.
def decode_token(self, token: str) -> str | None:
"""Decode a JWT token.
:param token: (str) the token to be decoded
:return: (str | None) the decoded token or None if JWT is not available
:raises: KeyError: if the token is invalid
:raises: KeyError: if the token is expired
"""
if self._available is False:
return None
if isinstance(token, str) is False:
raise TypeError(f'Token to be decoded must be a string.Got {type(token).__name__} instead.')
try:
payload = jwt.decode(token, self.__secret_key, algorithms=['HS256'])
return payload['sub']
except jwt.ExpiredSignatureError:
raise KeyError('Token is expired')
except jwt.InvalidTokenError:
raise KeyError('Token is invalid')
Return a string representation of the class.
def __str__(self):
"""Return a string representation of the class.
:return: (str) A string representation of the JwtAuthentication
"""
if self._available is False:
return '{:s} unavailable'.format(self.__class__.__name__)
return "{:s}(secret key: '{:s}', id: '{}')".format(self.__class__.__name__, self.__secret_key, self.method_id)
Return the official string representation of the class.
def __repr__(self):
"""Return the official string representation of the class.
:return: (str) The official string representation of the JwtAuthentication
"""
if self._available is False:
return '{:s} unavailable'.format(self.__class__.__name__)
return '{:s}({:s})'.format(self.__class__.__name__, ', '.join(["name: '{}'".format(self.name()), "id: '{}'".format(self.method_id), "secret key: '{}'".format(self.__secret_key)]))