chalice icon indicating copy to clipboard operation
chalice copied to clipboard

Error deploying with blueprint authorizer

Open fernandoflorez opened this issue 4 years ago • 10 comments

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.

fernandoflorez avatar Jun 18 '21 15:06 fernandoflorez

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?

fernandoflorez avatar Jun 18 '21 15:06 fernandoflorez

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.

areeves87 avatar Jun 19 '21 23:06 areeves87

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.

fernandoflorez avatar Jun 20 '21 13:06 fernandoflorez

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 ?

areeves87 avatar Jun 20 '21 18:06 areeves87

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?

fernandoflorez avatar Jun 20 '21 22:06 fernandoflorez

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.

areeves87 avatar Jun 21 '21 14:06 areeves87

Yes. Lets see if the administators/community have any thoughts on this so a PR can be filled.

Thanks!

fernandoflorez avatar Jun 21 '21 15:06 fernandoflorez

I work around that i found was registering all the authorizers in app.py.

Ankushpandey-ti avatar May 17 '23 23:05 Ankushpandey-ti

@Ankushpandey-ti could you describe in further detail what the workaround is

akhil-arun avatar Jan 23 '24 05:01 akhil-arun

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"}

kutakieu avatar Feb 09 '24 06:02 kutakieu