async def _validate_token(self, jwt_token: str,
                              channel_id: str) -> ClaimsIdentity:
        headers = jwt.get_unverified_header(jwt_token)

        # Update the signing tokens from the last refresh
        key_id = headers.get("kid", None)
        metadata = await self.open_id_metadata.get(key_id)

        if key_id and metadata.endorsements:
            if not EndorsementsValidator.validate(channel_id,
                                                  metadata.endorsements):
                raise Exception("Could not validate endorsement key")

        if headers.get("alg",
                       None) not in self.validation_parameters.algorithms:
            raise Exception("Token signing algorithm not in allowed list")

        options = {
            "verify_aud": False,
            "verify_exp": not self.validation_parameters.ignore_expiration,
        }
        decoded_payload = jwt.decode(jwt_token,
                                     metadata.public_key,
                                     options=options)
        claims = ClaimsIdentity(decoded_payload, True)

        return claims
async def test_sign_in_tampered_token(
    repositories: Repositories,
    approved_up_user: User,
    approved_up_user_email_address: str,
    approved_up_user_password: str,
):
    user_sign_in_request = UserSignInRequest(
        email_address=approved_up_user_email_address,
        password=approved_up_user_password)
    response = await sign_in_user(user_sign_in_request)
    token = f"Bearer {response.token}"
    await get_all_feeds(authorization=token)
    with pytest.raises(HTTPException) as http_exception:
        await get_all_feeds(authorization=f"s-{token}")
    assert http_exception.value.status_code == 401

    # construct some other token.
    decoded = jwt.get_unverified_header(response.token)
    other_users_token = jwt.encode(
        {
            "name": decoded.get("name"),
            "user_id": decoded.get("user_id"),
            "exp": datetime.utcnow() + timedelta(days=7),
        },
        f"wrong-{AppConfig.token_secret_key()}",
        algorithm="HS256",
    )
    with pytest.raises(HTTPException) as http_exception:
        await get_all_feeds(authorization=other_users_token)
    assert http_exception.value.status_code == 401
Example #3
0
    def verify_cognito_kid(jwt_value):
        """
        Verifies that the kid in the access_token header matches a well-known kid in Cognito
        :param jwt_value:
        :return:
        """
        try:
            jwt_kid = jwt.get_unverified_header(jwt_value).get('kid')
        except jwt.exceptions.DecodeError:
            raise exceptions.AuthenticationFailed({
                'error': 'invalid_jwt'
            })

        if jwt_kid is None:
            raise exceptions.AuthenticationFailed({
                'error': 'kid_required'
            })

        jwk_path = os.path.join(settings.BASE_DIR, 'account', 'resources', 'jwks.json')
        if not os.path.isfile(jwk_path):
            capture_message("jwks_missing: jwks.json does not exist. run get_all_jwks", level="error")
            raise exceptions.AuthenticationFailed({
                'error': 'jwks_missing'
            })

        with open(jwk_path) as f:
            keys = json.loads(f.read())['keys']
        keys = [key['kid'] for key in keys]

        if not jwt_kid in keys:
            capture_message("invalid_kid: make sure JWKs retrieved (get_all_jwks)", level="error")
            raise exceptions.AuthenticationFailed({
                'error': 'invalid_kid'
            })
Example #4
0
def test_keys_with_key_id(monkeypatch, user, call_auth_endpoint, rsa_keys):

    monkeypatch.setattr(api_settings, "JWT_PRIVATE_KEY",
                        {"rsa1": rsa_keys["secret"]["rsa1"]})
    monkeypatch.setattr(api_settings, "JWT_PUBLIC_KEY", rsa_keys["public"])

    secret_key = OrderedDict([("hash1", "one"), ("hash2", "two")])
    monkeypatch.setattr(api_settings, "JWT_SECRET_KEY", secret_key)

    for kid, algo in {
            "hash1": ["HS256", "RS256"],
            "rsa1": ["RS256", "HS256"]
    }.items():
        monkeypatch.setattr(api_settings, "JWT_ALGORITHM", algo)

        response = call_auth_endpoint("username", "password")
        token = response.json()["token"]

        # check needs to succeed no matter which algo is first
        algo = [algo[1], algo[0]]
        monkeypatch.setattr(api_settings, "JWT_ALGORITHM", algo)
        payload = JSONWebTokenAuthentication.jwt_decode_token(token)
        hdr = get_unverified_header(token)

        assert hdr["kid"] == kid
        assert response.status_code == status.HTTP_200_OK
        assert payload["user_id"] == user.id
        assert payload["username"] == user.get_username()
Example #5
0
def decode_jwt(token: str,
               audience: typing.List[str]) -> typing.Optional[typing.Mapping]:
    """
    Verify and decode the JWT from the request.

    :param token: the Authorization header in the request.
    :param audience: the expected audience for the JWT
    :return: Decoded and verified token info.
    """
    try:
        unverified_token = jwt.decode(token, verify=False)
    except jwt.DecodeError:
        raise AuthenticationException('Failed to decode token.')

    assert_authorized_issuer(unverified_token)
    issuer = unverified_token['iss']
    public_keys = get_public_keys(issuer)

    try:
        token_header = jwt.get_unverified_header(token)
        verified_token_info = jwt.decode(
            token,
            key=public_keys[token_header["kid"]],
            issuer=issuer,
            audience=audience,
            algorithms=allowed_algorithms,
        )
    except jwt.PyJWTError as ex:  # type: ignore
        raise AuthenticationException('Authorization token is invalid') from ex
    return verified_token_info
def authenticate(encoded_token: str) -> Mapping[str, Any]:
    """
    Authenticate the token.
    Upon successful authentication, the decoded token is returned.
    Otherwise, an exception is thrown.
    :param encoded_token: The encoded token in string form
    :return: The verified token
    :raises PyJWTError: if there's an issue decoding the token
    :raises Exception: if there's some other issue
    """
    unverified_token = jwt.decode(encoded_token, verify=False)
    unverified_headers = jwt.get_unverified_header(encoded_token)
    jti = unverified_token.get("jti", "UNKNOWN")
    logger.debug(f"Authenticating token with jti: {jti}")
    if current_app.config["NO_VERIFY"] is True:
        logger.debug(f"Skipping Verification of the token with jti: {jti}")
        return unverified_token

    issuer_url = unverified_token["iss"]
    if issuer_url not in current_app.config["ISSUERS"]:
        raise InvalidIssuerError(f"Unauthorized Issuer: {issuer_url}")
    issuer = current_app.config["ISSUERS"][issuer_url]

    # This can throw an InvalidIssuerError as well,
    # though it may be a server-side issue
    key = get_key_as_pem(issuer_url, unverified_headers["kid"])
    return jwt.decode(
        encoded_token,
        key,
        algorithm=ALGORITHM,
        audience=issuer["audience"],
        options=current_app.config.get("JWT_VERIFICATION_OPTIONS"),
    )
Example #7
0
    def _authenticate(self, request: Request):
        """Authenticate a request
        """
        token = self._get_token_from_headers(request)
        if token is None:
            token = self._get_token_from_qs(request)
        if token is None:
            return None

        # Check if this is a JWT token, and if it has the expected key ID
        try:
            header = jwt.get_unverified_header(token)
            if self.key_id and self.key_id != header.get('kid'):
                return None
        except jwt.PyJWTError:
            return None

        # We got a JWT token, now let's decode and verify it
        try:
            return jwt.decode(token,
                              key=self._get_verification_key(),
                              algorithms=self.algorithm,
                              leeway=self.leeway)
        except jwt.PyJWTError as e:
            raise Unauthorized(
                'Expired or otherwise invalid JWT token ({})'.format(str(e)))
    async def auth_middleware(request, handler):
        request.user = None
        try:
            token = request.headers.get('authorization', None).split(' ')[1]
            unverified_header = jwt.get_unverified_header(token)
        except:
            return await handler(request)
        rsa_key = await validate_header(unverified_header)
        if rsa_key:
            try:
                payload = jwt.decode(
                    token,
                    jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(rsa_key)),
                    algorithms=[JWT_ALGORITHM],
                    audience=API_AUDIENCE,
                    issuer=f"https://{AUTH0_DOMAIN}/",
                )
            except jwt.ExpiredSignatureError:
                return web.json_response({'message': 'token is expired'},
                                         status=401)
            except (jwt.InvalidAudienceError, jwt.InvalidIssuerError):
                return web.json_response(
                    {
                        'message':
                        'Incorrect claims, please check the audience and issuer'
                    },
                    status=401)
            except Exception:
                return web.json_response(
                    {'message': 'Unable to parse authentication token.'},
                    status=401)

            request.user = payload
        return await handler(request)
Example #9
0
    def jwt_bruteforce(
        self, wordlist: str, b64_encode: bool = False, algorithm: list = ["HS256"]
    ):
        """Brute force JWT token secret

        This method will use the provided wordlist to try and bruteforce the 
        verification.
        
        Args:
            wordlist (str): Required. Path to a wordlist
            b64_encode (bool, optional): Encoded the words in base64. Defaults to False.
            algorithm (list, optional): Array of valid algorithms. Defaults to ["HS256"].
        
        Returns:
            Chepy: The Chepy object. 
        """
        with open(pathlib.Path(wordlist).expanduser().absolute()) as words:
            for word in words:
                try:
                    word = word.strip()
                    if b64_encode:  # pragma: no cover
                        word = base64.b64encode(word)
                    j = jwt.decode(self._convert_to_str(), word, algorithms=algorithm)
                    self.state = {
                        "paylod": j,
                        "header": jwt.get_unverified_header(self._convert_to_str()),
                        "secret": word,
                    }
                    return self
                except jwt.InvalidSignatureError:
                    continue
            else:  # pragma: no cover
                return self
Example #10
0
def decode_jwt(jwt_token, provider):
    """

    :param jwt_token:
    :param provider:
    :return:
    """

    provider_config = current_app.config['LTI_TOOL_CONFIG'].get_iss_config(
        provider)
    jwks_url = provider_config['key_set_url']
    jwks = requests.get(jwks_url).json()

    public_keys = {}
    for jwk in jwks['keys']:
        kid = jwk['kid']
        public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(
            json.dumps(jwk))

    kid = jwt.get_unverified_header(jwt_token)['kid']
    key = public_keys[kid]

    jwt_payload = jwt.decode(jwt_token,
                             key=key,
                             audience=provider_config['client_id'],
                             algorithms=['RS256'])

    return jwt_payload
def validate_iap_jwt(base_url, iap_jwt):
    """Validate a JWT passed to your application by Identity-Aware Proxy.

    Args:
      base_url: The URL from the incoming request, minus any path, query, etc.
                For instance: "https://example.com:8443" or
                "https://example.appspot.com" .
      iap_jwt: The contents of the X-Goog-Authenticated-User-JWT header.

    Returns:
      (user_id, user_email, error_str).
    """
    try:
        key_id = jwt.get_unverified_header(iap_jwt).get('kid')
        if not key_id:
            return (None, None, '**ERROR: no key ID**')
        key = get_iap_key(key_id)
        decoded_jwt = jwt.decode(
            iap_jwt, key,
            algorithms=['ES256'],
            audience=base_url)
        return (decoded_jwt['sub'], decoded_jwt['email'], '')
    except (jwt.exceptions.InvalidTokenError,
            requests.exceptions.RequestException) as e:
        return (None, None, '**ERROR: JWT validation error {}**'.format(e))
def validate_cognito_id_token(
        token: str,
        region: str,
        user_pool_id: str,
        client_id: str,
) -> dict:
    header = jwt.get_unverified_header(token)
    keys = get_jwt_keys(region, user_pool_id)

    # convert to {kid: key} map, instead of [{kid: kid, ...}, ...] list
    keys = {
        key['kid']: key
        for key in keys['keys']
    }

    key = keys[header['kid']]  # may raise

    public_key = import_jwk(key)
    token = jwt.decode(
        token,
        key=public_key,
        algorithms=['RS256'],
        audience=client_id,
    )
    return token
Example #13
0
    def decode_token(self, token, use):
        kid = jwt.get_unverified_header(token).get('kid')
        jwt_set = [x for x in self.cognito_jwt_set.get('keys')
                   if x.get('kid') == kid][0]
        n_str, e_str = jwt_set.get('n'), jwt_set.get('e')

        # signature verification included
        if use == 'access':
            decoded = jwt.decode(token, key=_public_key(n_str, e_str))
        elif use == 'id':
            decoded = jwt.decode(
                token, key=_public_key(n_str, e_str),
                audience=app.config.get('COGNITO_CLIENT_ID'))
        else:
            raise exception.AuthError('unknown token_use:{}'.format(use))

        if decoded.get('iss') != 'https://cognito-idp.{}.amazonaws.com/{}' \
                  .format(self.cognito_region, self.cognito_user_pool_id):
            raise exception.AuthError('token invalid. bad iss.')
        if decoded.get('token_use') != use:
            raise exception.AuthError(
                'token invalid. bad token_use. expected {}'.format(use))
        if datetime.datetime.fromtimestamp(decoded.get('exp'), pytz.utc) \
           < datetime.datetime.now(pytz.utc):
            raise exception.AuthError('token invalid. expired.')

        return decoded
Example #14
0
def verify_jwt_token(jwt_token, expected_issuer, expected_audience, algorithms,
                     public_certs_url):
    # https://developers.cloudflare.com/access/setting-up-access/validate-jwt-tokens/
    # https://cloud.google.com/iap/docs/signed-headers-howto
    # Loop through the keys since we can't pass the key set to the decoder
    keys = get_public_keys(public_certs_url)

    key_id = jwt.get_unverified_header(jwt_token).get('kid', '')
    if key_id and isinstance(keys, dict):
        keys = [keys.get(key_id)]

    valid_token = False
    payload = None
    for key in keys:
        try:
            # decode returns the claims which has the email if you need it
            payload = jwt.decode(jwt_token,
                                 key=key,
                                 audience=expected_audience,
                                 algorithms=algorithms)
            issuer = payload['iss']
            if issuer != expected_issuer:
                raise Exception('Wrong issuer: {}'.format(issuer))
            valid_token = True
            break
        except Exception as e:
            logging.exception(e)
    return payload, valid_token
Example #15
0
    def decorated(*args, **kwargs):
        token = get_token_auth_header(request)
        with urllib.request.urlopen(os.getenv('AUTH0_BASE_URL') + "/.well-known/jwks.json") as url:
            jwks = json.loads(url.read().decode())
        unverified_header = jwt.get_unverified_header(token)
        rsa_key = {}
        for key in jwks["keys"]:
            if key["kid"] == unverified_header["kid"]:
                rsa_key = RSAAlgorithm.from_jwk(json.dumps(key))
        if rsa_key:
            try:
                payload = jwt.decode(
                    token,
                    rsa_key,
                    algorithms=ALGORITHMS,
                    audience=os.getenv('AUTH0_WEB_API_AUDIENCE'),
                    issuer=os.getenv('AUTH0_BASE_URL') + "/"
                )
            except jwt.ExpiredSignatureError:
                raise CoreAuthError({"code": "token_expired",
                                     "description": "token is expired"}, 401)
            except jwt.MissingRequiredClaimError:
                raise CoreAuthError({"code": "invalid_claims",
                                     "description":
                                         "incorrect claims,"
                                         "please check the audience and issuer"}, 401)
            except Exception as e:
                raise CoreAuthError({"code": "invalid_header",
                                     "description": str(e)}, 401)

            _request_ctx_stack.top.current_user = payload
            return f(*args, **kwargs)
        raise CoreAuthError({"code": "invalid_header",
                             "description": "Unable to find appropriate key"}, 401)
Example #16
0
    def visit_value(self, key: str, value: str):
        if value in self._visited_values:
            return

        self._log_visit(value, name=key)

        key = key.lower()

        if key == "appid":
            log.info(f"App ID {value}")
        elif key == "muid":
            log.info(f"MUID {value}")

        values = value.split(" ")
        for val in values:
            try:
                token = jwt.get_unverified_header(val)
                log.info(f"JWT token {token}")
            except:
                pass


#
# g UserAuthentication 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1...'
# DEBUG:visitors:Visiting FedAuth '77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGlu...'
# DEBUG:visitors:Visiting FedAuth1 'UkN6OHVuNlBnaGRudzB3a2RqLzJ1U1JvcTUyZVkx...'
# DEBUG:visitors:Visiting FedAuth2 'cml0eUNvbnRleHRUb2tlbj4='
# DEBUG:visitors:Visiting HostAuthentication 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1...'
Example #17
0
    def decode_user_jwt_token_hs256(self):
        user_info = ''
        signing_algo = ''

        try:
            signing_algo = jwt.get_unverified_header(self.payload)['alg']
        except:
            return False

        try:
            if signing_algo.upper() == 'RS256':
                user_info = jwt.decode(self.payload,
                                       self.__get_pub_key__(),
                                       algorithm='RS256')
            elif signing_algo.upper() == 'HS256':
                user_info = jwt.decode(self.payload,
                                       self.__get_fake_pub_key__(),
                                       algorithm='HS256')
            else:
                return False
        except:
            return False

        if user_info['group'] == 'Supervillains':
            return True
        else:
            False
Example #18
0
 def authorize(self, request, uid=None):
     token = self._get_raw_token(request)
     issuer_info = self._get_issuer_info()
     unverified_headers = jwt.get_unverified_header(token)
     key_id = unverified_headers.get('kid', None)
     if key_id is None:
         raise UnauthorizedException("Missing key id in token")
     jwks_uri = issuer_info.get('jwks_uri')
     if jwks_uri is None:
         raise UnauthorizedException("Missing JWKS URI in config")
     key, algo = self._get_signing_key(jwks_uri, key_id)
     try:
         claims = jwt.decode(token,
                             key,
                             algorithms=algo,
                             issuer=issuer_info['issuer'],
                             audience=self.config['audience'])
     except Exception as e:
         raise UnauthorizedException('Invalid access token: %s' % e)
     if token['preferred_username'] == self.config.get(
             'admin_username', 'admin'):
         return 'admin'
     if uid and uid == claims['preferred_username']:
         return uid
     if uid and uid != claims['preferred_username']:
         raise UnauthorizedException("Only the admin ")
     raise UnauthorizedException('unauthorized')
Example #19
0
def oauth(token):
    jsonurl = urlopen("https://" + app.config['AUTH0_DOMAIN'] +
                      "/.well-known/jwks.json")
    jwks = json.loads(jsonurl.read())
    unverified_header = jwt.get_unverified_header(token)
    rsa_key = {}
    for key in jwks["keys"]:
        if key["kid"] == unverified_header["kid"]:
            rsa_key = {
                "kty": key["kty"],
                "kid": key["kid"],
                "use": key["use"],
                "n": key["n"],
                "e": key["e"]
            }
    if rsa_key:
        try:
            payload = jose_jwt.decode(token,
                                      rsa_key,
                                      algorithms=["RS256"],
                                      audience=app.config['AUTH0_AUDIENCE'],
                                      issuer='https://' +
                                      app.config['AUTH0_DOMAIN'] + '/')
        except Exception as exp:
            traceback.print_exc()
            raise AuthException(
                payload={'info': 'Sessão expirada ou é inválida'}) from exp

    return payload['email']
Example #20
0
def getJWTTokens():
    jsonData = request.get_json()
    if jsonData and 'safetynet' in jsonData and 'device_id' in jsonData and 'timestamp' in jsonData:
        jwt_body = jsonData['safetynet']

        x5c = jwtStandalone.get_unverified_header(jwt_body)['x5c'][0]
        certificate = x509.load_der_x509_certificate(
            base64.b64decode(x5c), default_backend())

        if "CN=attest.android.com" not in certificate.subject.rfc4514_string():
            return "Attestation failed!", 403

        jwt_decoded = jwtStandalone.decode(
            jwt_body, key=certificate.public_key(), algorithm='HS256')

        if jwt_decoded and 'nonce' in jwt_decoded:
            if not check_password_hash(base64.b64decode(jwt_decoded['nonce']).decode('utf-8'), jsonData['timestamp']+jsonData['device_id']):
                return "Error with nonce!", 403

        if jwt_decoded and 'ctsProfileMatch' in jwt_decoded and 'basicIntegrity' in jwt_decoded:
            if jwt_decoded['ctsProfileMatch'] or jwt_decoded['basicIntegrity']:
                expires = datetime.timedelta(days=30)
                jwt_keys = {
                    'access_token': create_access_token(identity=jsonData['device_id']),
                    'refresh_token': create_refresh_token(identity=jsonData['device_id'], expires_delta=expires)
                }
                return jsonify(jwt_keys)
            else:
                return "Attestation failed!", 403
        else:
            return "Invalid attestation response", 403
    return "Missing body parts!", 403
Example #21
0
    def from_jwt(cls, jwt, key=''):
        """
        Decode a JWT string into a Jwt object
        :param str jwt: JWT string
        :param Optional[str] key: key used to verify JWT signature, if not provided then validation
                                  is skipped.
        :raises JwtDecodeError if decoding JWT fails for any reason.
        :return: A DecodedJwt object containing the jwt information.
        """
        verify = True if key else False

        try:
            headers = jwt_lib.get_unverified_header(jwt)

            alg = headers.get('alg')
            if alg != cls.ALGORITHM:
                raise ValueError(f"Incorrect decoding algorithm {alg}, "
                                 f"expecting {cls.ALGORITHM}.")

            payload = jwt_lib.decode(jwt,
                                     key,
                                     algorithms=[cls.ALGORITHM],
                                     options={
                                         'verify_signature': verify,
                                         'verify_exp': True,
                                         'verify_nbf': True,
                                     })
        except Exception as e:
            raise JwtDecodeError(getattr(e, 'message', str(e)))

        return cls._from_jwt(headers, payload, key)
Example #22
0
def decode_token(encoded_token, csrf_value=None):
    """
    Returns the decoded token (python dict) from an encoded JWT. This does all
    the checks to insure that the decoded token is valid before returning it.

    :param encoded_token: The encoded JWT to decode into a python dict.
    :param csrf_value: Expected CSRF double submit value (optional)
    """
    jwt_manager = _get_jwt_manager()
    unverified_claims = jwt.decode(
        encoded_token, verify=False, algorithms=config.algorithm
    )
    unverified_headers = jwt.get_unverified_header(encoded_token)
    # Attempt to call callback with both claims and headers, but fallback to just claims
    # for backwards compatibility
    try:
        secret = jwt_manager._decode_key_callback(unverified_claims, unverified_headers)
    except TypeError:
        msg = (
            "The single-argument (unverified_claims) form of decode_key_callback ",
            "is deprecated. Update your code to use the two-argument form ",
            "(unverified_claims, unverified_headers)."
        )
        warn(msg, DeprecationWarning)
        secret = jwt_manager._decode_key_callback(unverified_claims)
    return decode_jwt(
        encoded_token=encoded_token,
        secret=secret,
        algorithm=config.algorithm,
        identity_claim_key=config.identity_claim_key,
        user_claims_key=config.user_claims_key,
        csrf_value=csrf_value,
        audience=config.audience,
        leeway=config.leeway
    )
Example #23
0
def verify_jwt_token(jwt_token, expected_issuer, expected_audience, algorithms, public_certs_url):
    # https://developers.cloudflare.com/access/setting-up-access/validate-jwt-tokens/
    # https://cloud.google.com/iap/docs/signed-headers-howto
    # Loop through the keys since we can't pass the key set to the decoder
    keys = get_public_keys(public_certs_url)

    key_id = jwt.get_unverified_header(jwt_token).get('kid', '')
    if key_id and isinstance(keys, dict):
        keys = [keys.get(key_id)]

    valid_token = False
    payload = None
    for key in keys:
        try:
            # decode returns the claims which has the email if you need it
            payload = jwt.decode(
                jwt_token,
                key=key,
                audience=expected_audience,
                algorithms=algorithms
            )
            issuer = payload['iss']
            if issuer != expected_issuer:
                raise Exception('Wrong issuer: {}'.format(issuer))
            valid_token = True
            break
        except Exception as e:
            logging.exception(e)
    return payload, valid_token
Example #24
0
def verify_jwt(token: str) -> typing.Optional[typing.Mapping]:
    try:
        unverified_token = jwt.decode(token, verify=False)
    except jwt.DecodeError:
        logger.info(f"Failed to decode JWT: {token}", exc_info=True)
        raise DSSException(401, 'Unauthorized', 'Failed to decode token.')

    assert_authorized_issuer(unverified_token)
    issuer = unverified_token['iss']
    public_keys = get_public_keys(issuer)

    try:
        token_header = jwt.get_unverified_header(token)
        verified_tok = jwt.decode(
            token,
            key=public_keys[token_header["kid"]],
            issuer=issuer,
            audience=Config.get_audience(),
            algorithms=allowed_algorithms,
        )
        logger.info("""{"valid": true, "token": %s}""",
                    json.dumps(verified_tok))
    except jwt.PyJWTError as ex:  # type: ignore
        logger.info("""{"valid": false, "token": %s}""",
                    json.dumps(unverified_token),
                    exc_info=True)
        raise DSSException(401, 'Unauthorized',
                           'Authorization token is invalid') from ex
    return verified_tok
Example #25
0
def _signer_kid(encoded_jwt, allow_none=False):
    headers = get_unverified_header(encoded_jwt)
    kid = headers.get('kid', None)
    if not kid and not allow_none:
        abort(400)

    return kid
Example #26
0
def get_payload(encoded):
    failed = False
    print(encoded)
    try:
        print(jwt.get_unverified_header(encoded))
        decoded_jwt = jwt.decode(encoded,
                                 options={"verify_signature": False},
                                 algorithms=["RS256"])
        keys_returned = decoded_jwt.keys()
    except jwt.exceptions.DecodeError as e:
        print("Decode failed.", e)
        decoded_jwt = None
        failed = True
    if not failed:
        if "appId" not in keys_returned:
            print("Error: encoded JWT data does not contain appId key.")
        if "activationRefId" not in keys_returned:
            print(
                "Error: encoded JWT data does not contain activationRefId key."
            )
        if "expiresIn" not in keys_returned:
            print("Error: encoded JWT data does not contain expiresIn key")
        try:
            expiration_time = datetime.fromtimestamp(decoded_jwt["expiresIn"] /
                                                     1000)
        except:
            print("Error: encoded JWT expiration time invalid.")
        if expiration_time < datetime.now():
            print(f"Error: the JWT expired on {expiration_time}")
        elif debug:
            print(f"Note: JWT token will expire {expiration_time}")
    return decoded_jwt
Example #27
0
def verify_token(token):
    public_key = current_app.config.get("QUICKPOLL_PUBLIC_KEY")
    algorithm = current_app.config.get("QUICKPOLL_ALGORITHM", "RS512")

    if not public_key:
        return False

    try:
        data = jwt.decode(token, public_key, algorithm=algorithm)
    except jwt.InvalidTokenError:
        try:
            print(jwt.get_unverified_header(token))
            print(jwt.decode(token, verify=False))
        except jwt.InvalidTokenError:
            print("Unable to decode JWT")

        return False

    try:
        return User(
            id=data["id"],
            username=data.get("username"),
            roles=data.get("roles", [])
        )
    except KeyError:
        return False
Example #28
0
    def get_jwt_info(self):
        if has_jwt is False:
            self.error_message = "PyJWT not installed, please add PyJWT to requirements.txt add deploy saas again"
            return False
        if has_crypto is False:
            self.error_message = (
                "cryptography not installed, please add PyJWT to requirements.txt add "
                "deploy saas again")
            return False

        if not self.raw_content:
            self.error_message = "X_BKAPI_JWT not in http header or it is empty, please called API through API Gateway"
            return False
        try:
            self.headers = jwt.get_unverified_header(self.raw_content)
            self.payload = jwt.decode(self.raw_content,
                                      settings.APIGW_PUBLIC_KEY,
                                      issuer='APIGW')
            self.is_valid = True
        except jwt_exceptions.InvalidKeyError:
            self.error_message = "APIGW_PUBLIC_KEY error"
        except jwt_exceptions.DecodeError:
            self.error_message = "Invalid X_BKAPI_JWT, wrong format or value"
        except jwt_exceptions.ExpiredSignatureError:
            self.error_message = "Invalid X_BKAPI_JWT, which is expired"
        except jwt_exceptions.InvalidIssuerError:
            self.error_message = "Invalid X_BKAPI_JWT, which is not from API Gateway"
        except Exception as error:
            LOG.exception('decode jwt fail')
            self.error_message = error.message
Example #29
0
 def validate_request(self, req, config):
     headers = req.headers
     if "Authorization" not in headers:
         return False, "Must provide authorization header.", None
     id_token = headers["Authorization"]
     try:
         kid = jwt.get_unverified_header(id_token)['kid']
     except:
         return False, "Could not retrieve kid from ID token.", None
     try:
         public_key = self.get_key(kid)
     except:
         return False, "Failed to retrieve public key.", None
     if public_key is None:
         return False, "Unable to find matching public key.", None
     try:
         token_data = jwt.decode(
             id_token,
             public_key,
             algorithms='RS256',
             audience=config.client_id,
         )
     except:
         return False, "ID Token is invalid.", None
     try:
         now = time.time()
         exp = token_data['exp']
         if now > exp:
             return False, "Token is expired.", None
         nbf = token_data['nbf']
         if now < nbf:
             return False, "Token nbf check failed.", None
     except:
         return False, "Token timestamps are invalid.", None
     return True, None, token_data
Example #30
0
    def verify_login(self, token):
        """

        This function is called for each Flask route. This is to ensure that user's login is verified for each web page.
        To avoid multiple calls to Keycloak's introspect endpoint, this function performs manual token validation
        """
        # Make request to keycloak's jwks endpoint, which returns the Json web key set
        jwk_uri = '{0}/auth/realms/{1}/protocol/openid-connect/certs'.format(
            base_uri, realm)
        jwks = requests.get(jwk_uri).json()
        public_keys = {}
        # Sort all the returned jwk into dictionary keyed with their KID. In this case, we are returned with a single key
        for jwk in jwks['keys']:
            kid = jwk['kid']
            public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(
                json.dumps(jwk))
        # Get the Kid from access token - it tells which key was used to sign the token
        kid = jwt.get_unverified_header(token)['kid']
        # Use the same key to verify signature
        key = public_keys[kid]
        # The jwt decode throws an exception if it fails to verify signature. Catch the exception and authenticate user before serving the request.
        try:
            jwt_decode = jwt.decode(token,
                                    key=key,
                                    audience='{}'.format(realm))
            print(jwt_decode)
            verify_user = jwt_decode['preferred_username']
            print(verify_user)
            return True, verify_user
        except:
            return False, verify_user
Example #31
0
 def decode(self, token: str) -> Dict[str, Any]:
     """
         Args:
             token: The jwt token to decode
         
         Returns:
             the decoded token
     """
     public_keys = {}
     unverified_header = jwt.get_unverified_header(token)
     for jwk in self._key["keys"]:
         if jwk["kid"] == unverified_header["kid"]:
             kid = jwk["kid"]
             public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(
                 json.dumps(jwk))
             rsa_key = public_keys[kid]
             if rsa_key:
                 try:
                     return jwt.decode(
                         token,
                         rsa_key,
                         algorithms=["RS256"],
                         options={"verify_aud": False},
                     )
                 except jwt.ExpiredSignatureError:
                     raise LumAppsJwtTokenExpiredError("Token is expired.")
                 except LumAppsJWTClaimsError:
                     raise LumAppsJwtInvalidClaimError(
                         "Incorrect claims, please check the audience and issuer."
                     )
                 except Exception as e:
                     raise LumAppsJwtCustomError(e)
     raise LumAppsJwtHeaderError("Unable to find appropriate key.")
Example #32
0
def decode_token(token):
    """Return user dict from given token.
    If incorrect token or user is inputted, it returns None.
    """

    # firstly get public u_id from header
    try:
        u_id = jwt.get_unverified_header(token).get('u_id')
    except DecodeError:
        return None

    # next, get the hidden session_secret
    try:
        stored_secret = jwt.decode(token, JWT_SECRET,
                                   algorithms=['HS256']).get('session_secret')
    except DecodeError:
        # if it fails to decode token, return none
        return None
    # find user with session secret
    focus_user = None
    for user in data.return_users():
        if (user.get('session_secret') == stored_secret
                and user.get('u_id') == u_id):
            # if user is correct and matches the session
            focus_user = user
            break

    # if u_id and session_secret match, return user
    # if no user is found, it also returns None
    return focus_user
Example #33
0
def oauth2_callback():
    state = json.loads(base64.b64decode(request.args["state"]))
    token_endpoint = get_openid_config(
        os.environ["OPENID_PROVIDER"])["token_endpoint"]
    res = requests.post(
        token_endpoint,
        dict(code=request.args["code"],
             client_id=os.environ["OAUTH2_CLIENT_ID"],
             client_secret=os.environ["OAUTH2_CLIENT_SECRET"],
             redirect_uri=get_redirect_uri(),
             grant_type="authorization_code"))
    token_header = jwt.get_unverified_header(res.json()["id_token"])
    tok = jwt.decode(res.json()["id_token"],
                     key=get_public_key(token_header["kid"]),
                     audience=os.environ["OAUTH2_CLIENT_ID"])
    assert tok["email_verified"]
    credentials = sts.assume_role(RoleArn=os.environ["ASSUME_ROLE_ARN"],
                                  RoleSessionName=tok["email"])["Credentials"]
    del credentials["Expiration"]
    cookie = base64.b64encode(json.dumps(credentials).encode()).decode()
    cookie_header = "elk_auth={}; Path=/; Max-Age=3600; Secure; HttpOnly".format(
        cookie)
    response = make_response("", 302)
    response.headers['Location'] = state["nav_origin"]
    response.headers['Set-Cookie'] = cookie_header
    return response
Example #34
0
    def storeToken(token, request, conf):
        """ Save the important parts of the token in session storage.
            Returns the corresponding SessionInfo object.  If we can't
            return the object for any reason, we remove the Auth0 information
            from the session and expire the cookie.
        """
        try:
            session = request.SESSION
            # get the key id from the jwt header
            key_id = jwt.get_unverified_header(token)['kid']
            key = Auth0._getKey(key_id, conf)
            if not key:
                log.warn('Invalid jwt kid (key id) - not setting session info')
                Auth0.removeToken(request)
                return None

            payload = jwt.decode(token, key, verify=True,
                                 algorithms=['RS256'],
                                 audience=conf['audience'],
                                 issuer=conf['tenant'])

            # Make sure we have an auth0 conf
            conf = conf or getAuth0Conf()
            if not conf:
                log.warn('Incomplete Auth0 config in GlobalConfig - not using Auth0 login')
                Auth0.removeToken(request)
                return None

            # Verify that the tenant is in our whitelist.
            # + The tenantkey is used to lookup the tenant from the jwt.
            tenantkey = conf.get('tenantkey', 'https://dev.zing.ninja/tenant')
            tenant = payload.get(tenantkey, None) # ie: "https://dev.zing.ninja/tenant": "alphacorp", in jwt
            if not tenant:
                log.warn('No auth0 tenant specified in jwt for tenantkey: {}'.format(tenantkey))
                Auth0.removeToken(request)
                return None
            # + Get the whitelist from global.conf and verify that it's in the list.
            whitelist = conf.get('whitelist', [])
            if not tenant in whitelist:
                log.warn('Tenant {} is invalid. Not in whitelist: {}'.format(tenant, whitelist))
                Auth0.removeToken(request)
                return None

            emailkey = conf.get('emailkey', 'https://dev.zing.ninja/email')
            email = payload.get(emailkey, None)

            sessionInfo = session.setdefault(Auth0.session_key, SessionInfo())
            # use the email as the userid, if defined, otherwise fall back to parsing the sub field.
            if email:
                sessionInfo.userid = email
            else:
                sessionInfo.userid = payload['sub'].encode('utf8').split('|')[-1]
            sessionInfo.expiration = payload['exp']
            sessionInfo.roles = Auth0.getRoleAssignments(payload.get('https://zenoss.com/roles', []))
            return sessionInfo
        except Exception as ex:
            log.debug('Error storing jwt token: {}'.format(ex.message))
            Auth0.removeToken(request)
            return None
Example #35
0
    def assertJwtsEqual(self, jwt, key, expected_payload=None, expected_headers=None):
        expected_headers = expected_headers or {}
        expected_payload = expected_payload or {}

        decoded_payload = jwt_lib.decode(jwt, key, verify=False)
        decoded_headers = jwt_lib.get_unverified_header(jwt)

        self.assertEqual(expected_headers, decoded_headers)
        self.assertEqual(expected_payload, decoded_payload)
Example #36
0
 def parsing_token(self,raw_jwttoken):
     raw_jwttoken = unquote(raw_jwttoken)
     token = JWTToken()
     try:
         token.headers = jwt.get_unverified_header(raw_jwttoken)
         token.body = jwt.decode(raw_jwttoken, verify=False)
         token.algo = token.headers['alg']
     except:
         pass
     return token
Example #37
0
def get_header(jwt_string):
    """ Return all of the headers in the given JWT.

    :return the headers as a dictionary
    """
    try:
        return jwt.get_unverified_header(jwt_string)
    except jwt.InvalidTokenError as e:
        log.debug("", exc_info=1)
        raise ValidationError("Unable to decode token: %s" % e)
Example #38
0
def get_header(jwt_string):
    """ Return all of the headers in the given JWT.

    :return the headers as a dictionary
    """
    try:
        return jwt.get_unverified_header(jwt_string)
    except jwt.InvalidTokenError as e:
        if log.isEnabledFor(logging.DEBUG):
            log.exception('')
        raise ValidationError('Unable to decode token: %s' % e)
def _validate_iap_jwt(iap_jwt, expected_audience):
    try:
        key_id = jwt.get_unverified_header(iap_jwt).get('kid')
        if not key_id:
            return (None, None, '**ERROR: no key ID**')
        key = get_iap_key(key_id)
        decoded_jwt = jwt.decode(
            iap_jwt, key,
            algorithms=['ES256'],
            audience=expected_audience)
        return (decoded_jwt['sub'], decoded_jwt['email'], '')
    except (jwt.exceptions.InvalidTokenError,
            requests.exceptions.RequestException) as e:
        return (None, None, '**ERROR: JWT validation error {}**'.format(e))
    def _check_headers(self, token):
        header_data, payload_data, signature_data = token.split('.', maxsplit=2)
        try:
            headers = self._base64_decode(header_data)
            if not headers:
                raise InvalidTokenException("Missing Headers")
            self._check_for_duplicates(headers)
        except UnicodeDecodeError:
            raise InvalidTokenException("Corrupted Header")
        except ValueError as e:
            raise InvalidTokenException(repr(e))

        header = jwt.get_unverified_header(token)
        self._check_header_values(header)
Example #41
0
def ValidateIapJwt(iap_jwt, expected_audience):
  """Validates an IAP JWT."""

  try:
    key_id = jwt.get_unverified_header(iap_jwt).get("kid")
    if not key_id:
      raise IAPValidationFailedError("No key ID")
    key = GetIapKey(key_id)
    decoded_jwt = jwt.decode(
        iap_jwt, key, algorithms=["ES256"], audience=expected_audience)
    return (decoded_jwt["sub"], decoded_jwt["email"])
  except (jwt.exceptions.InvalidTokenError,
          requests.exceptions.RequestException) as e:
    raise IAPValidationFailedError(e)
def decode_jwt_token(token):
    unverified_header = jwt.get_unverified_header(token)
    unverified_claims = jwt.decode(token, verify=False)

    if unverified_header.get(claims.KEY_ID):
        unverified_key_id = six.text_type(unverified_header.get(claims.KEY_ID))
    else:
        unverified_key_id = None

    if claims.ISSUER not in unverified_claims:
        raise MissingRequiredClaimError(claims.ISSUER)

    unverified_issuer = six.text_type(unverified_claims[claims.ISSUER])

    if api_settings.ACCEPTED_ISSUERS is not None and unverified_issuer not in api_settings.ACCEPTED_ISSUERS:
        raise InvalidIssuerError('Invalid issuer')

    public_key, key_id = get_public_key_and_key_id(issuer=unverified_issuer, key_id=unverified_key_id)

    options = {
        'verify_exp': api_settings.VERIFY_EXPIRATION,
        'verify_aud': True,
        'verify_iss': True,
    }

    payload = jwt.decode(
        jwt=token,
        key=public_key,
        verify=api_settings.VERIFY_SIGNATURE,
        algorithms=api_settings.DECODE_ALGORITHMS or [api_settings.ENCODE_ALGORITHM],
        options=options,
        leeway=api_settings.EXPIRATION_LEEWAY,
        audience=api_settings.IDENTITY,
        issuer=unverified_issuer,
    )

    if payload.get(claims.TOKEN) not in (claims.TOKEN_SESSION, claims.TOKEN_AUTHORIZATION):
        raise InvalidTokenError('Unknown token type')
    if payload.get(claims.ISSUER) != api_settings.IDENTITY and payload.get(claims.TOKEN) != claims.TOKEN_AUTHORIZATION:
        raise InvalidTokenError('Only authorization tokens are accepted from other issuers')
    if not payload.get(claims.SESSION_ID):
        raise MissingRequiredClaimError('Session ID is missing.')
    if not payload.get(claims.USER_ID):
        raise MissingRequiredClaimError('User ID is missing.')

    return payload
def verify_auth_token(request):
    """Verifies the JWT auth token in the request.

    If no token is found or if the token is invalid, returns None.
    Otherwise, it returns a dictionary containing the JWT claims.
    """
    if 'Authorization' not in request.headers:
        return None

    # Auth header is in format 'Bearer {jwt}'.
    request_jwt = request.headers['Authorization'].split(' ').pop()

    # Determine which certificate was used to sign the JWT.
    header = jwt.get_unverified_header(request_jwt)
    kid = header['kid']

    certificates = get_firebase_certificates()

    try:
        certificate = certificates[kid]
    except KeyError:
        logging.warning('JWT signed with unkown kid {}'.format(header['kid']))
        return None

    # Get the public key from the certificate. This is used to verify the
    # JWT signature.
    public_key = extract_public_key_from_certificate(certificate)

    # [START decrypt_token]
    try:
        claims = jwt.decode(
            request_jwt,
            public_key,
            algorithms=['RS256'],
            audience=os.environ['FIREBASE_PROJECT_ID'],
            issuer='https://securetoken.google.com/{}'.format(
                os.environ['FIREBASE_PROJECT_ID']))
    except jwt.exceptions.InvalidTokenError as e:
        logging.warning('JWT verification failed: {}'.format(e))
        return None
    # [END decrypt_token]

    return claims
Example #44
0
 def auth_token(self, token):
     header = jwt.get_unverified_header(token)
     kid = header.get('kid')
     if not kid:
         raise Exception("The JWT token not include KID")
     
     if int(time.time()) >= self.cert_expire:
         try:
             yield self.request_cert()
         except Exception as e:
             raise Exception("Requires JWT public certificate failure, {}".format(str(e)))
             
     try:
         cert_obj = load_pem_x509_certificate(self.public_cert.get(kid).encode('utf-8'), default_backend())
         public_key = cert_obj.public_key()
         payload = jwt.decode(token, public_key, audience=self.PROJECT_ID, algorithms=['RS256'], verify=True)
     except Exception as e:
         raise Exception("Verify JWT token failure, {}".format(str(e)))
     
     raise gen.Return({'user_id': payload['user_id'], 'token': token, 'expire': payload['exp'], "ext": payload})
Example #45
0
def get_public_key_for_jwt(encoded_jwt, url):
    """Get public key for JWT in order to verify the signature.

    The keys get cached in order to limit the amount of network round trips.

    Args:
        encoded_jwt: Base64 encoded JWT.
        url: URL where keys can be fetched.

    Raises:
        JwTKeyError if keys cannot be fetched.

    Returns:
        Key as string.
    """
    # Get the Key ID from the JWT header.
    key_id = jwt.get_unverified_header(encoded_jwt).get('kid')
    if not key_id:
        raise JwtKeyError('Missing key ID field in token header')
    key_cache = get_public_key_for_jwt.key_cache
    key = key_cache.get(key_id)
    if key:
        return key

    # Re-fetch the key file.
    keys_json = _fetch_public_keys(url)
    if 'keys' in keys_json:
        _new_keys_dict = {}
        for key_dict in keys_json['keys']:
            public_key = jwt.algorithms.RSAAlgorithm.from_jwk(
                json.dumps(key_dict))
            _new_keys_dict[key_dict['kid']] = public_key
        key_cache = _new_keys_dict
    else:
        key_cache = keys_json
    get_public_key_for_jwt.key_cache = key_cache
    key = key_cache.get(key_id)
    if not key:
        raise JwtKeyError('IAP public key {!r} not found'.format(key_id))

    return key
Example #46
0
    def from_jwt(cls, jwt, key=''):
        """
        Decode a JWT string into a Jwt object
        :param str jwt: JWT string
        :param Optional[str] key: key used to verify JWT signature, if not provided then validation
                                  is skipped.
        :raises JwtDecodeError if decoding JWT fails for any reason.
        :return: A DecodedJwt object containing the jwt information.
        """
        verify = True if key else False

        try:
            payload = jwt_lib.decode(bytes(jwt), key, options={
                'verify_signature': verify,
                'verify_exp': True,
                'verify_nbf': True,
            })
            headers = jwt_lib.get_unverified_header(jwt)
        except Exception as e:
            raise JwtDecodeError(getattr(e, 'message', str(e)))

        return cls._from_jwt(headers, payload, key)
def _get_key_id_from_jwt_header(a_jwt):
    """ returns the key identifier from a jwt header. """
    header = jwt.get_unverified_header(a_jwt)
    return KeyIdentifier(header['kid'])
def test_token_should_contain_correct_headers():
    token = create_jwt_token("key", "client_id")
    headers = jwt.get_unverified_header(token)
    assert headers['typ'] == 'JWT'
    assert headers['alg'] == 'HS256'
Example #49
0
def openid():

    oidc_configuration, jwt_key_set = get_oidc_configuration(current_app)
    token_endpoint = oidc_configuration['token_endpoint']
    userinfo_endpoint = oidc_configuration['userinfo_endpoint']

    data = {
        'grant_type': 'authorization_code',
        'code': request.json['code'],
        'redirect_uri': request.json['redirectUri'],
        'client_id': request.json['clientId'],
        'client_secret': current_app.config['OAUTH2_CLIENT_SECRET'],
    }
    r = requests.post(token_endpoint, data)
    token = r.json()

    try:
        if current_app.config['OIDC_VERIFY_TOKEN']:
            jwt_header = jwt.get_unverified_header(token['id_token'])
            public_key = jwt_key_set[jwt_header['kid']]

            id_token = jwt.decode(
                token['id_token'],
                key=public_key,
                algorithms=jwt_header['alg']
            )
        else:
            id_token = jwt.decode(
                token['id_token'],
                verify=False
            )
    except Exception:
        current_app.logger.warning('No ID token in OpenID Connect token response.')
        id_token = {}

    try:
        headers = {'Authorization': '{} {}'.format(token.get('token_type', 'Bearer'), token['access_token'])}
        r = requests.get(userinfo_endpoint, headers=headers)
        userinfo = r.json()
    except Exception:
        raise ApiError('No access token in OpenID Connect token response.')

    subject = userinfo['sub']
    name = userinfo.get('name') or id_token.get('name')
    nickname = userinfo.get('nickname')
    email = userinfo.get('email') or id_token.get('email')
    email_verified = userinfo.get('email_verified', id_token.get('email_verified', bool(email)))
    picture = userinfo.get('picture') or id_token.get('picture')

    role_claim = current_app.config['OIDC_ROLE_CLAIM']
    group_claim = current_app.config['OIDC_GROUP_CLAIM']
    custom_claims = {
        role_claim: userinfo.get(role_claim) or id_token.get(role_claim, []),
        group_claim: userinfo.get(group_claim) or id_token.get(group_claim, []),
    }

    login = userinfo.get('preferred_username', nickname or email)
    if not login:
        raise ApiError("Must support one of the following OpenID claims: 'preferred_username', 'nickname' or 'email'", 400)

    user = User.find_by_id(id=subject)
    if not user:
        user = User(id=subject, name=name, login=login, password='', email=email,
                    roles=[], text='', email_verified=email_verified)
        user.create()
    else:
        user.update(login=login, email=email)

    roles = custom_claims[role_claim] or user.roles
    groups = custom_claims[group_claim]

    if user.status != 'active':
        raise ApiError('User {} is not active'.format(login), 403)

    if not_authorized('ALLOWED_OIDC_ROLES', roles) and not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('User {} is not authorized'.format(login), 403)
    user.update_last_login()

    scopes = Permission.lookup(login, roles)
    customers = get_customers(login, groups=[user.domain] + groups)

    auth_audit_trail.send(current_app._get_current_object(), event='openid-login', message='user login via OpenID Connect',
                          user=login, customers=customers, scopes=scopes, resource_id=subject, type='user', request=request)

    token = create_token(user_id=subject, name=name, login=login, provider='openid', customers=customers,
                         scopes=scopes, email=email, email_verified=email_verified, picture=picture, **custom_claims)
    return jsonify(token=token.tokenize)