Exemple #1
0
    def parse_token(self, token, now=None):
        """Extract the data embedded in the given token, if valid.

        The token is valid if it has a valid signature and if the embedded
        expiry time has not passed.  If the token is not valid then this
        method raises ValueError.
        """
        # Parse the payload and signature from the token.
        try:
            decoded_token = decode_token_bytes(token)
        except (TypeError, ValueError) as e:
            raise errors.MalformedTokenError(str(e))
        payload = decoded_token[:-self.hashmod_digest_size]
        sig = decoded_token[-self.hashmod_digest_size:]
        # Carefully check the signature.
        # This is a deliberately slow string-compare to avoid timing attacks.
        # Read the docstring of strings_differ for more details.
        expected_sig = self._get_signature(payload)
        if strings_differ(sig, expected_sig):
            raise errors.InvalidSignatureError()
        # Only decode *after* we've confirmed the signature.
        # This should never fail, but well, you can't be too careful.
        try:
            data = json.loads(payload.decode("utf8"))
        except ValueError as e:  # pragma: nocover
            raise errors.MalformedTokenError(str(e))
        # Check whether it has expired.
        if now is None:
            now = time.time()
        if data["expires"] <= now:
            raise errors.ExpiredTokenError()
        return data
    def parse_token(self, token, now=None):
        """Extract the data embedded in the given token, if valid.

        The token is valid if it has a valid signature and if the embedded
        expiry time has not passed.  If the token is not valid then this
        method raises ValueError.
        """
        # Parse the payload and signature from the token.
        try:
            decoded_token = decode_token_bytes(token)
        except (TypeError, ValueError) as e:
            raise errors.MalformedTokenError(str(e))
        payload = decoded_token[:-self.hashmod_digest_size]
        sig = decoded_token[-self.hashmod_digest_size:]
        # Carefully check the signature.
        # This is a deliberately slow string-compare to avoid timing attacks.
        # Read the docstring of strings_differ for more details.
        expected_sig = self._get_signature(payload)
        if strings_differ(sig, expected_sig):
            raise errors.InvalidSignatureError()
        # Only decode *after* we've confirmed the signature.
        # This should never fail, but well, you can't be too careful.
        try:
            data = json.loads(payload.decode("utf8"))
        except ValueError as e:  # pragma: nocover
            raise errors.MalformedTokenError(str(e))
        # Check whether it has expired.
        if now is None:
            now = time.time()
        if data["expires"] <= now:
            raise errors.ExpiredTokenError()
        return data
 def test_token_validation(self):
     manager = tokenlib.TokenManager(timeout=0.2)
     token = manager.make_token({"hello": "world"})
     token_bytes = decode_token_bytes(token)
     # Proper token == valid.
     data = manager.parse_token(token)
     self.assertEquals(data["hello"], "world")
     # Badly-encoded bytes == not valid.
     bad_token = "@" + token[1:]
     with self.assertRaises(errors.MalformedTokenError):
         manager.parse_token(bad_token)
     # Bad signature == not valid.
     bad_token = encode_token_bytes(b"X" * 50)
     with self.assertRaises(errors.InvalidSignatureError):
         manager.parse_token(bad_token)
     bad_token_bytes = token_bytes[:-1]
     bad_token_bytes += b"X" if token_bytes[-1] == b"Z" else b"Z"
     bad_token = encode_token_bytes(bad_token_bytes)
     with self.assertRaises(errors.InvalidSignatureError):
         manager.parse_token(bad_token)
     # Modified payload == not valid.
     bad_token = encode_token_bytes(b"admin" + token_bytes[6:])
     with self.assertRaises(errors.InvalidSignatureError):
         manager.parse_token(bad_token)
     # Expired token == not valid.
     time.sleep(0.2)
     with self.assertRaises(errors.ExpiredTokenError):
         manager.parse_token(token)
Exemple #4
0
 def test_token_validation(self):
     manager = tokenlib.TokenManager(timeout=0.2)
     token = manager.make_token({"hello": "world"})
     token_bytes = decode_token_bytes(token)
     # Proper token == valid.
     data = manager.parse_token(token)
     self.assertEquals(data["hello"], "world")
     # Badly-encoded bytes == not valid.
     bad_token = "@" + token[1:]
     with self.assertRaises(errors.MalformedTokenError):
         manager.parse_token(bad_token)
     # Bad signature == not valid.
     bad_token = encode_token_bytes(b"X" * 50)
     with self.assertRaises(errors.InvalidSignatureError):
         manager.parse_token(bad_token)
     bad_token_bytes = token_bytes[:-1]
     bad_token_bytes += b"X" if token_bytes[-1] == b"Z" else b"Z"
     bad_token = encode_token_bytes(bad_token_bytes)
     with self.assertRaises(errors.InvalidSignatureError):
         manager.parse_token(bad_token)
     # Modified payload == not valid.
     bad_token = encode_token_bytes(b"admin" + token_bytes[6:])
     with self.assertRaises(errors.InvalidSignatureError):
         manager.parse_token(bad_token)
     # Expired token == not valid.
     time.sleep(0.2)
     with self.assertRaises(errors.ExpiredTokenError):
         manager.parse_token(token)
    def get_derived_secret(self, token):
        """Get the derived secret key associated with the given token.

        A per-token secret key is calculated by deriving it from the master
        secret with HKDF.
        """
        try:
            payload = decode_token_bytes(token)[:-self.hashmod_digest_size]
            salt = json.loads(payload.decode("utf8"))["salt"].encode("ascii")
        except (TypeError, KeyError, ValueError) as e:
            raise errors.MalformedTokenError(str(e))
        info = HKDF_INFO_DERIVE + token.encode("ascii")
        secret = HKDF(self.secret, salt=salt, info=info,
                      size=self.hashmod_digest_size, hashmod=self.hashmod)
        return encode_token_bytes(secret)
Exemple #6
0
    def get_derived_secret(self, token):
        """Get the derived secret key associated with the given token.

        A per-token secret key is calculated by deriving it from the master
        secret with HKDF.
        """
        try:
            payload = decode_token_bytes(token)[:-self.hashmod_digest_size]
            salt = json.loads(payload.decode("utf8"))["salt"].encode("ascii")
        except (TypeError, KeyError, ValueError) as e:
            raise errors.MalformedTokenError(str(e))
        info = HKDF_INFO_DERIVE + token.encode("ascii")
        secret = HKDF(self.secret,
                      salt=salt,
                      info=info,
                      size=self.hashmod_digest_size,
                      hashmod=self.hashmod)
        return encode_token_bytes(secret)
Exemple #7
0
 def unsafelyParseToken(self, token):
     # For testing purposes, don't check HMAC or anything...
     return json.loads(decode_token_bytes(token)[:-32].decode('utf8'))
 def unsafelyParseToken(self, token):
     # For testing purposes, don't check HMAC or anything...
     token = token.encode("utf8")
     return json.loads(decode_token_bytes(token)[:-32].decode("utf8"))