Учебники

GraphQL — клиент для аутентификации

Аутентификация — это процесс или действие по проверке личности пользователя или процесса. Важно, чтобы приложение аутентифицировало пользователя, чтобы гарантировать, что данные не доступны анонимному пользователю. В этом разделе мы узнаем, как аутентифицировать клиента GraphQL.

Экспресс JWT

В этом примере мы будем использовать jQuery для создания клиентского приложения. Для аутентификации запросов мы будем использовать модуль express-jwt на стороне сервера.

Модуль express-jwt — это промежуточное ПО, которое позволяет аутентифицировать HTTP-запросы с использованием токенов JWT. JSON Web Token (JWT) — это длинная строка, которая идентифицирует вошедшего в систему пользователя.

После успешного входа пользователя сервер генерирует токен JWT. Этот токен четко идентифицирует журнал. Другими словами, токен является представлением личности пользователя. Поэтому в следующий раз, когда клиент приходит на сервер, он должен представить этот токен, чтобы получить необходимые ресурсы. Клиент может быть мобильным приложением или веб-приложением.

Экспресс модуль JWT

иллюстрация

Мы будем следовать пошаговой процедуре, чтобы понять эту иллюстрацию.

Настройка сервера

Ниже приведены шаги для настройки сервера:

Шаг 1 — Загрузите и установите необходимые зависимости для проекта

Создайте папку auth-server-app . Измените свой каталог на auth-server-app из терминала. Выполните шаги с 3 по 5, описанные в главе «Настройка среды».

Шаг 2 — Создание схемы

Добавьте файл schema.graphql в папку проекта auth-server-app и добавьте следующий код —

type Query
{
   greetingWithAuth:String
}

Шаг 3 — Добавить резольверы

Создайте файл resolvers.js в папке проекта и добавьте следующий код —

Средство распознавания проверит, доступен ли аутентифицированный пользовательский объект в объекте контекста GraphQL. Возникнет исключение, если аутентифицированный пользователь недоступен.

const db = require('./db')

const Query = {
   greetingWithAuth🙁root,args,context,info) => {

      //check if the context.user is null
      if (!context.user) {
         throw new Error('Unauthorized');
      }
      return "Hello from TutorialsPoint, welcome back : "+context.user.firstName;
   }
}

module.exports = {Query}

Шаг 4 — Создайте файл Server.js

Промежуточное ПО аутентификации аутентифицирует абонентов с помощью веб-токена JSON. URL для аутентификации — http: // localhost: 9000 / login .

Это почтовая операция. Пользователь должен предоставить свой адрес электронной почты и пароль, которые будут проверены с бэкэнда. Если действительный токен генерируется с использованием метода jwt.sign, клиент должен будет отправить его в заголовке для последующих запросов.

Если токен действителен, req.user будет установлен с декодированным объектом JSON, который будет использоваться последующим промежуточным программным обеспечением для авторизации и контроля доступа.

Следующий код использует два модуля — jsonwebtoken и express-jwt для аутентификации запросов —

  • Когда пользователь нажимает кнопку приветствия , выдается запрос на маршрут / graphql. Если пользователь не аутентифицирован, ему будет предложено аутентифицировать себя.

  • Пользователю предоставляется форма, которая принимает идентификатор электронной почты и пароль. В нашем примере маршрут / login отвечает за аутентификацию пользователя.

  • Маршрут / login проверяет, найдено ли совпадение в базе данных для учетных данных, предоставленных пользователем.

  • Если учетные данные недействительны, исключение HTTP 401 возвращается пользователю.

  • Если учетные данные действительны, токен генерируется сервером. Этот токен отправляется как часть ответа пользователю. Это делается с помощью функции jwt.sign.

Когда пользователь нажимает кнопку приветствия , выдается запрос на маршрут / graphql. Если пользователь не аутентифицирован, ему будет предложено аутентифицировать себя.

Пользователю предоставляется форма, которая принимает идентификатор электронной почты и пароль. В нашем примере маршрут / login отвечает за аутентификацию пользователя.

Маршрут / login проверяет, найдено ли совпадение в базе данных для учетных данных, предоставленных пользователем.

Если учетные данные недействительны, исключение HTTP 401 возвращается пользователю.

Если учетные данные действительны, токен генерируется сервером. Этот токен отправляется как часть ответа пользователю. Это делается с помощью функции jwt.sign.

const expressJwt = require('express-jwt');
const jwt = require('jsonwebtoken');

//private key
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');

app.post('/login', (req, res) => {
   const {email, password} = req.body;
   
   //check database
   const user = db.students.list().find((user) =>  user.email === email);
   if (!(user && user.password === password)) {
      res.sendStatus(401);
      return;
   }
   
   //generate a token based on private key, token doesn't have an expiry
   const token = jwt.sign({sub: user.id}, jwtSecret);
   res.send({token});
});

Для каждого запроса будет вызываться функция app.use (). Это, в свою очередь, вызовет промежуточное программное обеспечение expressJWT. Это промежуточное ПО будет декодировать веб-токен JSON. Идентификатор пользователя, сохраненный в токене, будет извлечен и сохранен как пользователь свойства в объекте запроса.

//decodes the JWT and stores in request object
app.use(expressJwt({
   secret: jwtSecret,
   credentialsRequired: false
}));

Чтобы сделать свойство пользователя доступным в контексте GraphQL, это свойство назначается объекту контекста, как показано ниже:

//Make req.user available to GraphQL context
app.use('/graphql', graphqlExpress((req) => ({
   schema,
   context: {user: req.user &&apm; db.students.get(req.user.sub)}
})));

Создайте server.js в текущем пути к папке. Полный файл server.js выглядит следующим образом —

const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const expressJwt = require('express-jwt'); //auth
const jwt = require('jsonwebtoken'); //auth
const db = require('./db');

var port = process.env.PORT || 9000
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
const app = express();

const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')
const {makeExecutableSchema} = require('graphql-tools')

const schema = makeExecutableSchema({typeDefs, resolvers})

app.use(cors(), bodyParser.json(), expressJwt({
   secret: jwtSecret,
   credentialsRequired: false
}));

const  {graphiqlExpress,graphqlExpress} = require('apollo-server-express')

app.use('/graphql', graphqlExpress((req) => ({
   schema,
   context: {user: req.user && db.students.get(req.user.sub)}
})));
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))

//authenticate students
app.post('/login', (req, res) => {
   const email = req.body.email;
   const password = req.body.password;

   const user = db.students.list().find((user) =>  user.email === email);
   if (!(user && user.password === password)) {
      res.sendStatus(401);
      return;
   }
   const token = jwt.sign({sub: user.id}, jwtSecret);
   res.send({token});
});

app.listen(port, () => console.info(`Server started on port ${port}`));

Шаг 5 — Запустите приложение

Выполните команду npm start в терминале. Сервер будет работать на 9000 портов. Здесь мы используем GraphiQL в качестве клиента для тестирования приложения.

Откройте браузер и введите URL-адрес http: // localhost: 9000 / graphiql . Введите следующий запрос в редакторе —

{
   greetingWithAuth
}

В ответе ниже мы получили ошибку, поскольку мы не являемся аутентифицированным пользователем.

{
   "data": {
      "greetingWithAuth": null
   },
   "errors": [
      {
         "message": "Unauthorized",
         "locations": [
            {
               "line": 2,
               "column": 3
            }
         ],
         "path": [
            "greetingWithAuth"
         ]
      }
   ]
}

В следующем разделе давайте создадим клиентское приложение для аутентификации.

Настройка клиента JQuery

В клиентском приложении предусмотрена кнопка приветствия, которая вызовет схему приветствияWithAuth . Если вы нажмете кнопку без входа в систему, появится сообщение об ошибке, как показано ниже:

Аутентификация клиентских приложений

Как только вы войдете в систему с пользователем, доступным в базе данных, появится следующий экран —

Аутентификация клиентского приложения прошла успешно

Чтобы получить доступ к приветствию , нам сначала нужно получить доступ к URL-адресу http: // localhost: 9000 / login route, как показано ниже.

Ответ будет содержать токен, сгенерированный с сервера.

$.ajax({
   url:"http://localhost:9000/login",
   contentType:"application/json",
   type:"POST",
   data:JSON.stringify({email,password}),
   success:function(response) {
      loginToken = response.token;
      $('#authStatus')
      .html("authenticated successfully")
      .css({"color":"green",'font-weight':'bold'});
      $("#greetingDiv").html('').css({'color':''});
   },
   error🙁xhr,err) =>  alert('error')
})

После успешного входа в систему мы можем получить доступ к схемеreetingWithAuth, как показано ниже. Должен быть заголовок авторизации для всех последующих запросов с токеном носителя.

{ 
   url: "http://localhost:9000/graphql",
   contentType: "application/json",
   headers: {"Authorization": 'bearer '+loginToken},  type:'POST',
   data: JSON.stringify({
   query:`{greetingWithAuth}`
}

Ниже приведен код для index.html —