2.4. Создание аутентификации на Node.js

Разберём, как подключить систему, гарантирующую, что доступ к сохранённым данным будет предоставлен только пользователю, которому они принадлежат. Это нужно для приложений с пользовательским входом (логин и пароль), например, админки сайта, личного кабинета, интернет-магазинов или форумов.

Для этого воспользуемся Auth0 — платформой авторизации и аутентификации, которая возьмёт на себя функции сервера.

Мы напишем аутентификацию через Auth0 на Node.js и библиотеке Express OpenID Connect.

Приступим. Если вы начинаете проект с нуля или хотите потренироваться, то инициируем проект:

npm init

Если у вас уже есть проект, то начинайте с этого шага. Установите библиотеку Express OpenID Connect и пакет dotenv, который поможет работать c файлами .env:

npm install express express-openid-connect dotenv

Теперь зарегистрируйте проект в Auth0: страница регистрации

Регистрация проекта в Auth0

Выберите подходящий тип аккаунта:

Выбор типа аккаунта в Auth0

Во вкладке Applications выберите Applications:

Выбор Applications в Auth0

Создайте новый проект, нажав Create Application:

Создание нового проекта в Auth0

Введите название проекта, выберите тип проекта Regular Web Application, нажмите кнопку Create:

Настройки проекта в Auth0

Перейдите во вкладку Settings:

Настройки проекта в Auth0

Прокрутите вниз до пункта Allowed Callback URLs и добавьте http://localhost:3000/callback. Это необходимо для того, чтобы Auth0 провела необходимую аутентификацию.

Allowed Callback URLs в Auth0

В Allowed Logout URLs добавьте http://localhost:3000:

Allowed Logout URLs в Auth0

Прокрутите вниз и нажмите Save Changes:

Save changes в Auth0

Библиотека Express OpenID Connect предоставляет маршрутизатор аутентификации, чтобы добавить аутентификацию к приложению. Теперь нужно настроить маршрутизатор со следующими ключами конфигурации:

  • authRequired — требуется ли аутентификация для всех маршрутов;

  • auth0Logout — выход из системы;

  • baseURL — URL расположения приложения;

  • secret — длинная произвольная строка, минимум 32 символа;

  • issuerBaseURL — защищённый URL-адрес, указанный в настройках приложения;

  • clientID — Client ID, указанный в настройках приложения.

Сделаем это. Создадим файл app.js, импортируем express и пакет dotenv:

const exprees = require('express');
const app = express();
require('dotenv').config();

Укажем порт 3000 по умолчанию или другой открытый:

const port = process.env.PORT || 3000;

Начнём слушать порт и выведем в консоль сообщение, если всё в порядке:

app.listen(port, () => {
  console.log('слушает порт ${port}');
});

Библиотеке нужны ISSUER_BASE_URL, CLIENT_ID, BASE_URL и SECRET, чтобы запрашивать и принимать аутентификацию. Их можно настроить с помощью переменных:

ISSUER_BASE_URL=https://YOUR_DOMAIN

CLIENT_ID=YOUR_CLIENT_ID

BASE_URL=https://YOUR_APPLICATION_ROOT_URL

SECRET=LONG_RANDOM_VALUE

ISSUER_BASE_URL и CLIENT_ID берём из настроек приложения, пункты Domain и Client ID соответственно:

ISSUER_BASE_URL и CLIENT_ID в настройках

BASE_URL — это локалхост, а SECRET — длинная произвольная строка, минимум 32 символа.

Всё это прописываем в файле .env:

ISSUER_BASE_URL=https://dev-84-b0-zj.us.auth0.com
CLIENT_ID=5R39ZIpwSagbpmItMriRG9mGneJFy
BASE_URL=http://localhost:3000
SECRET=sahfaskjwesahfaskjwesahfaskjwedd

Теперь в файл app.js добавляем конфигурации и вписываем переменные из файла .env:

const { auth } = require('express-openid-connect');
app.use(
  auth({
    issuerBaseURL: process.env.ISSUER_BASE_URL,
    baseURL: process.env.BASE_URL,
    clientID: process.env.CLIENT_ID,
    secret: process.env.SECRET,
    idpLogout: true,
  })
);

Также давайте используем пакет nodemon, который перезапускает сервер при изменении файлов.

И запустим проект командой nodemon app.js:

nodemon app.js

В консоли:

Start app.js

В браузере:

В браузере после старта

Нажмём зелёную кнопку. Нас перенаправили на локалхост с сообщением о том, что не удаётся получить директорию:

В браузере после старта

Настроим директорию в app.js:

app.get('/', (req, res) => {
  res.send(req.oidc.isAuthenticated() ? 'Logged in' : 'Logged out');
});

Выведем сообщение Logged in, если пользователь авторизован, и сообщение Logged out, если не авторизован. В браузере теперь отображается верное сообщение:

Авторизован

Теперь мы знаем, что пользователь авторизован.

Допишем authRequired со значением false, чтобы пользователю не нужно было авторизовываться при каждом входе. И auth0Logout со значением true для возможности выйти из учётной записи:

app.use(
  auth({

    authRequired: false;
    auth0Logout: true;

    issuerBaseURL: process.env.ISSUER_BASE_URL,
    baseURL: process.env.BASE_URL,
    clientID: process.env.CLIENT_ID,
    secret: process.env.SECRET,
    idpLogout: true,
  })
);

Проверим. Перейдём по URL localhost:3000/logout и увидим, что мы вышли из учётной записи:

Вышли из учётной записи

Далее мы будем перенаправлены опять на директорию localhost:3000 с сообщением Logged out:

Вышли из учётной записи на localhost:3000

Далее, если перейти по URL localhost:3000/login, увидим, что теперь можно авторизовываться разными способами:

Авторизация

При авторизации вас перенаправят на локалхост с сообщением Logged in:

Перенаправление с сообщением Logged in

Готово!