Предотвращение эксплойта утечки данных отношений с помощью graphql

Как сделать так, чтобы люди не запрашивали отношения между объектами, которые они не должны видеть в graphql?

Например, предположим, что у нас есть следующая модель данных.

type Board {
    id: ID! @unique
    name: String!
    boardUserRoles: [BoardUserRole!]!
}

type BoardUserRole {
    id: ID! @unique
    board: Board!
    user: User!
    role: BoardRole!
}

type User {
    id: ID! @unique
    tasks: [Task!]!
    userName: String! @unique
    boardUserRoles: [BoardUserRole!]!
}

Это настройка, в которой есть пользователи, которые имеют доступ к определенным доскам. И BoardUserRole определяет, какую роль играет пользователь для конкретной таблицы.

Теперь я прихожу и запрашиваю доску, на которую у меня есть разрешение, и смотрю на ее название.

query {
    board(where: {id: "3"}) {
        id
        name
    }
}

Это прекрасно. Однако я могу связаться с другими пользователями системы и увидеть задачи, которые у них есть, если я изменю запрос. Я могу видеть все, что связано с этим пользователем.

query {
    board(where: {id: "3"}) {
        id
        name
        boardUserRoles {
            user {
                tasks
            }
        }
    }
}

Как защитить себя от запросов такого типа?

это серьезный вопрос? это похоже на «У меня есть таблица sql с паролем - как не показывать их с помощью select» - API просто не должен возвращать данные, у которых нет разрешений. Неважно, что это sql, rest, graphql, что угодно. Проверить документы Prisma?

xadm 11.08.2018 00:16

@xadm да. Серьезный. Возможно, я что-то неправильно понимаю, но если у пользователя есть доступ к доске 3, как бы вы помешали ему использовать остальную схему для обхода графика для доступа к другим данным? Вы делаете это очевидным, поэтому, пожалуйста, дайте мне знать, о чем вы думаете. Я прочитал Prisma, Apollo и graphql и ничего не нашел о том, как запретить кому-либо запрашивать весь граф в одном запросе. Я знаю способ сделать это, переопределив info, который поставляется на преобразователе, только с теми данными, которые я хочу, чтобы они получали, но я не хочу лишать пользователей этой возможности.

prolink007 11.08.2018 06:49

В graphql вы можете иметь безопасность на уровне поля. It doesn't matter it's traversing or simple query - резольвер всегда беру отдельно. Вы должны ограничить возвращаемые поля, когда у пользователя нет разрешения. F.e. не показывать некоторые данные, не обновлять контент поста, если вы не являетесь автором или модератором ... 2-секундный поиск в Google: github.com/prismagraphql/prisma/issues/1768, директивы разрешений prisma ...

xadm 11.08.2018 09:50

@xadm, это действительно хорошие книги, я считаю, что это именно то, что я ищу. Подробнее об этом в понедельник. Ty

prolink007 11.08.2018 14:34
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
4
471
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

При использовании Prisma вы можете изменить структуры данных, которые доступны вашим клиентским приложениям, переопределив тип в схема приложения.

Определения SDL, которые вы показываете в своем вопросе, мне кажутся Модель данных Prisma. Я предполагаю, что у вас также есть сервер API (возможно, реализованный с помощью graphl-yoga или apollo-server), который предоставляет API GraphQL, который будет использоваться вашими клиентскими приложениями. Назовем схему GraphQL, определяющую этот API, схема приложения. Внутри схемы приложения вы можете переопределить типов из вашей модели данных так, как вы хотите предоставить их своим клиентам.

Вот простой пример:

Предположим, у вас есть следующий тип User в вашей модели данных Prisma:

type User {
  id: ID! @unique
  email: String! @unique
  password: String!
  name: String!
  posts: [Post!]!
}

Теперь вы не хотите показывать password своим клиентам. Итак, что вы можете сделать, так это переопределить тип User таким образом, чтобы ваши клиенты могли получить к нему доступ. Вот как вы можете определить его в схеме приложения (часто называемой schema.graphql):

type User {
  id: ID!
  email: String!
  name: String!
  posts: [Post!]!
}

Вы можете найти работающую версию этого примера здесь. Кроме того, если вас смущает терминология схемы приложения и модели данных, я рекомендую вам прочитать часть это документации Prisma.

Я полностью понимаю, о чем вы говорите. Я не знал, что могу переопределить свои типы в schema.graphql. Я думал, что это предназначено только для резольверов. Это проницательно, но не решение моей проблемы. Мне нужно, чтобы определенные вещи были открыты на основании авторизации. Я разобрался и опубликую свое решение через несколько минут. Спасибо!

prolink007 14.08.2018 15:37
Ответ принят как подходящий

С помощью @xadm. Мне удалось собрать решение, которое идеально мне подошло.

Прочитав эту статью о том, как выполнение запроса работает. Я понял, как писать преобразователи полей. Преобразователь полей позволяет мне определять, как именно разрешается конкретное поле. Я сделал преобразователь полей для Board: boardUserRoles.

Вот мой преобразователь поля.

Board: {
    boardUserRoles: async (parent: Board, args, ctx, info) => {
        // getting user id from header.
        const userId: string = VerificationHelper.getUserId(ctx);

        // Verifying role of user.
        return VerificationHelper.verifyRole(userId, ["ADMIN"], ctx).pipe(
            map(
                (result: boolean) => {
                    // If the user has an admin role, show the roles
                    if (result) {
                        return parent.boardUserRoles;
                    // If not, map the results to undefined
                    } else {
                        return undefined;
                    }
                }
            )
        ).toPromise();
    }
}

Затем я добавил этот преобразователь в свой список преобразователей при создании graphql.

const server: GraphQLServer = new GraphQLServer({
    typeDefs: "src/schema.graphql",
    resolvers: {
        Query: QueryResolvers,
        Mutation: MutationResolvers,
        Subscription: SubscriptionResolvers,
        ...FieldResolvers, // A file that contains all my field resolvers.
        AuthPayload
    },
    context: (req: any) => ({
        ...req,
        prisma: new Prisma({
            typeDefs: "src/generated/prisma.graphql",
            endpoint: endpoint()
        })
    })
});

Это очень простой преобразователь полей. Он проверяет роль пользователя и определяет, следует ли скрывать данные или отображать данные. Я просмотрел всю свою схему и нашел другие эксплойты данных. Я исправил те, которые нашел с помощью преобразователей полей, и теперь все работает отлично.

Спасибо за помощь @xadm, ваши ссылки указали мне в правильном направлении.

Замечательно! ? Дайте мне знать, если у вас возникнут другие вопросы по Prisma.

nburk 14.08.2018 16:11

@nburk Подойдет, изучаю graphql прямо сейчас и получаю от этого удовольствие. Предпочитаете его прямо сейчас обычному restAPI.

prolink007 14.08.2018 16:13

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