Error deploying with blueprint authorizer
Hello,
We are specifying an authorizer on a blueprint and on deploy we receive the following error:
chalice/deploy/swagger.py", line 86, in _generate_security_from_auth_obj 'name': auth_config.header, AttributeError: 'NoneType' object has no attribute 'header'
Still investigating the issue so will provide more info or a PR later. Just wanted to fill the issue in case I forget.
Thanks.
Found the issue. Seems you can use an authorizer declared on a different blueprint.
How would it be possible to create a global authorizer that can be used in all blueprints?
I would just create a module for storing your authorizer in chalicelib/authorizers.py and then import the authorizer as necessary into your blueprint modules.
Yes. This is what ive done but this will create 2 authorizer lambdas. An idea would be to have a parent authorizer (app or blueprint level) and have child route declare or inherit it.
I see what you mean now -- we can't distribute the authorizer from a blueprint for whatever reason. It needs to be top-level. But how to pass top-level authorizers to blueprint modules in chalicelib? Here's one hacky approach for passing app-level authorizer to blueprint routes.
# app.py
from chalice import Chalice, AuthResponse
from chalicelib.extra import ExtraRoutes
app = Chalice(app_name='auth-example')
@app.authorizer()
def demo_auth(auth_request):
token = auth_request.token
# This is just for demo purposes as shown in the API Gateway docs.
# Normally you'd call an oauth provider, validate the
# jwt token, etc.
# In this exampe, the token is treated as the status for demo
# purposes.
if token == 'allow':
return AuthResponse(routes=['/','/demo-auth','/extra'], principal_id='user')
else:
# By specifying an empty list of routes,
# we're saying this user is not authorized
# for any URLs, which will result in an
# Unauthorized response.
return AuthResponse(routes=[], principal_id='user')
extra_routes = ExtraRoutes(demo_auth)
app.register_blueprint(extra_routes.handler)
@app.route('/')
def index():
return {'hello': 'world'}
@app.route('/demo-auth', methods=['GET'], authorizer=demo_auth)
def authenticated():
return {"success": True}
# chalicelib/extra.py
from chalice import Blueprint
class ExtraRoutes:
def __init__(self, auth=None):
self.handler = Blueprint(__name__)
@self.handler.route('/extra', methods=['GET'], authorizer=auth)
def foo():
return {'foo': 'bar'}
Seems to work when I deploy. What do you think @fernandoflorez ?
Seems great. It would be great to have an extra param on the blueprint registration to allow it to pass an authorizer which of course could be overriden by an authorizer on a blueprint level.
Thoughts?
Yeah that would be nice to have. I don't see a way to easily change the blueprint registration call with workarounds. Seems like something you'd need to make a feature request for and/or update the code base to do.
Separately I think you might have found a bug with the authorizer/blueprint interaction and so having a reproducible example and a bug issue to track it with would be helpful.
Yes. Lets see if the administators/community have any thoughts on this so a PR can be filled.
Thanks!
I work around that i found was registering all the authorizers in app.py.
@Ankushpandey-ti could you describe in further detail what the workaround is
I faced the same issue and this is my workaround. Not sure if it's correct but it works.
# app.py
from chalice import Chalice
from chalicelib.authorizers import authorizers
from chalicelib.blueprints import extra_routes
app = Chalice(app_name="my-api")
app.register_blueprint(authorizers)
app.register_blueprint(extra_routes)
# chalicelib/authorizers.py
from chalice import Blueprint
authorizers = Blueprint(__name__)
@authorizers.authorizer()
def some_auth(auth_request):
pass
# chalicelib/blueprints.py
from .authorizers import some_auth
extra_routes = Blueprint(__name__)
@extra_routes.route("/test", authorizer=some_auth)
def test():
return {"hello": "world"}