Как выполнить @auth на уровне поля для двунаправленного @connection «один ко многим» с помощью AppSync GraphQL Transform?

Я пытаюсь выяснить, как вы можете защитить на уровне поля один-ко-многим @connection с @auth от мутаций, которые не должны быть разрешены. (то есть: запретить конкретному пользователю запускать мутацию, которая в конечном итоге приведет к вставке сообщений от имени другого пользователя.)

Начиная с примера защиты мутации на уровне поля: https://aws-amplify.github.io/docs/cli/graphql#авторизация на уровне поля

Я попытался сделать что-то вроде этого:

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

Затем скажите, что уже есть пользователь с идентификатором regular-user-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, поэтому я думаю, что, должно быть, что-то не понимаю, но это настолько распространенный сценарий использования, что я действительно удивлен, что нет больше документации об этом.

Некоторая помощь была бы очень признательна.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
2
0
833
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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.

ovidb 12.07.2019 20:03

Поле владельца будет «postUserId», а не «userPostId», что может вызвать путаницу. Вы также можете явно установить ключевые поля, используя аргументы «keyField» и «sortField» в @connection.

mparis 02.08.2019 21:56
Ответ принят как подходящий

Чтобы защитить мутацию Mutation.createPost, чтобы только владелец сообщения, указанный с помощью postUserId, мог получить к нему доступ, вы добавляете директиву @auth в определение объекта Post:

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
  }
}

произойдет сбой, если вошедший в систему пользователь не является «обычным идентификатором пользователя».

Этот ответ также может помочь заполнить информацию https://github.com/aws-amplify/amplify-cli/issues/1507#issuecomment-513042021.

Другие вопросы по теме