コード例 #1
0
    def test_override_configs(self):
        self.app.config['JWT_TOKEN_LOCATION'] = 'cookies'
        self.app.config['JWT_HEADER_NAME'] = 'Auth'
        self.app.config['JWT_HEADER_TYPE'] = 'JWT'

        self.app.config['JWT_COOKIE_SECURE'] = True
        self.app.config['JWT_ACCESS_COOKIE_NAME'] = 'banana1'
        self.app.config['JWT_REFRESH_COOKIE_NAME'] = 'banana2'
        self.app.config['JWT_ACCESS_COOKIE_PATH'] = '/banana/'
        self.app.config['JWT_REFRESH_COOKIE_PATH'] = '/banana2/'
        self.app.config['JWT_COOKIE_CSRF_PROTECT'] = False
        self.app.config['JWT_ACCESS_CSRF_COOKIE_NAME'] = 'banana1a'
        self.app.config['JWT_REFRESH_CSRF_COOKIE_NAME'] = 'banana2a'
        self.app.config['JWT_CSRF_HEADER_NAME'] = 'bananaaaa'

        self.app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(minutes=5)
        self.app.config['JWT_REFRESH_TOKEN_EXPIRES'] = timedelta(days=7)
        self.app.config['JWT_ALGORITHM'] = 'HS512'
        self.app.config['JWT_BLACKLIST_ENABLED'] = True
        self.app.config['JWT_BLACKLIST_STORE'] = simplekv.memory.DictStore()
        self.app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = 'all'

        with self.app.test_request_context():
            self.assertEqual(get_token_location(), 'cookies')
            self.assertEqual(get_jwt_header_name(), 'Auth')
            self.assertEqual(get_jwt_header_type(), 'JWT')

            self.assertEqual(get_cookie_secure(), True)
            self.assertEqual(get_access_cookie_name(), 'banana1')
            self.assertEqual(get_refresh_cookie_name(), 'banana2')
            self.assertEqual(get_access_cookie_path(), '/banana/')
            self.assertEqual(get_refresh_cookie_path(), '/banana2/')
            self.assertEqual(get_cookie_csrf_protect(), False)
            self.assertEqual(get_access_csrf_cookie_name(), 'banana1a')
            self.assertEqual(get_refresh_csrf_cookie_name(), 'banana2a')
            self.assertEqual(get_csrf_header_name(), 'bananaaaa')

            self.assertEqual(get_access_expires(), timedelta(minutes=5))
            self.assertEqual(get_refresh_expires(), timedelta(days=7))
            self.assertEqual(get_algorithm(), 'HS512')
            self.assertEqual(get_blacklist_enabled(), True)
            self.assertIsInstance(get_blacklist_store(),
                                  simplekv.memory.DictStore)
            self.assertEqual(get_blacklist_checks(), 'all')

        self.app.config['JWT_TOKEN_LOCATION'] = 'banana'
        self.app.config['JWT_HEADER_NAME'] = ''
        self.app.config['JWT_ACCESS_TOKEN_EXPIRES'] = 'banana'
        self.app.config['JWT_REFRESH_TOKEN_EXPIRES'] = 'banana'

        self.app.testing = True  # Propagate exceptions
        with self.app.test_request_context():
            with self.assertRaises(RuntimeError):
                get_jwt_header_name()
            with self.assertRaises(RuntimeError):
                get_access_expires()
            with self.assertRaises(RuntimeError):
                get_refresh_expires()
            with self.assertRaises(RuntimeError):
                get_token_location()
コード例 #2
0
def _encode_refresh_token(identity, secret, algorithm, token_expire_delta):
    """
    Creates a new refresh token, which can be used to create subsequent access
    tokens.

    :param identity: Some identifier used to identify the owner of this token
    :param secret: Secret key to encode the JWT with
    :param algorithm: Which algorithm to use for the toek
    :return: Encoded JWT
    """
    now = datetime.datetime.utcnow()
    uid = str(uuid.uuid4())
    token_data = {
        'exp': now + token_expire_delta,
        'iat': now,
        'nbf': now,
        'jti': uid,
        'identity': identity,
        'type': 'refresh',
    }
    if get_token_location() == 'cookies' and get_cookie_csrf_protect():
        token_data['csrf'] = _create_csrf_token()
    encoded_token = jwt.encode(token_data, secret, algorithm).decode('utf-8')

    # If blacklisting is enabled, store this token in our key-value store
    blacklist_enabled = get_blacklist_enabled()
    if blacklist_enabled:
        store_token(token_data, revoked=False)
    return encoded_token
コード例 #3
0
def _decode_jwt(token, secret, algorithm):
    """
    Decodes an encoded JWT

    :param token: The encoded JWT string to decode
    :param secret: Secret key used to encode the JWT
    :param algorithm: Algorithm used to encode the JWT
    :return: Dictionary containing contents of the JWT
    """
    # ext, iat, and nbf are all verified by pyjwt. We just need to make sure
    # that the custom claims we put in the token are present
    data = jwt.decode(token, secret, algorithm=algorithm)
    if 'jti' not in data or not isinstance(data['jti'], six.string_types):
        raise JWTDecodeError("Missing or invalid claim: jti")
    if 'identity' not in data:
        raise JWTDecodeError("Missing claim: identity")
    if 'type' not in data or data['type'] not in ('refresh', 'access'):
        raise JWTDecodeError("Missing or invalid claim: type")
    if data['type'] == 'access':
        if 'fresh' not in data or not isinstance(data['fresh'], bool):
            raise JWTDecodeError("Missing or invalid claim: fresh")
        if 'user_claims' not in data or not isinstance(data['user_claims'],
                                                       dict):
            raise JWTDecodeError("Missing or invalid claim: user_claims")
    if get_token_location() == 'cookies' and get_cookie_csrf_protect():
        if 'csrf' not in data or not isinstance(data['csrf'],
                                                six.string_types):
            raise JWTDecodeError("Missing or invalid claim: csrf")
    return data
コード例 #4
0
def _decode_jwt_from_cookies(type):
    if type == 'access':
        cookie_key = get_access_cookie_name()
    else:
        cookie_key = get_refresh_cookie_name()

    token = request.cookies.get(cookie_key)
    if not token:
        raise NoAuthorizationError('Missing cookie "{}"'.format(cookie_key))
    secret = _get_secret_key()
    algorithm = get_algorithm()
    token = _decode_jwt(token, secret, algorithm)

    if get_cookie_csrf_protect(
    ) and request.method in get_csrf_request_methods():
        csrf_header_key = get_csrf_header_name()
        csrf_token_from_header = request.headers.get(csrf_header_key, None)
        csrf_token_from_cookie = token.get('csrf', None)

        # Verify the csrf tokens are present and matching
        if csrf_token_from_cookie is None:
            raise JWTDecodeError("Missing claim: 'csrf'")
        if not isinstance(csrf_token_from_cookie, six.string_types):
            raise JWTDecodeError("Invalid claim: 'csrf' (must be a string)")
        if csrf_token_from_header is None:
            raise CSRFError("Missing CSRF token in headers")
        if not safe_str_cmp(csrf_token_from_header, csrf_token_from_cookie):
            raise CSRFError("CSRF double submit tokens do not match")
    return token
コード例 #5
0
def _encode_access_token(identity, secret, algorithm, token_expire_delta,
                         fresh, user_claims):
    """
    Creates a new access token.

    :param identity: Some identifier of who this client is (most common would be a client id)
    :param secret: Secret key to encode the JWT with
    :param fresh: If this should be a 'fresh' token or not
    :param algorithm: Which algorithm to use for the toek
    :return: Encoded JWT
    """
    # Verify that all of our custom data we are encoding is what we expect
    if not isinstance(user_claims, dict):
        raise JWTEncodeError('user_claims must be a dict')
    if not isinstance(fresh, bool):
        raise JWTEncodeError('fresh must be a bool')
    try:
        json.dumps(user_claims)
    except Exception as e:
        raise JWTEncodeError('Error json serializing user_claims: {}'.format(
            str(e)))

    # Create the jwt
    now = datetime.datetime.utcnow()
    uid = str(uuid.uuid4())
    token_data = {
        'exp': now + token_expire_delta,
        'iat': now,
        'nbf': now,
        'jti': uid,
        'identity': identity,
        'fresh': fresh,
        'type': 'access',
        'user_claims': user_claims,
    }
    if get_token_location() == 'cookies' and get_cookie_csrf_protect():
        token_data['csrf'] = _create_csrf_token()
    encoded_token = jwt.encode(token_data, secret, algorithm).decode('utf-8')

    # If blacklisting is enabled and configured to store access and refresh tokens,
    # add this token to the store
    blacklist_enabled = get_blacklist_enabled()
    if blacklist_enabled and get_blacklist_checks() == 'all':
        store_token(token_data, revoked=False)
    return encoded_token
コード例 #6
0
def set_refresh_cookies(response, encoded_refresh_token):
    """
    Takes a flask response object, and configures it to set the encoded refresh
    token in a cookie (as well as a csrf refresh cookie if enabled)
    """
    # Set the refresh JWT in the cookie
    response.set_cookie(get_refresh_cookie_name(),
                        value=encoded_refresh_token,
                        secure=get_cookie_secure(),
                        httponly=True,
                        path=get_refresh_cookie_path())

    # If enabled, set the csrf double submit refresh cookie
    if get_cookie_csrf_protect():
        response.set_cookie(get_refresh_csrf_cookie_name(),
                            value=_get_csrf_token(encoded_refresh_token),
                            secure=get_cookie_secure(),
                            httponly=False,
                            path='/')
コード例 #7
0
def _decode_jwt_from_cookies(type):
    if type == 'access':
        cookie_key = get_access_cookie_name()
    else:
        cookie_key = get_refresh_cookie_name()

    token = request.cookies.get(cookie_key)
    if not token:
        raise NoAuthorizationError('Missing cookie "{}"'.format(cookie_key))
    secret = _get_secret_key()
    algorithm = get_algorithm()
    token = _decode_jwt(token, secret, algorithm)

    if get_cookie_csrf_protect():
        csrf_header_key = get_csrf_header_name()
        csrf = request.headers.get(csrf_header_key, None)
        if not csrf or not safe_str_cmp(csrf, token['csrf']):
            raise NoAuthorizationError(
                "Missing or invalid csrf double submit header")

    return token
コード例 #8
0
    def test_default_configs(self):
        with self.app.test_request_context():
            self.assertEqual(get_token_location(), 'headers')
            self.assertEqual(get_jwt_header_name(), 'Authorization')
            self.assertEqual(get_jwt_header_type(), 'Bearer')

            self.assertEqual(get_cookie_secure(), False)
            self.assertEqual(get_access_cookie_name(), 'access_token_cookie')
            self.assertEqual(get_refresh_cookie_name(), 'refresh_token_cookie')
            self.assertEqual(get_access_cookie_path(), None)
            self.assertEqual(get_refresh_cookie_path(), None)
            self.assertEqual(get_cookie_csrf_protect(), True)
            self.assertEqual(get_access_csrf_cookie_name(),
                             'csrf_access_token')
            self.assertEqual(get_refresh_csrf_cookie_name(),
                             'csrf_refresh_token')
            self.assertEqual(get_csrf_header_name(), 'X-CSRF-TOKEN')

            self.assertEqual(get_access_expires(), timedelta(minutes=15))
            self.assertEqual(get_refresh_expires(), timedelta(days=30))
            self.assertEqual(get_algorithm(), 'HS256')
            self.assertEqual(get_blacklist_enabled(), False)
            self.assertEqual(get_blacklist_store(), None)
            self.assertEqual(get_blacklist_checks(), 'refresh')