如何使用 AppSync GraphQL 转换为双向一对多 @connection 执行字段级别 @auth?

Posted

技术标签:

【中文标题】如何使用 AppSync GraphQL 转换为双向一对多 @connection 执行字段级别 @auth?【英文标题】:How to do field level @auth for bi-directional one-to-many @connection with AppSync GraphQL Transform? 【发布时间】:2019-11-11 12:59:46 【问题描述】:

我正在尝试弄清楚如何在现场级别保护一对多 @connection@auth 免受不应允许的突变。 (即:拒绝特定用户运行突变,最终以另一个用户的身份插入帖子。)

从在字段级别保护突变的示例开始:https://aws-amplify.github.io/docs/cli/graphql#field-level-authorization

我试着做这样的事情:

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" ])

然后说已经有一个 id 为regular-user-id 的用户 显然,我的身份验证规则不会阻止其他用户,例如使用 id 为:malicious-user-id 来运行此突变:

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

运行一个简单的查询以确保这确实发生了:

query 
  getUser(id:"regular-user-id")
    posts
      items
      
        title
      
    
  

=> 

  "data": 
    "getUser": 
      "posts": 
        "items": [
          
            "title": "Regular User title"
          ,
          
            "title": "Oh this is BAD!"
          ,
        ]
      
    
  

我尝试了各种方法来解决这个问题,但找不到任何有关双向字段级别身份验证的文档。我对 AppSync 还很陌生,所以我想我一定没有得到任何东西,但这是如此常见的用例场景,我真的很惊讶没有更多关于它的文档。

我们将不胜感激。

【问题讨论】:

【参考方案1】:

要保护Mutation.createPost 突变,以便只有通过postUserId 指定的帖子的所有者才能访问它,您可以在帖子对象定义中添加@auth 指令:

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

有了这个设置,一个突变:

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

如果登录用户不是“regular-user-id”,则会失败。

这个答案也可能有助于填写内容https://github.com/aws-amplify/amplify-cli/issues/1507#issuecomment-513042021。

【讨论】:

【参考方案2】:

恶意用户应该能够更新Post 标题吗?我知道这不是您问题的确切答案,因为您专注于关系领域,但是通过尝试了解如何自己做这些事情,我阅读了一些关于引入某种形式的“每个人”组的内容因此您可以为非所有者的用户定义身份验证。然后,您可以在整个 Post 模型上添加身份验证,这样只有所有者才能更新任何字段;

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

我是一个超级新手(我目前正在评估是否将它用于我正在开始的项目),所以我在这里可能完全错了。如果您确实想要一个只有参考字段具有身份验证的半开放模型,我不知道该怎么做:(

【讨论】:

帖子创建后不更新。这很好用。创建帖子是问题所在。我找不到阻止说 UserB 运行突变的方法,他指定帖子属于另一个用户说 UserA。 ownerField 将是“postUserId”而不是“userPostId”,这可能会导致混淆。您还可以使用@connection 上的“keyField”和“sortField”参数显式设置关键字段。

以上是关于如何使用 AppSync GraphQL 转换为双向一对多 @connection 执行字段级别 @auth?的主要内容,如果未能解决你的问题,请参考以下文章

使用 GraphQL 转换在 AWS AppSync 中生成带有参数的订阅

通过 AWS AppSync GraphQL API 使用多种授权类型

如何使用 AWS appsync (GraphQL) 禁用自省查询?

如何使用 amplify 将 GraphQL 更改从 Appsync 同步到 Android?

AppSync/Amplify - 如何定义 GraphQL 订阅

如何在 AppSync GraphQL 架构中使用自定义输入类型?