aws / chalice

Python Serverless Microframework for AWS
Apache License 2.0
10.65k stars 1.01k forks source link

Cognito Authorizer and User Groups #783

Open mlecoq opened 6 years ago

mlecoq commented 6 years ago

Hi,

I need to control access to my api with user groups : in the same user pool, users belong to different groups and have access to different parts (pages) of the same app. I also have the case where some users have access to 2 apps but others only one.

Cognito Authorizer only check if user belongs to cognito user pool. It would be great if I could precise user groups (or attributed roles). CustomAuthorizer may be a solution but It requires to rewrite jwt checks.

Thanks !

kgutwin commented 6 years ago

You should be able to do this by checking the request context within your method.

from chalice import Chalice, CognitoUserPoolAuthorizer, ForbiddenError

app = Chalice(app_name='access-check')

@app.route('/')
def index():
    return "anyone can access"

cognito = CognitoUserPoolAuthorizer(
    'access-check', header='Authorization', provider_arns=['arn:aws:...'])

def must_be_in_group(group, request):
    groups = request.context['authorizer']['claims'].get('cognito:groups', '')
    groups = groups.split(',')
    if group not in groups:
         raise ForbiddenError("user must be in the {} group".format(group))

@app.route('/users', authorizer=cognito)
def user_list():
    must_be_in_group('admins', app.current_request)
    return "Only admins can access this page"
mlecoq commented 6 years ago

Yes I have made a decorator which decodes the jwt and then checks if given group as parameter match with existing groups in jwt.

Thanks

mlecoq commented 6 years ago

@kgutwin I have no authorizer in the context of my request

Here are the data I have {'httpMethod': 'GET', 'resourcePath': '/farm/...', 'identity': {'sourceIp': '127.0.0.1'}}

mlecoq commented 6 years ago

There is no authorizer in local mode 😅

stealthycoin commented 6 years ago

The ChaliceAuthorizer does work in local mode. But the rest do not at the moment. I'll mark this as an enhancement for Local mode.

mlecoq commented 6 years ago

It will be great - for the moment I support both cases : reading directly jwt for local mode or using authorizer for production mode

kucharzyk-sebastian commented 3 years ago

Hi,

Is there any better workaround in 2020 than checking for app.current_request.context['authorizer']? Manual disabling authorization for local mode is a bit troublesome and effectively handicaps testing.

m1stermanager commented 2 years ago

if i'm understanding this properly......

extracting any claims, including subscriber.... will not function during local development, even if I do supply a token? I can't really validate any refresh token flows etc because all requests will be authorized, but I also can't just extract some basic info from the token w/ handrolling some jwt parsing logic?

m1stermanager commented 2 years ago

ok, apparently I need to send the identity token to the cognito authorizer, not the access token.