Как структурировать аутентифицированные запросы с помощью GraphQL?
Я подумывал написать API, который выполняет следующие действия:
- Пользователи регистрации и входа в систему, которые предоставляют пользователю токен аутентификации
- Создание карт (пример данных:
{ name: "Quotes", attributes: ["quote", "author"] }
)
- Создание элементов карты (пример данных:
{ quote: "...", author: "..." }
)
Я бы построил несколько запросов следующим образом:
// return the name and id of all the user maps
maps(authToken="…") {
name,
id
}
// return all the items of a single map
maps(authToken="…") {
map(name="Quotes") {
items
}
}
// OR by using the map_id
maps(authToken="…") {
map(id="…") {
items
}
}
Итак, мой вопрос: правильно ли это или мне нужно структурировать его по-другому?
Ответы
Ответ 1
Я бы рекомендовал создать аутентификацию вне самого GraphQL и позволить вашей логике схемы обрабатывать авторизацию. Например, если вы используете модуль express-graphql
NPM, вы можете проверить свои файлы cookie или HTTP Basic Auth или какой-либо механизм, который вы хотите использовать для получения вашего токена аутентификации, а затем передать свой аутентифицированный объект просмотра через схему через rootValue
, который доступен на каждом уровне во время разрешения запроса:
app.use('/graphql', (request, response, next) => {
const viewer = getViewerFromRequest(); // You provide this.
const options = {
rootValue: {
viewer,
},
schema,
};
return graphqlHTTP(request => options)(request, response, next);
});
И затем внутри схемы вы имеете доступ к вашему rootValue и можете использовать ее для целей контроля доступа и авторизации:
resolve: (parent, args, {rootValue}) => {
const viewer = {rootValue};
// Code that uses viewer here...
}
Обратите внимание, что по сравнению с graphql v0.5.0, подпись resolve
изменилась и третий параметр "context" был вставлен в позицию 3 в аргументе список. Этот параметр подходит для передачи токена аутентификации или аналогичного:
resolve: (parent, args, authToken, {rootValue}) => {
// Code that uses the auth token here...
}
Ответ 2
Я предложил подход, который структурирует резольверов как состав меньших функций, чтобы помочь в решении этой точной проблемы. Вы можете увидеть полный ответ здесь: Как проверить разрешения и другие условия в запросе GraphQL?.
Основная идея заключается в том, что если вы структурируете свои резольверы в виде небольших функций, которые составлены вместе, вы можете сложить различные механизмы авторизации/аутентификации друг над другом и выбросить ошибку в первом, которая не выполняется. Это поможет сохранить ваш код в чистоте, проверке и повторном использовании:)
Также да, контекст resolver - отличное место для хранения информации аутентификации, а также других полезных свойств, которые могут потребоваться для использования в ваших распознавателях.
Счастливый взлом!