Closed plumdog closed 5 years ago
When building complex authorization use cases (such as ones that traverse multiple models) you have a few options.
1. Use a lambda function.
As of writing you can connect your own functions using custom stacks: https://aws-amplify.github.io/docs/cli/graphql#add-a-custom-resolver-that-targets-an-aws-lambda-function
We have a PR under review that simplifies this process into a @function
directive #1346 that will be available as soon as it is merged.
2. Use pipeline functions.
You can use custom stacks to create AppSync pipeline functions that use multiple DynamoDB calls to authorize the action. For example you could get the thing's section then get the section's project and check if the user is allowed to view the project. If they are return the item, else return false. You can use custom resources to add the pipeline functions such that they are deployed via amplify. Here are the AppSync pipeline resolver docs https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html.
3. Store auth info on the Thing
and use Elasticsearch.
If you store information such as the projectId
on the Thing
then you can use a pipeline resolver & elasticsearch to build authorization on top of rich text search. For example, you could use a field like this:
type Query {
searchThingsInProject(projectId: String!, thingSearchTerm: String!): ThingConnection
}
Where your Query.searchThingsInProject
resolver is a pipeline with two functions.
$ctx.args.projectId
and authorize the user.projectId
in the query body as a term query (https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html). This will restrict only items that belong to this project to be searched and you have already determined that you are authorized for the project.Feel free to comment if this doesn't answer your question
@mikeparisstuff I think I understand the overall approach here - namely that the authorization happens "behind" GraphQL.
However, am I right that in doing so I would lose (or rather, would choose to ignore) the auto-generated resolvers that Amplify generates? I can't add my own function to the "front" of the generated resolver for each endpoint?
To put it another way: all of these approaches replace the resolvers, none of them let me augment the resolvers like @auth
does?
Might my most effective way of doing this be:
This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.
Looking for a help forum? We recommend joining the Amplify Community Discord server *-help
channels for those types of questions.
Which Category is your question related to?
GraphQL, Auth
What AWS Services are you utilizing?
Amplify, (AppSync, Cognito)
Provide additional details e.g. code snippets
I think that my permissions model is beyond what
@auth
can handle. I have, in essence:I need my permissions to be managed by users within the application (eg, an admin user says "you have access on project x and project y"), and on a per-project basis. I think that, in theory, this could work using Cognito groups, but I can't see how to say either:
So my assumption is:
@auth
is unable to handle my current situation (I'm aware #766 may handle this, but as far as I can tell doesn't handle it yet, and doesn't point me towards a solution. Is there I beta I can use?).At any rate: assume I have some fiddly permissions model.
Does this mean Amplify is unable to accommodate my use case? Or is there a workaround? I noticed that https://aws.amazon.com/blogs/mobile/amplify-adds-support-for-multiple-environments-custom-resolvers-larger-data-models-and-iam-roles-including-mfa/ says:
implying that I can implement this kind of custom authorization in resolvers. Is this true? Is this a good idea?
Or can I write some kind of "call this Lambda function to decide if the current user can do the thing they want do do" code in my GraphQL somewhere?
My current inclination is to use GraphQL and
@model
and@searchable
, but to make the GraphQL API totally private and only accessible from a Lambda that handles a REST API. (Eg, the frontend saysGET /myapi/things?search=foo
and my lambda makes some authorization decisions based on your Cognito user and some DynamoDB table rows controlling who can access what, and does some GraphQL at the private GraphQL API for you, eg "search Things matching foo where project in (projects you can access)"). But having to hide my GraphQL from my frontend client feels like it goes against the Amplify model, and makes me a bit sad. Is making my GraphQL API private actually possible with Amplify?Much more generally, I love that Amplify is built with what it refers to as "escape hatches", but the docs haven't really helped me find one here.
Any help about how I might handle fine-grained access control would be appreciated.