def get_app() -> API: auth_backend = JWTAuthBackend(user_loader, SECRET, algorithm="HS256", leeway=30) auth_middleware = FalconAuthMiddleware( auth_backend, exempt_routes=["/auth", "/register"], exempt_methods=["HEAD", "OPTIONS"], ) _app = falcon.API(middleware=[ Marshmallow(), auth_middleware, ] # middleware=[auth_middleware] - add to enable jwt authentication ) _app.add_route("/decoder", JWTDecoder()) _app.add_route("/auth", JWTIssuer()) _app.add_route("/item/{name}", Item()) _app.add_route("/items", ItemList()) _app.add_route("/register", UserRegister()) _app.add_route("/store/{name}", Store()) _app.add_route("/stores", StoreList()) return _app
def test_right_expired_refresh_token_post(client, john_snow): auth_backend = JWTAuthBackend(get_authenticated_user, settings.SECRET_KEY, expiration_delta=0) uid = john_snow.id with scoped_session() as session: refresh_token = session.query(RefreshToken).filter(RefreshToken.user_id == uid).first().token token = auth_backend.get_auth_token(TokenPayloadSchema().dump(john_snow).data) decoded = jwt.decode(token, key=settings.SECRET_KEY, algorithms='HS256') assert decoded is not None and 'exp' in decoded time.sleep(1) assert decoded['exp'] < int(time.time()) response = client.simulate_post( '/auth/refresh_token', headers={ 'authorization': 'jwt %s' % token }, body=json.dumps({ 'refresh_token': refresh_token }) ) assert response.status == falcon.HTTP_200 assert response.json['token'] != token
def get_auth_middleware(secret_key=None, key_file=None): if type(key_file) is str: secret_key = get_auth_key(key_file) elif not type(secret_key) is str: raise TypeError('type of secret_key or key_file must be str') user_loader = lambda payload: payload['user_id'] jwt_auth_backend = JWTAuthBackend( user_loader, secret_key, required_claims=['user_id'], auth_header_prefix='Bearer') auth_middleware = NeuroseedAuthMiddleware(jwt_auth_backend) return auth_middleware
def __init__(self): self.redis_account = redis.StrictRedis.from_url(url=REDIS_URL, db=7, charset="utf-8", decode_responses=True) self.redis_auth = redis.StrictRedis.from_url(url=REDIS_URL, db=6, charset="utf-8", decode_responses=True) try: self._secret_key = os.environ['ANNOUNCEMENTS_SECRET_KEY'] except KeyError: if self.redis_auth.exists('secret_key'): self._secret_key = self.redis_auth.get('secret_key') else: self.redis_auth.set('secret_key', secrets.token_hex()) self._secret_key = self.redis_auth.get('secret_key') self.jwt_auth = JWTAuthBackend(self.jwt_user_loader, secret_key=self._secret_key, auth_header_prefix='Bearer', leeway=60, expiration_delta=JWT_EXPIRE_TIME) self.auth_middleware = FalconAuthMiddleware(self.jwt_auth)
def __init__(self, sql_conn: sqlite3.Connection, data_path: str, **kwargs): users_resource = UsersResource(sql_conn, data_path) auth_backend = JWTAuthBackend(users_resource.validate_claims, JWT_KEY, required_claims=['exp', 'selected_campaign', 'email']) auth_middleware = FalconAuthMiddleware(auth_backend, exempt_routes=['/users', '/login', '/captcha'], exempt_methods=['HEAD', 'OPTIONS']) super().__init__(middleware=[auth_middleware], **kwargs) auth_resource = Login(sql_conn, data_path) profile_resource = Profile(sql_conn, data_path) captcha_resource = Captcha(sql_conn, data_path) characters_resource = Characters(sql_conn, data_path) character_resource = Character(sql_conn, data_path) factions_resource = Factions(sql_conn, data_path) faction_resource = Faction(sql_conn, data_path) places_resource = Places(sql_conn, data_path) place_resource = Place(sql_conn, data_path) things_resource = Things(sql_conn, data_path) thing_resource = Thing(sql_conn, data_path) entries_resource = ChronicleEntries(sql_conn, data_path) entry_resource = ChronicleEntry(sql_conn, data_path) char_rels_resource = CharacterRelations(sql_conn, data_path) char_rel_resource = CharacterRelation(sql_conn, data_path) faction_rels_resource = FactionRelations(sql_conn, data_path) self.add_route("/users/", users_resource) self.add_route("/login", auth_resource) self.add_route("/profile", profile_resource) self.add_route("/profile/{profile_id}", profile_resource) self.add_route("/profile/campaigns/{campaign_id}", profile_resource) self.add_route("/captcha/", captcha_resource) self.add_route("/characters/", characters_resource) self.add_route("/characters/{character_id}", character_resource) self.add_route("/factions/", factions_resource) self.add_route("/factions/{faction_id}", faction_resource) self.add_route("/places/", places_resource) self.add_route("/places/{place_id}", place_resource) self.add_route("/things/", things_resource) self.add_route("/things/{thing_id}", thing_resource) self.add_route("/chronicle/", entries_resource) self.add_route("/chronicle/{entry_id}", entry_resource) self.add_route("/characters/{character_id}/relations/{relation_type}", char_rels_resource) self.add_route("/characters/{character_id}/relations/{relation_type}/{relation_id}", char_rel_resource) self.add_route("/factions/{faction_id}/relations/{relation_type}", faction_rels_resource) self.add_route("/{relation_type}/{relation_id}/relations/characters/{character_id}", char_rel_resource)
class AuthService: _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance def __init__(self): self.redis_account = redis.StrictRedis.from_url(url=REDIS_URL, db=7, charset="utf-8", decode_responses=True) self.redis_auth = redis.StrictRedis.from_url(url=REDIS_URL, db=6, charset="utf-8", decode_responses=True) try: self._secret_key = os.environ['ANNOUNCEMENTS_SECRET_KEY'] except KeyError: if self.redis_auth.exists('secret_key'): self._secret_key = self.redis_auth.get('secret_key') else: self.redis_auth.set('secret_key', secrets.token_hex()) self._secret_key = self.redis_auth.get('secret_key') self.jwt_auth = JWTAuthBackend(self.jwt_user_loader, secret_key=self._secret_key, auth_header_prefix='Bearer', leeway=60, expiration_delta=JWT_EXPIRE_TIME) self.auth_middleware = FalconAuthMiddleware(self.jwt_auth) def register(self, username: str, password: str) -> bool: """Very basic user register function. Args: username (str): username. password (str): password, support sha-256 length. Raises: falcon.HTTPUnauthorized: username too long. falcon.HTTPUnauthorized: password length error. (support sha-256 length) falcon.HTTPUnauthorized: already register. Returns: bool: True, success register. """ if len(username) < 8 or len(username) > 64: raise falcon.HTTPUnauthorized(description="username length error") if username.find("@") > -1: raise falcon.HTTPUnauthorized( description="Normal register can't use mail username.") if len(password) < 50 or len(password) > 80: raise falcon.HTTPUnauthorized(description="password length error") if self.redis_account.exists(username): raise falcon.HTTPUnauthorized(description="already register") if self.is_banned(username): raise falcon.HTTPForbidden( title="banned", description= "Your account is banned, any question please ask Facebook fan page." ) s = hashlib.sha256() s.update(password.encode('utf-8')) _password = s.hexdigest() data = {'username': username, 'password': _password} user_data = json.dumps(data) self.redis_account.set(name=username, value=user_data) return True def login(self, username: str, password: str, fcm_token=None) -> str: """basic login function Args: username (str): username password (str): password Raises: falcon.HTTPUnauthorized: 401, username or password error Returns: str: jwt payload. JWT_Payload: { username permission_level } permission_level: - 0 is user - 1 is editor/reviewer - 2 is admin """ if self.redis_account.exists(username): user_data = json.loads(self.redis_account.get(username)) s = hashlib.sha256() s.update(password.encode('utf-8')) _password = s.hexdigest() if self.is_banned(username): raise falcon.HTTPForbidden( title="banned", description= "Your account is banned, any question please ask Facebook fan page." ) if user_data['password'] == _password: _user_level = 0 if username in ADMIN: _user_level = 2 elif username in self.get_editor_list(): _user_level = 1 jwt_string = self.jwt_auth.get_auth_token( user_payload={ "username": username, "login_type": "General", "permission_level": _user_level, "fcm": fcm_token }) return jwt_string raise falcon.HTTPUnauthorized() def get_editor_list(self) -> list: if self.redis_auth.exists("editor"): return json.loads(self.redis_auth.get('editor')) self.redis_auth.set(name='editor', value="[]") return [] def is_banned(self, username: str) -> bool: """is user banned ? Args: username (str): username Returns: bool: True is banned, False is not. """ banned_list = self.get_banned_list() try: banned_list.index(username) except ValueError: return False return True def get_banned_list(self) -> list: if self.redis_auth.exists("banned"): return json.loads(self.redis_auth.get('banned')) self.redis_auth.set(name='banned', value="[]") return [] def ban_user(self, username: str) -> bool: banned_list = self.get_banned_list() banned_list.append(username) self.redis_auth.set(name='banned', value=json.dumps(list(set(banned_list)))) return True def remove_banned(self, username: str) -> bool: banned_list = self.get_banned_list() try: banned_list.remove(username) except ValueError: return False self.redis_auth.set(name='banned', value=json.dumps(list(set(banned_list)))) return True def add_editor(self, username: str) -> bool: # if not self.redis_account.exists(username): # raise falcon.HTTPNotAcceptable( # description="This user isn't register") if username in self.get_editor_list(): raise falcon.HTTPNotAcceptable( description="user already is editor") if not self.redis_auth.exists("editor"): editor_list = [username] self.redis_auth.set(name='editor', value=json.dumps(editor_list)) return True editor_list = self.get_editor_list() editor_list.append(username) self.redis_auth.set(name='editor', value=json.dumps(editor_list)) return True def remove_editor(self, username: str) -> bool: if not self.redis_account.exists(username): raise falcon.HTTPNotAcceptable( description="This user isn't register") editor_list = self.get_editor_list() try: editor_list.remove(username) except ValueError: raise falcon.HTTPNotAcceptable( description="This user not in editor") self.redis_auth.set(name='editor', value=json.dumps(editor_list)) return True def jwt_user_loader(self, client_submitted_jwt: dict) -> dict: """can make basic check in this function. Args: client_submitted_jwt ([dict]): after decode by JWT Returns: [dict]: after check raw_data """ if self.is_banned( client_submitted_jwt.get("user", {}).get("username", "")): raise falcon.HTTPForbidden( title="banned", description= "Your account is banned, any question please ask Facebook fan page." ) return client_submitted_jwt def google_oauth_login(self, code: str, fcm_token=None) -> str: user_info_by_google = google_sign_in(code=code) if user_info_by_google.get("verified_email", False) == False: falcon.HTTPForbidden("Your email need verified.") user_mail = user_info_by_google.get('email', False) if user_mail is False: falcon.HTTPServiceUnavailable( description="Get user email error :(") user_mail = user_mail.lower() if APPLICANT_HOSTNAME_LIMIT != [] and user_mail not in self.get_editor_list( ): user_mail_parse = address.parse(user_mail, addr_spec_only=True) if user_mail_parse is not None: if isinstance(user_mail_parse, address.EmailAddress) and \ user_mail_parse.hostname not in APPLICANT_HOSTNAME_LIMIT: raise falcon.HTTPForbidden( title="mail organization not allow") if self.is_banned(user_mail): raise falcon.HTTPForbidden( title="banned", description= "Your account is banned, any question please ask Facebook fan page." ) _user_level = 0 if user_mail in ADMIN: _user_level = 2 elif user_mail in self.get_editor_list(): _user_level = 1 jwt_string = self.jwt_auth.get_auth_token( user_payload={ "username": user_mail, "login_type": "Oauth2", "permission_level": _user_level, "fcm": fcm_token }) return jwt_string def google_oauth_login_by_id_token(self, id_token: str, fcm_token=None) -> str: user_info_by_google = get_user_profile_from_id_token(id_token=id_token) if user_info_by_google.get("verified_email", False) == False: falcon.HTTPForbidden("Your email need verified.") user_mail = user_info_by_google.get('email', False) if user_mail is False: falcon.HTTPServiceUnavailable( description="Get user email error :(") user_mail = user_mail.lower() if APPLICANT_HOSTNAME_LIMIT != [] and user_mail not in self.get_editor_list( ): user_mail_parse = address.parse(user_mail, addr_spec_only=True) if user_mail_parse is not None: if isinstance(user_mail_parse, address.EmailAddress) and \ user_mail_parse.hostname not in APPLICANT_HOSTNAME_LIMIT: raise falcon.HTTPForbidden( title="mail organization not allow") if self.is_banned(user_mail): raise falcon.HTTPForbidden( title="banned", description= "Your account is banned, any question please ask Facebook fan page." ) _user_level = 0 if user_mail in ADMIN: _user_level = 2 elif user_mail in self.get_editor_list(): _user_level = 1 jwt_string = self.jwt_auth.get_auth_token( user_payload={ "username": user_mail, "login_type": "Oauth2", "permission_level": _user_level, "fcm": fcm_token }) return jwt_string def apple_sign_in_by_id_token(self, id_token: str, bundle_id=None, fcm_token=None) -> str: jwt_payload = apple_verify_id_token(id_token=id_token, bundle_id=bundle_id) if jwt_payload.get("email", False) == False: falcon.HTTPServiceUnavailable( description="Get user email error :(") user_mail = jwt_payload.get("email", "").lower() print(user_mail) if APPLICANT_HOSTNAME_LIMIT != [] and user_mail not in self.get_editor_list( ): user_mail_parse = address.parse(user_mail, addr_spec_only=True) if user_mail_parse is not None: if isinstance(user_mail_parse, address.EmailAddress) and \ user_mail_parse.hostname not in APPLICANT_HOSTNAME_LIMIT: raise falcon.HTTPForbidden( title="mail organization not allow") if self.is_banned(user_mail): raise falcon.HTTPForbidden( title="banned", description= "Your account is banned, any question please ask Facebook fan page." ) _user_level = 0 if user_mail in ADMIN: _user_level = 2 elif user_mail in self.get_editor_list(): _user_level = 1 jwt_string = self.jwt_auth.get_auth_token( user_payload={ "username": user_mail, "login_type": "Apple_sign_in", "permission_level": _user_level, "fcm": fcm_token }) return jwt_string
allow_credentials_all_origins=True, ) stats_middleware = FalconStatsMiddleware() # Allow requiring authentication via JWT if config["bel_api"]["authenticated"]: # Loads user data from JWT def user_loader(payload): # log.info(payload) return True auth_backend = JWTAuthBackend( user_loader=user_loader, secret_key=config["secrets"]["bel_api"]["shared_secret"], required_claims=["exp", "iat"], ) auth_middleware = FalconAuthMiddleware( auth_backend, exempt_routes=["/simple_status", "/healthcheck", "/version"], exempt_methods=["HEAD"], ) app = application = falcon.API(middleware=[stats_middleware, auth_middleware, cors.middleware]) else: app = application = falcon.API(middleware=[stats_middleware, cors.middleware]) # Add exception handling middleware.falcon_exceptions.register_defaults(app)
#!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2018/12/6 @author: shimakaze-git ''' import json import falcon from auth import user_loader, SECRET_KEY, ExampleUser from falcon_auth import FalconAuthMiddleware, JWTAuthBackend API_ENDPOINT = "/api" auth_backend = JWTAuthBackend(user_loader, SECRET_KEY) auth_middleware = FalconAuthMiddleware(auth_backend, exempt_routes=None, exempt_methods=None) app = falcon.API(middleware=[auth_middleware]) class TokenAuth: auth = { 'auth_disabled': True, # 'exempt_methods': ['POST'] } def on_post(self, req, resp, **params): body = req.stream.read()
return user.level = level self.session.add(user) self.session.commit() resp.media = result('success') except NoResultFound: resp.media = error('no such user') ### END ### def jwt_loader(data): return data user_loader = jwt_loader auth_backend = JWTAuthBackend(user_loader, secret_key = SECRET_KEY, required_claims=['exp']) auth_middleware = FalconAuthMiddleware(auth_backend, exempt_routes=[ '/user/token', '/user/signup', ]) ### CORS CONFIG ### cors = CORS(allow_all_origins=True, allow_all_headers=True, allow_all_methods=True) ### END ### api = falcon.API(middleware=[cors.middleware, auth_middleware, SQLAlchemySessionManager(Session)]) ### USER Router ### api.add_route('/user/token', UserSignInResource()) # POST api.add_route('/user/signup', UserSignUpResource()) # POST
# Setup Middlewares for Falcon API from falcon_auth import FalconAuthMiddleware, JWTAuthBackend from app.controllers.cred_checker import cred_checker from app.settings import ( jwt_secret_key, jwt_algorithm, jwt_auth_header_prefix, jwt_leeway, jwt_expiration_delta ) # Setup falcon-auth JWT Authentication based Middleware jwt_auth = JWTAuthBackend( user_loader=cred_checker, secret_key=jwt_secret_key, algorithm=jwt_algorithm, auth_header_prefix=jwt_auth_header_prefix, leeway=jwt_leeway, expiration_delta=jwt_expiration_delta, ) middleware = [ FalconAuthMiddleware(jwt_auth) ]
else: # generate key and save to redis SECRET_KEY = util.randStr(32) red_auth.set('secret_key', SECRET_KEY) def user_loader(client_submitted_jwt): """can make basic check in this function. Args: client_submitted_jwt ([dict]): after decode by JWT Returns: [dict]: after check raw_data """ redis_token_name = "{username}_{token}".format( username=client_submitted_jwt['user']['username'], token=client_submitted_jwt['user']['token']) if red_auth_token.exists(redis_token_name): return client_submitted_jwt return False jwt_auth = JWTAuthBackend(user_loader, secret_key=SECRET_KEY, auth_header_prefix='Bearer', leeway=60, expiration_delta=JWT_EXPIRE_TIME) auth_middleware = FalconAuthMiddleware(jwt_auth)
allow_all_headers=True, allow_credentials_all_origins=True) stats_middleware = FalconStatsMiddleware() # Allow requiring authentication via JWT if config['bel_api']['authenticated']: # Loads user data from JWT def user_loader(payload): # log.info(payload) return True auth_backend = JWTAuthBackend( user_loader=user_loader, secret_key=config['secrets']['bel_api']['shared_secret'], required_claims=['exp', 'iat'], ) auth_middleware = FalconAuthMiddleware(auth_backend, exempt_routes=[ '/simple_status', '/healthcheck', '/version', ], exempt_methods=['HEAD']) api = application = falcon.API(middleware=[ stats_middleware, auth_middleware, cors.middleware, ])
# Redis redis_conn = redis.StrictRedis.from_url(REDIS_URI) q: Queue = Queue(connection=redis_conn) # Elasticsearch es = Elasticsearch(ELASTICSEARCH_URI) if ELASTICSEARCH_URI else None # TODO might have to load a different configuration for production, look into # SQLAlchemy db: SQLAlchemy = SQLAlchemy(DATABASE_URI) from app import models # noqa # Authentication from .utilities import user_loader # noqa auth_backend = JWTAuthBackend(user_loader, secret_key=SECRET_KEY) auth_middleware = FalconAuthMiddleware(auth_backend, exempt_routes=["/swagger"]) # Falcon app_middleware = [ auth_middleware, SQLAlchemySessionManager(db), SerializationMiddleware(), ] api = falcon.API(middleware=app_middleware) # Documentation spec = APISpec( title="Movie Recommendation", version="0.0.1",
def get_backend(self) -> JWTAuthBackend: return JWTAuthBackend(user_loader=self.__get_user(), secret_key=self.config.secret, algorithm=self.config.algorithm, required_claims=['exp'])
def create_app(conf_file): """ Main web application. IMPORTANT NOTICE: This application is designed to run under a single process and single thread in WSGI. It will not work properly if multiple processes operate using the same data at once. Parameters ---------- conf_file: String Configuration file in ini format. See file ini/example_eeris.ini for an example. """ # Config file parsing config = configparser.ConfigParser() config.read(conf_file) # Set logging level if 'loglevel' not in config['eeRIS'].keys(): loglevel = logging.DEBUG else: loglevel = eval('logging.' + config['eeRIS']['loglevel']) logging.basicConfig(level=loglevel) # DB connection logging.info("Connecting to database") mclient = pymongo.MongoClient(config['eeRIS']['dburl']) dbname = config['eeRIS']['dbname'] dblist = mclient.list_database_names() if dbname in dblist: mdb = mclient[dbname] else: sys.stderr.write('ERROR: Database ' + dbname + ' not found. Exiting.') return # Authentication auth_backend = JWTAuthBackend(lambda user: user, config['REST']['jwt_psk'], algorithm='HS256', expiration_delta=24 * 60 * 60) auth_middleware = FalconAuthMiddleware(auth_backend, exempt_methods=['HEAD']) # auth_middleware = FalconAuthMiddleware(auth_backend) api = falcon.API(middleware=[auth_middleware]) # api = falcon.API() # NILM logging.info("Setting up connections") nilm = eeris_nilm.nilm.NILM(mdb, config) api.add_route('/nilm/{inst_id}', nilm) api.add_route('/nilm/{inst_id}/clustering', nilm, suffix='clustering') api.add_route('/nilm/{inst_id}/activations', nilm, suffix='activations') api.add_route('/nilm/{inst_id}/recomputation', nilm, suffix='recomputation') api.add_route('/nilm/{inst_id}/start_thread', nilm, suffix='start_thread') api.add_route('/nilm/{inst_id}/stop_thread', nilm, suffix='stop_thread') api.add_route('/nilm/{inst_id}/appliance_name', nilm, suffix='appliance_name') # Installation manager (for database management - limited functionality) # inst_ids = [x.strip() for x in config['eeRIS']['inst_ids'].split(",")] # inst_manager = eeris_nilm.installation.\ # InstallationManager(mdb, inst_list=inst_ids) # api.add_route('/installation/{inst_id}/model', inst_manager, # suffix='model') logging.info("Ready") return api
try: uid = args[0]['user']['id'] user = _users.get(uid) except Exception as e: try: email = args[0]['user']['subject'] user = _users.first(email=email) except Exception as e: console.error(e) raise return user secret_key = os.environ.get('SECRET_KEY') auth_backend = JWTAuthBackend(user_loader, secret_key) auth_middleware = FalconAuthMiddleware(auth_backend, exempt_routes=EXEMPT_ROUTES, exempt_methods=['HEAD']) # Setup CORS cors = CORS(allow_origins_list=[ 'http://localhost:8080', 'http://smpa-frontend-staging.s3-website.eu-west-2.amazonaws.com', 'https://planningapplication.hackney.gov.uk', 'https://planningapplication-staging.hackney.gov.uk' ], allow_all_headers=True, allow_all_methods=True) # Create the Falcon app
"mongodb+srv://guest:[email protected]/fibonacci?retryWrites=true&w=majority" ) def user_loader(payload): print(payload) search_dict = payload['user'] db = client.test col = db.login if col.count_documents(search_dict): return payload['user'] else: return None auth_backend = JWTAuthBackend(user_loader, 'secret') auth_middleware = FalconAuthMiddleware(auth_backend) class SignUp(object): auth = {'auth_disabled': True} def on_post(self, req, resp, username, password): db = client.test col = db.login filtered_dict = {"username": username} if col.count_documents(filtered_dict): resp.body = json.dumps("Already exist") else: db.login.insert_one({ "username": username,
import json import uuid import falcon import jwt as jwt_lib from falcon_auth import JWTAuthBackend from sqlalchemy import or_ import jwtapi.app_db as app_db import jwtapi.env as ENV from jwtapi.app_db import User, find_user # JWT Backends user_loader = lambda token_content: token_content['user'] jwt_auth = JWTAuthBackend(user_loader, ENV.APP_SECRET, expiration_delta=ENV.EXP_ACCESS_TOKEN) refresh_auth = JWTAuthBackend(user_loader, ENV.APP_SECRET, expiration_delta=ENV.EXP_REFRESH_TOKEN) class Login: def on_post(self, req, resp): if req.media is None: resp.body = json.dumps({'status': 'missing username/password'}) resp.status = falcon.HTTP_409 return if any(('username' not in req.media, 'password' not in req.media)): resp.body = json.dumps({'status': 'missing username/password'})
from . import db, resources, settings from falcon_auth import FalconAuthMiddleware, JWTAuthBackend def user_loader(payload: dict): username = payload.get('username') password = payload.get('password') if username == settings.JWT_CONFIG[ 'username'] and password == settings.JWT_CONFIG['password']: # noqa return username else: return None auth_backend = JWTAuthBackend(user_loader, secret_key=settings.JWT_CONFIG['secret_key'], verify_claims=['exp'], required_claims=['exp']) exempt_routes = ['/'] auth_middleware = FalconAuthMiddleware(auth_backend, exempt_routes=exempt_routes, exempt_methods=['HEAD']) app = falcon.API(middleware=[ auth_middleware, db.SQLAlchemySessionManager(db.Session), ], ) app.add_route('/', resources.HomeResource()) app.add_route('/customers', resources.CustomerCollectionResource()) app.add_route('/customers/{customer_id}', resources.CustomerItemResource())