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.44k stars 2.13k forks source link

GraphQL auth rules : Datastore & Flutter and NextJS #9290

Closed matthewapps closed 2 years ago

matthewapps commented 2 years ago

Before opening, please confirm:

JavaScript Framework

Not applicable

Amplify APIs

GraphQL API, DataStore

Amplify Categories

auth, storage, api

Environment information

``` # Put output below this line System: OS: macOS 11.6 CPU: (4) x64 Intel(R) Core(TM) i5-4288U CPU @ 2.60GHz Memory: 275.83 MB / 8.00 GB Shell: 5.8 - /bin/zsh Binaries: Node: 14.17.5 - /usr/local/bin/node npm: 8.1.3 - /usr/local/bin/npm Browsers: Chrome: 96.0.4664.55 Firefox: 88.0 Safari: 15.0 npmGlobalPackages: @aws-amplify/cli: 7.5.2 angular-cli: 1.0.0-beta.28.3 browser-sync: 2.23.1 buffer: 5.6.0 cordova: 8.0.0 dezalgo: 1.0.3 inquirer: 7.3.3 ionic: 5.4.16 n: 7.3.1 npm: 8.1.3 typings: 2.1.1 undefined: 0.1.0 ```

Describe the bug

I am trying to set up auth rules for a Flutter app using Datastore but am not getting far. I have a Graphql model for which I want public to have read access and the owner to read, create, update and delete. I expected the following rule to work:

@auth(rules: [{allow: public, operations: [read]}, {allow: public, operations: [read], provider: iam}, {allow: owner}]) In this situation updates to the table don't get synced up to the backend. I am using the standard command to save the data "await Amplify.DataStore.save(item)".

The following rules work: @auth(rules: [{allow: public } ]) @auth(rules: [{allow: public }, {allow: public, provider: iam} ])

The following rules seem to have an effect in that the records are no longer synced down from the backend. I assume this is because the read operation is omitted from the list of owner operations:

@auth(rules: [{allow: public, operations: [read]}, {allow: public, operations: [read], provider: iam}, {allow: owner, operations: [create, update, delete] }]).

Any ideas why this doesn't work as I think it should??

Expected behavior

please see the description above

Reproduction steps

  1. Run amplify update API to included API,IAM and Cognito
  2. Use Amplify console to change the auth rules
  3. run amplify pull to download the graphql updates
  4. run the flutter app

Code Snippet

// Put your code below this line.

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

ios simulator

Mobile Operating System

IOS 13

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

sammartinez commented 2 years ago

@matthewapps Thanks for opening this issue, I do need to understand a couple of things. I am seeing that your issue is specific to Flutter. Are you using amplify-flutter? If so, this issue may fit better on the Amplify Flutter repo. If is not, can you please provide the steps to reproduce this issue following the template when you first cut the issue to us. Thanks ahead of time.

chrisbonifacio commented 2 years ago

@matthewapps I would also share the schema you're working with so we have a full view/context of where and how you're using the auth directives.

If you don't specify an operations field it is assumed that all are allowed, so you don't even need to specify read for the owner if you'd like for them to have full control over a record they've created.

i.e : @auth(rules: [{ allow: owner }])

Also, it's not clear what you mean by "doesn't work as I think it should".

What are you trying to do or expecting to happen and what behavior are you currently observing?

If you can provide screenshots and/or console logs that would help as well

matthewapps commented 2 years ago

@chrisbonifacio and @sammartinez, Thanks for the replies. Here are my answers to your questions

  1. Part of the schema here type Part @model @auth(rules: [{allow: public, operations: [read]}, {allow: public, operations: [read], provider: iam}, {allow: owner}]){ id: ID! make: String carmodel: String Name: String registrationNumber: String ....... ...... Listed: AWSDateTime accountID: ID @index(name: "byAccount") purchasedcarID: ID @index(name: "byPurchasedCar") }
  2. it's not clear what you mean by "doesn't work as I think it should". I want public to have read access and the owner to read, create, update and delete.
  3. what behaviour are you currently observing - In this situation any create/updates by a logged-in user(owner) do not get synced up from the datastore to the backend. I do not see any updates on Dynamodb or Amplify UI when logged in as admin. I was expecting to see them. I do however observe updates to the backend if I change the auth rules to either @auth(rules: [{allow: public } ]) OR @auth(rules: [{allow: public }, {allow: public, provider: iam} ]).

    1. @sammartinez : here is what I listed in the steps to reproduce above - is there anything else I can provide? Reproduction steps
  1. Run amplify update API to include API,IAM and Cognito
  2. Use Amplify ui to change and deploy the auth rules
  3. run amplify pull to download the graphql updates
  4. run the flutter app to create and update the Part table on an IOS simulator
  1. @sammartinez - I am using amplify-flutter but am wondering whether it is a datastore issue, or a graphl issue? Please advise if I should re-allocate it.

Many thanks

chrisbonifacio commented 2 years ago

@matthewapps thank you for providing more information. I'm not experienced with Flutter so I tried to reproduce the issue with a JS project to see if the behavior is not unique to Flutter. I observed that I was able to create/update/delete records locally while signed in (Cognito User Pools) but when I looked at the graphql network calls, they were all unauthorized, so they were not persisting to the server. When I signed out, the calls were still unauthorized because public was limited to read.

This would explain why records seem to persist to the server when you do @auth(rules: [{allow: public } ]), because public is authorized to perform all operations and DataStore will only use the default auth mode (probably API_KEY in your case) unless configured otherwise.

The issue, I believe, is that multi-auth is not enabled for your DataStore configuration. I enabled it for my JS project and the owner auth rules started to work, along with the public auth rules. This documentation should be helpful for Flutter.

matthewapps commented 2 years ago

@chrisbonifacio many thanks Chris for the prompt responses. This explains a lot, however the documentation relates to the GraphQL api for flutter. I am using Datastore and because the crud commands are different I went to the Datastore documentation. The information here is confusing because there is a section that goes into some detail describing multi authorisation and also says

"To enable DataStore to use multiple authorization types based on the model's @auth rules, configure the "auth mode strategy" when initializing DataStore "

but it doesn't describe how to do this? I've googled for examples but cannot find an example for Futter only for Swift.

In the middle of all the documentation surrounding multi-auth there is a message saying the following: "DataStore multi-authorization is currently unsupported in Flutter. We are actively working on this." Please follow this Github issue to track this missing feature.

This is why I'm now confused. Does multi-auth work for flutter? If so how can I configure the "auth mode strategy" for datastore?

Unfortunately single auth doesn't really work for me because my use case includes both a mobile app written in Flutter and a nextjs app using the same backend - both of which have different authorisation needs.

I really appreciate your help.

Matt

chrisbonifacio commented 2 years ago

@matthewapps Ahh yeah, I didn't realize I was reading the GraphQL documentation. I also didn't realize that Flutter still wasn't up to feature parity with DataStore for the other frameworks 😕 .

I just asked the flutter team for an update and they said that multi-auth is expected release soon after the release of 0.3. Flutter's pretty new to our platform so we're still working towards full feature parity. Apologies for the confusion.

matthewapps commented 2 years ago

@chrisbonifacio this is really unfortunate. Any view on timelines for resolution , are we talking days, weeks or months? The documentation is misleading - none of the graphql auth rules apply. The Flutter docs look like a cut and paste of the Javascript docs but the features unfortunately are not available in this release.

chrisbonifacio commented 2 years ago

Unfortunately, I can't know for certain when a feature is to be released exactly, only that it's in the pipeline.

There was a PR Draft recently that has been closed until further notice that started on this feature.

I would recommend tracking the feature request for any further updates.

github-actions[bot] commented 1 year ago

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 or Discussions for those types of questions.