В наши дни каждый человек имеет встроенную аутентификацию на своих веб-сайтах и ​​в мобильных приложениях. Аутентификация играет огромную роль в области разработки программного обеспечения, и сегодня вы узнаете, как создать REST API аутентификации с помощью Node. Прежде чем мы начнем, убедитесь, что у вас есть следующее.

Предварительные требования

  • "Узел"
  • Текстовый редактор (я буду использовать VS Code)
  • Определение
  • Компьютер
  • Wi-fi

После того, как у вас есть все вышеперечисленное, вы готовы приступить к работе.

Базовый REST API

Давайте теперь создадим простой REST API в NodeJS, который использует Express. Создайте новый каталог, в котором будет жить наш проект, и запустите следующее:

$ npm init

Пока оставьте все значения по умолчанию, мы можем отредактировать это позже, если нам понадобится.

Теперь, когда мы инициализировали наш проект, нам нужно установить модуль узла express.js:

$ npm install express --save

Это уйдет и получит необходимый модуль экспресс-узла, который мы будем использовать для создания REST API, который мы будем защищать.

Примечание. В данном конкретном примере мы используем Express, но концепции в этом руководстве не зависят от фреймворка и могут использоваться с другими фреймворками веб-приложений, такими как Koa.

Теперь, когда у нас установлены все наши зависимости, мы можем написать код! Создайте новый файл в каталоге вашего проекта с именем index.js.

index.js

const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, 
    () => console.log(`Simple Express app listening on port ${port}!`))

Это невероятно простое приложение, которое возвращает Hello World! всякий раз, когда вы попадаете на путь / порта 3000. Впоследствии вы можете запустить это приложение так:

$ node index.js

Example app listening on port 3000!

Теперь, когда это запущено, перейдите к http://localhost:3000/ в своем браузере, и вы увидите, что ваше приложение возвращает вам ожидаемый Hello World!.

Добавление нескольких конечных точек

Теперь, когда у нас есть базовое приложение NodeJS, работающее на порте 3000, давайте посмотрим, как мы можем его расширить и добавить несколько конечных точек, которые впоследствии можно будет защитить.

Я собираюсь сделать это пока очень простым, чтобы мы могли сосредоточиться на авторизации JWT, а не на базовом приложении.

Откройте ваш index.js файл еще раз. Давайте добавим несколько новых HTTP GET конечных точек:

index.js

const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello World!'))
// let's first add a /secret api endpoint that we will be protecting
app.get('/secret', (req, res) => {
    res.json({ "message" : "THIS IS SUPER SECRET, DO NOT SHARE!" })
})
// and a /readme endpoint which will be open for the world to see 
app.get('/readme', (req, res) => {
    res.json({ "message" : "This is open to the world!" })
})
app.listen(port, 
    () => console.log(`Simple Express app listening on port ${port}!`))

Теперь, когда у нас есть эти конечные точки, давайте повторно запустим наше приложение, чтобы убедиться, что мы ничего не сломали:

$ node index.js

Simple Express app listening on port 3000!

Давайте теперь откроем http://localhost:3000/secret в окне браузера, когда он запущен. Вы увидите следующий ответ:

http: // localhost: 3000 / secret

{
    "message": "THIS IS SUPER SECRET, DO NOT SHARE!"
}

И когда мы откроем конечную точку /readme, мы должны увидеть следующее:

http: // localhost: 3000 / secret

{
    "message": "This is open to the world!"
}

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

Создание действительного JWT

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

Чтобы сгенерировать и проверить эти JWT, нам нужно сначала импортировать модуль узла jsonwebtoken:

$ npm install --save jsonwebtoken

После установки этого модуля узла мы можем продолжить и создать пользовательскую конечную точку /jwt, которая создаст для нас токен JWT, который имеет невероятно простую полезную нагрузку { "body": "stuff" } и подписан с использованием закрытого ключа, который я сгенерировал для устаревшего проекта.

Создайте в своем проекте новый файл с именем private.pem и добавьте следующий ключ:

private.pem

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAyVTQ9QxfutaYXKBbYfZbH2vhIWoIPEjAFSbsy1PZoIcclUQR
hJ8t2m7v47M8eEyYd7EvXTNdoN6CDs0DoNC9KESATZV5SUVr7sk9pOcMrm0VryAd
h7hQbbHWqyKmOehCt1JdX7gV2i5XnRb5qYQSyoB8sGdfR4SQ9q1XPRIpBP8RYXCP
WPmwnmtzYjfs+VVMp+ByNWgM8Qvyc3Z13tHKHWfTokbEbJJE0xfFG6CVFZy+T7uq
0UxhkWh8tekaDbfrIYtgC8HRHfRPcqvsN/pkJM0DIU4UNIf2TeLARa+iATNiF5IX
DeAAkIqoQL0tgt6S+8HIEPGiQ3gpGE56DON06QIDAQABAoIBAAvIxyJQwxmwjeJ+
EFs/jD3elqLaDflZWMTkLmAIXGik/+tMvKnCl3B9pdTyHMv9z77RxC/0XbqYy4wK
O/ghv7CnscrYwOyk/5hOdyk7zOY4xFgnzRKwmySQkDwcHxasnZsVWxnLMJxAsigj
vCFL9b2cn6/DnTQWclW996k/ct8z5DzodH/O+JyQl2MvLgjtf1OupbNZcjt4kMRP
GS5em5banlycUtPE0NAcS0QXleHLj5BXOp0AyD+PWfzhWcctiK7p+vmwXv6OVtlu
DIiTTOnsjoMq7skfVzRpjmAesllXBb1evwsrVK7cjYefEsVZ5DzOVLNU5Iug3HCf
RnftUAECgYEA6uWhJ9la1VpiYgEai4F61Rxs/MAQzmWVl0NQhPrczLCdRXfhmeBP
w1a4VkCD7FlZq/UuL4bSnU2JINL/enmrfZfdLdQgjY1VgPNki6v4Da9sqi+D17Wb
w863h/X29cukttFgUQdPO66bwsitoNVDsBqyf2hlFWC+rRPovoFA9WkCgYEA22s2
njRgoV6mTTCgXoZMs8unJ2CTd+BuVP1wDVsHR0VnK7blVlIW9Hop0ZmFK3I41kw3
3LXT6RSmZXsdgAsm3VuWlDVFY6t+JUUGYOfZZVNgUX0J597hf2SwxfJ8cgNHuSEO
glxc/dzHXMgamf8+84RCK3NSGP8xmuI/Wm5JE4ECgYEAmFelVTradlTQSc99b8zh
5SUyahoGzFWF1zyJFDW+zeIdndhKMIoSMRYlJ4tgBAFO7v9snNZL8kk/DlLJ7pzK
ZAICKJ7THfrz4VX5d7xofDexug5m65eVFkETNtKHAJK6mPbiCKs87/AmhQWx1gV6
iNRHv+ns5RiBka6/3A3oG0ECgYEAl+qIO0rqaG++1ozHTArSCl4DUlkkYQhLe56p
OSYASRE9WF/eM0DM0eHPGGahdC42OfE1cCOYH7WDa5mtGB0ggHxMKjsj2tk+kpFS
1D9SHjx24JShCiAfonNVjQfRr6KjwwKnKAzI+Z8ljRCikmLN9A5rPegvPE1by++/
i132TIECgYAiDd+OSokfZYi8mqjIoMI946+Hlb7lisb7CXksM69A+oWJrfkCwOMq
O3tExLbxtd7KZuAg1xH2thimIeT6tuCbCSAFGzr4EWCe7iavVzevHr98ivPLYXte
dyWl3YlvqO+SUuieGvHISlekblMO/4tcUscmKmo+FgkMroBsePcdEA==
-----END RSA PRIVATE KEY-----

Затем откройте свой index.js и добавьте следующее:

index.js

const jwt = require('jsonwebtoken');
const fs = require('fs')
app.get('/jwt', (req, res) => {
    let privateKey = fs.readFileSync('./private.pem', 'utf8');
    let token = jwt.sign({ "body": "stuff" }, "MySuperSecretPassPhrase", { algorithm: 'HS256'});
    res.send(token);
})

Когда мы открываем http://localhost:3000/jwt в нашем браузере после перезапуска приложения, мы должны увидеть возвращенный нам действительный веб-токен JSON:

http: // localhost: 3000 / jwt

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJib2R5Ijoic3R1ZmYiLCJpYXQiOjE1NTg4MTUyMzl9.3Z8G-kCEfr2Xch1FnaEAOeywcVs6aJZ3sbCARybWCgM

Замечательно, теперь у нас есть действующий JWT, который мы можем использовать для тестирования аутентификации, которую мы собираемся создать в следующей части этого руководства!

ПО промежуточного слоя аутентификации

Давайте посмотрим на функцию аутентификации, которая будет смотреть на входящий запрос и анализировать его на наличие заголовка Authorization.

index.js

function isAuthenticated(req, res, next) {
    if (typeof req.headers.authorization !== "undefined") {
        // retrieve the authorization header and parse out the
        // JWT using the split function
        let token = req.headers.authorization.split(" ")[1];
        let privateKey = fs.readFileSync('./private.pem', 'utf8');
        // Here we validate that the JSON Web Token is valid and has been 
        // created using the same private pass phrase
        jwt.verify(token, privateKey, { algorithm: "HS256" }, (err, user) => {
            
            // if there has been an error...
            if (err) {  
                // shut them out!
                res.status(500).json({ error: "Not Authorized" });
                throw new Error("Not Authorized");
            }
            // if the JWT is valid, allow them to hit
            // the intended endpoint
            return next();
        });
    } else {
        // No authorization header exists on the incoming
        // request, return not authorized and throw a new error 
        res.status(500).json({ error: "Not Authorized" });
        throw new Error("Not Authorized");
    }
}

Теперь, когда у нас есть эта isAuthorized функция, мы можем обновить нашу /secret конечную точку, чтобы использовать эту функцию в качестве промежуточного программного обеспечения.

index.js

app.get('/secret', isAuthorized, (req, res) => {
    res.json({ "message" : "THIS IS SUPER SECRET, DO NOT SHARE!" })
})

Если мы перезапустим наше приложение и снова попробуем нажать на конечную точку /secret, мы должны увидеть следующий ответ:

http: // localhost: 3000 / secret

{
    "error": "Not Authorized"
}

Отлично, это сработало в точности так, как ожидалось, и мы не можем получить доступ к нашей /secret конечной точке без соответствующего набора заголовков Authorization. Давайте попробуем поразить эту конечную точку с помощью команды curl, мы добавим заголовок Authorization и установим для него значение jwt вместе с действительным JWT, полученным с нашей /jwt конечной точки.

curl -H Авторизация: jwt« http: // localhost: 3000 / secret

{"message":"THIS IS SUPER SECRET, DO NOT SHARE!"}%

Замечательно, с этим допустимым JWT в заголовке Authorization мы смогли получить доступ к /secret конечной точке!

Заключение

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

Я задолбался. Что дальше?

На этом веселье не заканчивается, оно продолжается. Вы можете продолжать создавать новые вещи и узнавать что-то новое в других блогах, опубликованных Clever Programmer.

Впереди еще много клонов, советов и многого другого. Я знаю, что ты взволнован и готов, но тебе нужно подождать. Вы также можете проверить канал YouTube, если вас слишком волнует какой-нибудь крутой контент.

Поделитесь этим со всеми, кто, по вашему мнению, получит от этого пользу. Есть предложения? Не стесняйтесь ударить меня!

Увидимся в следующем!

Шрикар Кусуманчи