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()
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
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
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
def _decode_jwt_from_request(type): token_locations = get_token_location() # JWT can be in either headers or cookies if 'headers' in token_locations and 'cookies' in token_locations: try: return _decode_jwt_from_headers() except NoAuthorizationError: pass try: return _decode_jwt_from_cookies(type) except NoAuthorizationError: pass raise NoAuthorizationError("Missing JWT in header and cookies") # JWT can only be in headers elif 'headers' in token_locations: return _decode_jwt_from_headers() # JWT can only be in cookie else: return _decode_jwt_from_cookies(type)
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')
def _decode_jwt_from_request(type): token_location = get_token_location() if token_location == 'headers': return _decode_jwt_from_headers() else: return _decode_jwt_from_cookies(type)