aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.41k stars 2.11k forks source link

Way to pass IAM credentials to AWS Amplify on the server #11581

Open ghost opened 1 year ago

ghost commented 1 year ago

Is this related to a new or existing framework?

Next.js

Is this related to a new or existing API?

GraphQL API

Is this related to another service?

AppSync

Describe the feature you'd like to request

The amplify GraphQL API allows for passing different values of provider to the @auth directive including iam and API. For my use case, I need a way to make sure that only my server is able to make changes to a specific model in the schema so I was considering setting the @auth directive on the model with a provider value of iam and allow to private.

I am new to the AWS way of doing things, but I expected this kind of use case to be so common that there must be a recommended and documented way to go about it, but I couldn't find any, including in the docs.

I created this issue in the Amplify docs repo, but got no response since almost two days now. I created multiple threads in the Amplify Discord server about it but also got no response. I just want a way to make sure that clients can't access the model and my server can. And by the way, I don't want to create a lambda function. I am using Nextjs so I want to use API routes to handle all of the writing to the model that's supposed to happen on the server. So, I may just store the credentials as private environment variables and pass them where necessary.

I came across #10254 and #3116 which were both about amplify not providing a way to directly be supplied hydration credentials especially in the case where IAM Auth is supposed to be used to access the AppSync API. I'm kinda confused about what exactly to do at the moment, so I'll also like a few questions.

Other services typically use API keys for authentication to get server access to resources, so I believe AWS is doing something differently here.

Describe the solution you'd like

A way to supply credentials to be used for authentication when setting authMode to AWS_IAM or API. It's not cool in any way to have to install a bunch of base AWS sdks just to pass IAM credentials as done here.

Describe alternatives you've considered

I was considering manually installing and signing requests as done here https://docs.amplify.aws/guides/functions/graphql-from-lambda/q/platform/js/#iam-authorization.

I was also considering the approaches in the two issues mentioned above.

Additional context

No response

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

manueliglesias commented 1 year ago

Hi @abdulramonjemil ,

At the moment this "machine-to-machine" authentication pattern is not possible with the Amplify JS GraphQL client, for now the workaround is to do the http call + sigv4 signing yourself as shown on the docs you linked.

Another option (not recommended) is to use provider: apiKey and make sure that the API key is not used elsewhere AND that it is removed from the generated aws-exports.js file so it is not included in the app bundle (this file gets regenerated automatically in scenarios like a amplify push).

The team is taking a feature request for this to simplify in the future.

ghost commented 1 year ago

Thanks @manueliglesias. I'll really love to answer each of the questions above. I'm trying to fully wrap my head around how aws amplify works, so that'll go a long way. There are also a few more I'd like to ask. There are things I'm still not sure about.

ghost commented 1 year ago

I just want to get a clearer view of things, since a lot of things have been abstracted which is a good thing, but can also make development tough at times

ghost commented 1 year ago

Finally, I'll also like to know the difference between when I set allow: public and allow: private when provider is IAM. How do these two differ in terms of how I authenticate?

ganesh-rao commented 7 months ago

Hi @manueliglesias @chrisbonifacio - has there been any progress on this topic?

I'm currently trying to use the Amplify JS GraphQL client in a backend-only app with "{ allow: public, operations: [create, read, update, delete], provider: apiKey }" in my schema.graphql file. The apiKey is kept secure and isn't reused elsewhere (the client-side app uses userPools only). Do you see any downside in this setup?

Additionally, using the above configuration, while creating a new record in the database, is there a way to manually set the record's owner in the same query using the Amplify JS GraphQL client? In essence, I want this Lambda function process to create a new database entry, but the entry needs to be owned by a specific user in Cognito.

Thanks for your help. G

gpavlov2016 commented 3 months ago

I recently came up with a problem requiring a similar solution and realized that this is a very common use case for SaaS applications. Consider for example any payment transaction that the user of the app makes and in exchange he is supposed to get some kind of access to the application which is indicated in the database as a value or a flag. In the classical client-server model, we would address it by implementing the transaction processing on the server with only the server having access to the relevant DB fields/mutations. With Amplify, the server doesn't have a separate identity to authorize privileged access to the data and instead uses the user's auth tokens to access the data on behalf of the user. In this case, if access to the user is given to write the privileged field, they can execute the transaction without paying from the client side. If access is not given to the user, how can the server modify the privileged field? Is there any workaround to implement this use case?