Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic Group Authentication Support for Custom Queries #2761

Open
2 tasks
ryanchuleff opened this issue Aug 12, 2024 · 0 comments
Open
2 tasks

Dynamic Group Authentication Support for Custom Queries #2761

ryanchuleff opened this issue Aug 12, 2024 · 0 comments
Labels

Comments

@ryanchuleff
Copy link

Describe the feature you'd like to request

I'm building a multi-tenant application with Gen2. Each of my models has a tenantId attribute on it, and each user belongs to a Group in Cognito with that tenantId name. (I'm using Postgres for my database).

    models.User.authorization((allow) => [
      allow.groupDefinedIn('tenantId'),
    ]),

This works great and ensures that the tenancy is enforced without any work on the client side and allows me to easily ensure my queries don't leak data from other tenants.

Now I need to add some custom queries. I wrote a stored procedure in postgres to let me do a fuzzy search for users by multiple attributes, so I want to run the following:

    searchUsers: a.query()
      .arguments({
        lookup: a.string().required()
      })
      .returns(a.ref("user").array())
      .handler(a.handler.inlineSql(
        `SELECT * FROM public.search_user(:lookup);`
    )).authorization(allow => allow.authenticated()),

But here, the groupDefinedIn method is not supported, so the best I can do is authenticated(). This means that my tenancy is not enforced without passing in the tenantId from the client which can be easily modified (not secure).

Amplify doesn't pass the Cognito auth context to the database either, so I can't modify my stored procedure to use something like WHERE tenant_id = current_setting['appsync.identity_claims_custom_tenantId'].

The workaround for now is to move all of this to a custom Lambda function and manage it all manually, but that means losing out on the super simple way of handling custom queries in Gen 2.

Describe the solution you'd like

There are two possible solutions here:

  1. the preferred approach would be to allow custom queries to support the groupDefinedIn() method. This would let me treat my custom queries the same way I handle the rest of my models and their associated queries.

  2. alternatively, if the auth context were to be passed to the database, then I could write my own enforcement logic into the database itself using row level security or WHERE clauses. This isn't as elegant, but would still solve the problem.

Describe alternatives you've considered

Right now, I'm writing a Lambda function using the postgres library and writing my custom queries within that. This requires me to rebuild all the connection/auth logic again (that I would otherwise get for free from the data layer). It also introduces another function that only gets called periodically meaning I have to contend with more cold starts affecting response time back to the client.

Additional context

While I'm not certain of the decision making to not include support for groupDefinedIn() for custom queries, the only risk that I see would be if the query does not return the column identified in groupDefinedIn which should result in an error or automatic unauthorized rather than allowing it to pass through freely.

Is this something that you'd be interested in working on?

  • 👋 I may be able to implement this feature request

Would this feature include a breaking change?

  • ⚠️ This feature might incur a breaking change
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants