Имплементација аутентификације корисника у Екпресс.јс помоћу ЈВТ-а

ГрапхКЛ је популарна алтернатива традиционалној РЕСТфул АПИ архитектури, која нуди флексибилан и ефикасан језик за упите података и манипулацију за АПИ-је. Са његовим све већим усвајањем, постаје све важније дати приоритет безбедности ГрапхКЛ АПИ-ја како би се апликације заштитиле од неовлашћеног приступа и потенцијалних повреда података.

Један ефикасан приступ за обезбеђивање ГрапхКЛ АПИ-ја је имплементација ЈСОН веб токена (ЈВТ). ЈВТ-ови обезбеђују сигуран и ефикасан метод за одобравање приступа заштићеним ресурсима и извођење овлашћених радњи, обезбеђујући безбедну комуникацију између клијената и АПИ-ја.

Аутентификација и ауторизација у ГрапхКЛ АПИ-јима

За разлику од РЕСТ АПИ-ја, ГрапхКЛ АПИ-ји обично имају једну крајњу тачку која омогућава клијентима да динамички захтевају различите количине података у својим упитима. Иако је ова флексибилност њена снага, она такође повећава ризик од потенцијалних безбедносних напада као што су рањивости у контроли приступа.

Да бисте ублажили овај ризик, важно је имплементирати робусне процесе аутентификације и ауторизације, укључујући правилно дефинисање дозвола за приступ. На тај начин гарантујете да само овлашћени корисници могу да приступе заштићеним ресурсима и на крају смањујете ризик од потенцијалног нарушавања безбедности и губитка података.

Код овог пројекта можете пронаћи у њему ГитХуб репозиторијум.

Подесите Екпресс.јс Аполло сервер

Аполло Сервер је широко коришћена имплементација ГрапхКЛ сервера за ГрапхКЛ АПИ-је. Можете га користити да лако направите ГрапхКЛ шеме, дефинишете разрешиваче и управљате различитим изворима података за ваше АПИ-је.

Да бисте подесили Екпресс.јс Аполло сервер, креирајте и отворите фасциклу пројекта:

 mkdir graphql-API-jwt
cd graphql-API-jwt

Затим покрените ову команду да бисте иницијализовали нови Ноде.јс пројекат користећи нпм, Ноде менаџер пакета:

 npm init --yes 

Сада инсталирајте ове пакете.

 npm install apollo-server graphql mongoose jsonwebtokens dotenv 

На крају, креирајте сервер.јс датотеку у основном директоријуму и подесите свој сервер са овим кодом:

 const { ApolloServer } = require('apollo-server');
const mongoose = require('mongoose');
require('dotenv').config();

const typeDefs = require("./graphql/typeDefs");
const resolvers = require("./graphql/resolvers");

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: ({ req }) => ({ req }),
});

const MONGO_URI = process.env.MONGO_URI;

mongoose
  .connect(MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => {
    console.log("Connected to DB");
    return server.listen({ port: 5000 });
  })
  .then((res) => {
    console.log(`Server running at ${res.url}`);
  })
  .catch(err => {
    console.log(err.message);
  });

ГрапхКЛ сервер је подешен са параметрима типеДефс и резолвера, специфицирајући шему и операције којима АПИ може да рукује. Опција контекста конфигурише рек објекат у контексту сваког разрешавача, што ће омогућити серверу да приступи детаљима специфичним за захтев као што су вредности заглавља.

  МонгоДБ Схардинг: Практични водич корак по корак

Направите МонгоДБ базу података

Да бисте успоставили везу са базом података, прво креирајте МонгоДБ базу података или поставите кластер на МонгоДБ Атлас. Затим копирајте наведени низ УРИ везе са базом података, креирајте .енв датотеку и унесите низ везе на следећи начин:

 MONGO_URI="<mongo_connection_uri>"

Дефинишите модел података

Дефинишите модел података користећи Монгоосе. Направите нову датотеку моделс/усер.јс и укључите следећи код:

 const {model, Schema} = require('mongoose');

const userSchema = new Schema({
    name: String,
    password: String,
    role: String
});

module.exports = model('user', userSchema);

Дефинишите ГрапхКЛ шему

У ГрапхКЛ АПИ-ју, шема дефинише структуру података за које се може тражити упит, као и навођење доступних операција (упити и мутације) које можете извршити да бисте остварили интеракцију са подацима преко АПИ-ја.

Да бисте дефинисали шему, креирајте нову фасциклу у основном директоријуму вашег пројекта и назовите је грапхкл. Унутар ове фасцикле додајте две датотеке: типеДефс.јс и ресолверс.јс.

У датотеци типеДефс.јс укључите следећи код:

 const { gql } = require("apollo-server");

const typeDefs = gql`
  type User {
    id: ID!
    name: String!
    password: String!
    role: String!
  }
  input UserInput {
    name: String!
    password: String!
    role: String!
  }
  type TokenResult {
    message: String
    token: String
  }
  type Query {
    users: [User]
  }
  type Mutation {
    register(userInput: UserInput): User
    login(name: String!, password: String!, role: String!): TokenResult
  }
`;

module.exports = typeDefs;

Креирајте Ресолвере за ГрапхКЛ АПИ

Функције разрешивача одређују како се подаци преузимају као одговор на упите и мутације клијената, као и друга поља дефинисана у шеми. Када клијент пошаље упит или мутацију, ГрапхКЛ сервер покреће одговарајуће резолвере да обрађују и враћају потребне податке из различитих извора, као што су базе података или АПИ-ји.

  Фацебоок видео снимци се не репродукују у Цхроме-у, Фирефок-у, Сафарију (РЕШЕНО)

Да бисте имплементирали аутентификацију и ауторизацију помоћу ЈСОН веб токена (ЈВТ), дефинишите разрешиваче за мутације регистра и пријављивања. Они ће управљати процесима регистрације и аутентификације корисника. Затим креирајте разрешивач упита за преузимање података који ће бити доступан само аутентификованим и овлашћеним корисницима.

Али прво, дефинишите функције за генерисање и верификацију ЈВТ-ова. У датотеци ресолверс.јс почните додавањем следећих увоза.

 const User = require("../models/user");
const jwt = require('jsonwebtoken');
const secretKey = process.env.SECRET_KEY;

Обавезно додајте тајни кључ који ћете користити за потписивање ЈСОН веб токена у .енв датотеку.

 SECRET_KEY = '<my_Secret_Key>'; 

Да бисте генерисали токен за аутентификацију, укључите следећу функцију, која такође специфицира јединствене атрибуте за ЈВТ токен, нпр. време истека. Поред тога, можете да уградите и друге атрибуте, као што су издати у одређено време, на основу ваших специфичних захтева апликације.

 function generateToken(user) {
  const token = jwt.sign(
   { id: user.id, role: user.role },
   secretKey,
   { expiresIn: '1h', algorithm: 'HS256' }
 );

  return token;
}

Сада имплементирајте логику верификације токена да бисте потврдили ЈВТ токене укључене у наредне ХТТП захтеве.

 function verifyToken(token) {
  if (!token) {
    throw new Error('Token not provided');
  }

  try {
    const decoded = jwt.verify(token, secretKey, { algorithms: ['HS256'] });
    return decoded;
  } catch (err) {
    throw new Error('Invalid token');
  }
}

Ова функција ће узети токен као улаз, верификовати његову валидност помоћу наведеног тајног кључа и вратити декодирани токен ако је важећи, у супротном ће избацити грешку која указује на неважећи токен.

Дефинишите АПИ разрешиваче

Да бисте дефинисали разрешиваче за ГрапхКЛ АПИ, потребно је да наведете специфичне операције којима ће управљати, у овом случају, регистрацију корисника и операције пријављивања. Прво, креирајте објекат решавања који ће држати функције разрешивача, а затим дефинишите следеће операције мутације:

 const resolvers = {
  Mutation: {
    register: async (_, { userInput: { name, password, role } }) => {
      if (!name || !password || !role) {
        throw new Error('Name password, and role required');
     }

      const newUser = new User({
        name: name,
        password: password,
        role: role,
      });

      try {
        const response = await newUser.save();

        return {
          id: response._id,
          ...response._doc,
        };
      } catch (error) {
        console.error(error);
        throw new Error('Failed to create user');
      }
    },
    login: async (_, { name, password }) => {
      try {
        const user = await User.findOne({ name: name });

        if (!user) {
          throw new Error('User not found');
       }

        if (password !== user.password) {
          throw new Error('Incorrect password');
        }

        const token = generateToken(user);

        if (!token) {
          throw new Error('Failed to generate token');
        }

        return {
          message: 'Login successful',
          token: token,
        };
      } catch (error) {
        console.error(error);
        throw new Error('Login failed');
      }
    }
  },

Мутација регистра управља процесом регистрације додавањем нових корисничких података у базу података. Док мутација пријављивања управља пријављивањем корисника—по успешној аутентификацији, она ће генерисати ЈВТ токен, као и вратити поруку о успеху у одговору.

  Како да откажете састанак у Мицрософт тимовима

Сада укључите разрешивач упита за преузимање корисничких података. Да бисте били сигурни да ће овај упит бити доступан само провјереним и овлаштеним корисницима, укључите логику ауторизације да бисте ограничили приступ само корисницима са улогом администратора.

У суштини, упит ће прво проверити валидност токена, а затим и корисничку улогу. Ако је провера ауторизације успешна, упит разрешивача ће наставити да преузима и враћа податке корисника из базе података.

   Query: {
    users: async (parent, args, context) => {
      try {
        const token = context.req.headers.authorization || '';
        const decodedToken = verifyToken(token);

        if (decodedToken.role !== 'Admin') {
          throw new ('Unauthorized. Only Admins can access this data.');
        }

        const users = await User.find({}, { name: 1, _id: 1, role:1 });
        return users;
      } catch (error) {
        console.error(error);
        throw new Error('Failed to fetch users');
      }
    },
  },
};

Коначно, покрените развојни сервер:

 node server.js 

Сјајно! Сада, само напред и тестирајте функционалност АПИ-ја користећи Аполло Сервер АПИ сандбок у вашем претраживачу. На пример, можете користити мутацију регистра да додате нове корисничке податке у базу података, а затим мутацију за пријаву да бисте потврдили аутентичност корисника.

На крају, додајте ЈВТ токен у одељак заглавља ауторизације и наставите да тражите корисничке податке у бази података.

Обезбеђивање ГрапхКЛ АПИ-ја

Аутентификација и ауторизација су кључне компоненте за обезбеђивање ГрапхКЛ АПИ-ја. Ипак, важно је препознати да они сами по себи можда нису довољни да осигурају свеобухватну безбедност. Требало би да примените додатне мере безбедности као што су провера ваљаности уноса и шифровање осетљивих података.

Усвајањем свеобухватног безбедносног приступа, можете заштитити своје АПИ-је од различитих потенцијалних напада.