Cognito User Group as authorizer

I’m using Cognito to manage my user accounts. One of the features of Cognito is a concept of groups. I would like to segment my users into “customers” and “admins” all within the same pool. Each group would have access to specific API Gateway endpoints backed by lambda functions. I see that you can set the authorizer.arn to a user pool, but I’m not sure how I would specify a user group within a user pool?

2 Likes

I understand your query but can you explain your use case of using groups as opposed to multiple userpools i.e. 1 pool for admins and other for customers.

That is what I ended up doing but it’s kind of a pain to manage because I have to check two different user pools any time I want to do any sort of authentication. It also means that if I want to have different pools per environment, I need to have two per environment instead of just one.

Finally it seems like this is exactly what user groups were meant for, fine grain control over a pool.

Did you try creating 2 different groups with separate roles with limited privileges(i.e. one role with write privileges for admins assigned to ADMINS group and 2nd role with read only policy for users assigned to CUSTOMERS group) within the same userpool? You can also assign precedence in case your users are falling into 2 different groups.

You can refer this link for preparing resources for your service related to cognito user groups:
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolgroup.html

In your serverless.yml file , you can specify only the ARN of UserPool.

Let me know if this works . If not , I will try it over the weekend and update on this thread.

Hi Arb, are you using the provided Cognito User Pool Authorizer? If so this only supports Yes/No access to the API.
Cognito groups only apply if your performing a token (JWT) exchange for SigV4 credentials then any calls to API Gateway or native AWS API’s are performed with the IAM permissions you set for the users group (groups can be switched if a user is a member of more than one)

We built a custom authoriser that looks at the roles within the JWT and builds a policy for the API Gateway by looking up the relevant groups IAM policies and this then allowed us to use the Cog Ito groups/preferred group to control access to our API’s

So Admins could invoke say update and delete where as Users maybe only read and limited updates. I based the Custom Authoriser on the example on GitHub from AWS, But was rewritten in C#.

1 Like

Yes I’m using the provided Cognito User Pool Authorizer. I’m totally fine with yes/no access to the API, I just didn’t want to have to split my users across two user pools to make this work. When I became aware of groups, this seemed like the perfect fit.

I thought about building a custom authorizer but I had an extremely hard time believing no one in the community has ever tried this before?

I’m sure there a some people doing it, but we didn’t find any, maybe like my client, it ends up being their IP and they are not into sharing for what ever reason.

Rumours of a more advanced User Pool authoriser are abound, supporting groups like we built, but to be honest it wasn’t a lot of changes to the example code provided :slight_smile: But you could raise it as a requested feature with AWS.

@arb this may help you https://aws.amazon.com/blogs/mobile/building-fine-grained-authorization-using-amazon-cognito-user-pools-groups/

While you are correct the “the provided Cognito User Pool Authorizer” is only yes/no, you can inspect the claims in the JWT token in either your mapping template $context.authorizer.claims[‘cognito:groups’] ( Integrate a REST API with an Amazon Cognito user pool - Amazon API Gateway ) or a lambda function ( Accessing user claims in lambda with AWS_IAM authorizer. · Issue #320 · amazon-archives/amazon-cognito-identity-js · GitHub ) by and then providing logic based on the result.

FYI

1 Like

I just developed a middleware to manage permissions based on Cognito user’s group: @marcosantonocito/middy-cognito-permission

You can use customAuthorizer to use two groups in one user pool. You just need to create two custom authorizers for admin and customers. You can create the policy for the user types. You can get some idea from this. https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt

The way that we approached this is by defining “AWS::Cognito::UserPoolGroup” groups as part of the resources: block in the serverless YAML. An IAM role is also defined and assigned to this User Pool Group and this has the IAM policies defined for that particular User Pool Group.

We have a bunch of different APIs for our web app functionality, which are defined as separate Serverless YAMLs.

A single Cognito User Pool is used and users within this pool can be assigned to multiple User Pool Groups. For each API we just assigned the User Pool as the authoriser, but for both Access Tokens and ID Tokens you can access the user group claims within them for a user. This means that we just add a simple bit of logic to the lambda function to check whether a user is in the required group and if so adopt the role that is assigned. You can use STS Assume Role for this.

To prevent calling of the API in the first place you can use API keys for this.

I liked this approach because everything can be defined with the YAML template and you can clearly see what permission your Lambda function will have either in the YAML or by looking at the IAM role within AWS.

As an aside I am currently trying to do this on Azure using the Serverless Framework and currently struggling to see how it can be achieved without making separate ARM templates.