def blacklist_encoded_token(encoded_token, public_key=None): """ Given an encoded refresh JWT ``encoded_token``, add it to the blacklist using its JWT id ``jti`` and expiration ``exp``. This just wraps ``blacklist_token`` by decoding the token first. The token _must_ be a refresh token; only refresh tokens may be blacklisted. Args: encoded_token (str): the token public_key (Optional[str]): public key to decode token with Return: None Raises: - BlacklistingError: - ``jti`` is not UUID4 - ``exp`` not provided - token is missing a claim (``aud``, ``exp``, or ``jti``) - token decoding fails - token is missing Side Effects: - Add entry with ``jti`` to ``BlacklistedToken`` table """ # Decode token and get claims. public_key = public_key or keys.default_public_key() try: claims = jwt.decode( encoded_token, public_key, algorithm="RS256", options={"verify_aud": False}, ) except jwt.InvalidTokenError as e: raise BlacklistingError("failed to decode token: {}".format(e)) try: jti = claims["jti"] exp = claims["exp"] pur = claims["pur"] except KeyError as e: raise BlacklistingError("token missing claim: {}".format(e)) # Do checks. # Check that JWT id is UUID4 (this raises a ValueError otherwise). uuid.UUID(jti, version=4) # Must be refresh token or API key in order to revoke. if pur != "refresh" and pur != "api_key": raise BlacklistingError( "can only blacklist refresh tokens and API keys") blacklist_token(jti, exp)
def from_signed_and_encoded_token( cls, encoded_token, public_key=None, verify=True, client_id=None, issuer=None, max_age=None, nonce=None, ): """ Return an instance of UnsignedIDToken by decoding an encoded token. Args: encoded_token (str): encoded JWT ID token signed with a private_key public_key (str, optional): Public key used for encoding, defaults to app's default pub key verify (bool, optional): Whether or not to validate the JWT and ID token. NOTE: This is TRUE by default client_id (str, optional): Client identifier, defaults to current client in flask context issuer (str, optional) Issuer Identifier(s) for the Issuer of the response, defaults to BASE_URL max_age (int, optional): max number of seconds allowed since last user AuthN nonce (str, optional): String value used to associate a Client session with an ID Token Returns: UnsignedIDToken: A newly created instance with claims obtained from decoding the provided encoded token """ # Use application defaults if not provided issuer = issuer or config.get("BASE_URL") public_key = public_key or keys.default_public_key() payload = jwt.decode( encoded_token, public_key, algorithms="RS256", verify=verify, audience=client_id, ) headers = {} token = cls(payload, headers) if verify: token.validate() return token
def _get_initial_session_token(self): keypair = flask.current_app.keypairs[0] session_token = generate_signed_session_token( kid=keypair.kid, private_key=keypair.private_key, expires_in=config.get("SESSION_TIMEOUT"), ).token self._encoded_token = session_token initial_token = validate_jwt( session_token, aud={"fence"}, purpose="session", public_key=default_public_key(), ) return initial_token
def _get_initial_session_token(self): keypair = current_app.keypairs[0] session_token = generate_signed_session_token( kid=keypair.kid, private_key=keypair.private_key, expires_in=current_app.config.get('SESSION_TIMEOUT').seconds, ) self._encoded_token = session_token initial_token = validate_jwt( session_token, aud={'fence'}, purpose='session', public_key=default_public_key(), ) return initial_token
def is_token_blacklisted(encoded_token, public_key=None): """ Decode an encoded token and check if it is blacklisted. Args: encoded_token (str): JWT to check public key (Optional[str]): key to decode JWT with Return: bool: whether JWT is blacklisted """ public_key = public_key or keys.default_public_key() try: token = jwt.decode(encoded_token, public_key, algorithm="RS256", audience="openid") except jwt.exceptions.InvalidTokenError as e: raise JWTError( "could not decode token to check blacklisting: {}".format(e)) return is_blacklisted(token["jti"])
def __init__(self, session_token): self._encoded_token = session_token if session_token: try: jwt_info = validate_jwt( session_token, public_key=default_public_key(), aud={'fence'}, ) except JWTError: # if session token is invalid, create a new # empty one silently jwt_info = self._get_initial_session_token() else: jwt_info = self._get_initial_session_token() self.session_token = jwt_info self.modified = False super(UserSession, self).__init__()
def __init__(self, session_token): self._encoded_token = session_token if session_token: try: jwt_info = validate_jwt( session_token, scope=None, purpose="session", public_key=default_public_key(), ) except JWTError: # if session token is invalid, create a new # empty one silently jwt_info = self._get_initial_session_token() else: # do not create a token for anonymous session jwt_info = {"context": {}} self.session_token = jwt_info self.modified = False super(UserSession, self).__init__()