How to do field level @auth for bi-directional one-to-many @connection with AppSync GraphQL Transform?

て烟熏妆下的殇ゞ 提交于 2020-12-12 04:41:43

问题


I'm trying to figure out how can you protect at field level a one-to-many @connection with @auth against mutations that shouldn't be allowed. (ie: deny a specific user to run a mutation that will end-up inserting posts as another user.)

Starting with the example for protecting a mutation at the field level: https://aws-amplify.github.io/docs/cli/graphql#field-level-authorization

I tried doing something like this:

type User @model @auth(rules: [{ allow: owner, ownerField: "id" }]) {
  id: ID!
  posts: [Post]
    @connection(name: "UserPosts")
    @auth(rules: [{ allow: owner, ownerField: "id" }])
}

type Post @model {
  title: String!
  user: User!
    @connection(name: "UserPosts")
    @auth(rules: [{ allow: owner, ownerField: "userPostId" }])
}

Then say there already is a user with an id of regular-user-id Apparently my auth rules don't stop another user, say with id of: malicious-user-id to run this mutation:

mutation {
  createPost(input:{
    title:"Oh this is BAD!"
    postUserId: "regular-user-id"
  }) {
    title
  }
}

Running a simple query to make sure this really happened:

query {
  getUser(id:"regular-user-id"){
    posts{
      items
      {
        title
      }
    }
  }
}
=> 
{
  "data": {
    "getUser": {
      "posts": {
        "items": [
          {
            "title": "Regular User title"
          },
          {
            "title": "Oh this is BAD!"
          },
        ]
      }
    }
  }
}

I tried various ways to figure this one out and couldn't find any documentation about bi-directional field level authentication. I'm fairly new to AppSync so I think I must be not getting something, but then this is such common use-case scenario that I'm really surprised there isn't more documentation about it.

Some help would be really appreciated.


回答1:


To protect the Mutation.createPost mutation such that only the owner of the Post as designated via the postUserId may access it you add an @auth directive to the Post object definition:

type Post @model @auth(rules: [{ allow: owner, ownerField: "postUserId" }]) {
  title: String!
  # This will use a field 'postUserId' by default.
  user: User!
    @connection(name: "UserPosts")
}

With this setup, a mutation:

mutation {
  createPost(input:{
    title:"Oh this is BAD!"
    postUserId: "regular-user-id"
  }) {
    title
  }
}

will fail if the logged in user is not "regular-user-id".

This answer may help fill things in as well https://github.com/aws-amplify/amplify-cli/issues/1507#issuecomment-513042021.




回答2:


Should the malicious user be able to update the Post title? I know this isn't an exact answer to your question since you're focusing on the relation field, but from trying to understand how to do these kind of things myself, I read a few things about introducing some form of 'everyone' group so you can define auth for user's who aren't owners. Then you could put auth on the entire Post model so only owners can update any field;

type Post 
  @model 
  @auth(rules: [
    { allow: owner, ownerField: "userPostId" },
    { allow: groups, groups: ["everyone"], operations: [read] }
  ]) {
  title: String!
  user: User!
    @connection(name: "UserPosts")
}

I'm super new to amplify (I'm currently evaluating whether to use it for a project I'm starting), so I could be completely wrong here. If you do actually want a semi-open model where just the reference field has auth, I'm not sure how to do that :(



来源:https://stackoverflow.com/questions/56826035/how-to-do-field-level-auth-for-bi-directional-one-to-many-connection-with-apps

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!