Вы могли бы сказать, что такое магические ссылки? Что ж, если вы вошли в систему через электронную почту здесь, вы сделали это с помощью волшебной ссылки… одной, отправленной на ваш адрес электронной почты, с помощью которой вы можете аутентифицироваться в системе. Как правило, волшебная ссылка содержит общедоступный токен, срок действия которого быстро истекает, но при открытии ссылки его можно использовать для создания безопасного и долговечного токена.

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

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

Примечание: это основано на статье Жереми Друэ о создании волшебных ссылок с помощью Node.

Покажи мне код!

Это руководство предназначено для практических пользователей, поэтому начните с загрузки следующего примера проекта. Склонируйте Git, установите зависимости, загрузите config.js с вашими учетными данными SMTP-сервера (я использую AWS SES, но есть много других вариантов, таких как Mailgun и SendGrid), npm start, затем перейдите на http://localhost:8080/.

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



Каковы все эти зависимости?

body-parser: анализирует запросы API
cookie-parser: анализирует файл cookie, в котором будет находиться наш веб-токен JSON
joi: проверка данных для ввода данных в базу данных
knex: построитель запросов, совместимый с MSSQL, MySQL, PostgreSQL, SQLite3 и Oracle (включая аутентификацию Oracle Wallet)
запрос: позволяет серверу выполнять вызов API.

Как это работает?

Поскольку здесь много движущихся частей и зависимостей, я полагаю, что лучший способ объяснить это — просто погрузиться и объяснить, что делает каждый файл. Я попытался расположить описания в логическом порядке, чтобы у вас было достаточно информации для понимания каждой зависимости. Вот оно!

Если вы не знакомы с веб-токенами JSON, они представляют собой длинную строку закодированных символов, которые содержат данные JSON и дату истечения срока действия. Они служат отличным способом хранения и передачи данных (в данном случае адреса электронной почты нашего пользователя), не полагаясь на базу данных. Однако будьте осторожны с тем, как вы с ними обращаетесь; они статичны, и их невозможно пометить как «недействительные» после использования (для этого потребуется хранить их в базе данных, что противоречит цели), поэтому мы не можем допустить, чтобы они попали в чужие руки.

Чтобы приспособиться к этому, наша система сгенерирует два веб-токена JSON, которые я называю начальным и основным; первый из них является быстродействующим, который находится в виде строки запроса в волшебной ссылке (поэтому виден для истории браузера, журналов и т. д.), а второй является долгосрочным и хранится в файле cookie HttpOnly. Файл cookie HttpOnly недоступен для DOM и, следовательно, не может быть доступен для JavaScript через document.cookie, что затрудняет его захват и манипулирование.

Сервис/аутентификация.js

Этот файл содержит функции, с помощью которых сервер генерирует наши начальные и первичные токены.

Сервис/база данных.js

Это просто устанавливает соединение с базой данных. Вы заметите много бессмыслицы SQLite — это просто создание экземпляра локальной базы данных для целей этого примера проекта. Для правильной реализации вам понадобится что-то похожее на следующее:

Вы заметите, что я устанавливаю соединение с Knex, построителем запросов к базе данных, который возвращает массивы JSON объектов записей базы данных и использует приятный, чистый синтаксис JavaScript. Проверь это:

SQL-запрос:

SELECT * FROM user WHERE email = '[email protected]'

Эквивалент Knex:

Предположим, вы хотите использовать альтернативу Knex, чего-либо, что возвращает ответ JSON, будет достаточно.

Модель/account.js

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

Примечание. если вам интересно, почему он возвращает объекты, содержащие {'error': true}, а не выдает ошибки, это потому, что конечная точка API вызывает его (/api/accounts/register) интерпретирует эти ответы JSON и обрабатывает выдачу ошибок.

Сервис/mail.js

Это содержит логику, которая отправляет наше электронное письмо с волшебной ссылкой. Вам, вероятно, не нужно будет изменять это; вам нужно только изменить конфигурацию SMTP в config.js.

Контроллер/accounts-login.js

Это конечная точка API для /api/accounts/login. Это первый шаг в процессе аутентификации для существующих пользователей. Во-первых, мы должны проверить наши данные, прежде чем запускать их в базе данных. Джой быстро справляется с этим:

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

Промежуточное ПО/authentication.js

Это промежуточное ПО будет использоваться только в нашей конечной точке API /api/accounts/init. Все, что мы здесь делаем, — это используем express-jwt для декодирования токена, предоставленного строкой запроса, и помещения его в контекст запроса.

Контроллер/учетные записи-init.js

Это конечная точка нашего API /api/accounts/init. Благодаря промежуточному ПО для аутентификации адрес электронной почты пользователя теперь доступен в контексте запроса как req.user. Он использует службу проверки подлинности для создания основного маркера и создания файла cookie авторизации HttpOnly для его сохранения. После создания клиент перенаправляется в каталог верхнего уровня. После перенаправления сервер распознает, что у них теперь есть авторизационный файл cookie, и предоставит им dashboard.html.

Контроллер/accounts-me.js

Это конечная точка нашего API /api/accounts/me. Это позволяет получить сведения о пользователе из базы данных с помощью запроса «найти» (SELECT from user) из model/account.js. Вот как dashboard.html извлекает имя пользователя.

Контроллер/учетные записи-register.js

Это конечная точка нашего API /api/accounts/register. В примере проекта наша HTML-форма входа в систему (public/login.html) отправляет сюда имя пользователя и пароль. Я объяснил процесс в комментариях ниже:

Контроллер/учетные записи-logout.js

Довольно просто — наша конечная точка API /api/accounts/logout уничтожает файл cookie авторизации, а затем перенаправляет клиента в каталог верхнего уровня. После перенаправления сервер распознает, что у них больше нет файла cookie авторизации, и выдаст им login.html.

Промежуточное ПО/verifyToken.js

Все вызовы API, сделанные во время аутентификации (например, /api/accounts/me, который возвращает информацию о вошедшем в систему пользователе), должны запускать это промежуточное ПО. Он проверит, что токен, хранящийся в файле cookie авторизации, является законным, и передаст адрес электронной почты пользователя вместе с запросом. Если токена нет или в процессе проверки произошла ошибка, он не сможет выполнить вызов API.

Последний файл, который я не объяснил, это server.js. Это устанавливает некоторые необходимые зависимости, размещает конечные точки API и обслуживает файлы, как и должен делать хороший сервер. Теперь, когда все части на месте, у вас теперь будет отличный портал для входа в систему по волшебной ссылке в никуда! Наслаждайтесь его славой без пароля и имени пользователя. Я надеюсь, что вы нашли эту статью полезной и интуитивно понятной — не стесняйтесь обращаться, если у вас есть какие-либо вопросы.

Джо Койл любит работать удаленно и является большим поклонником JavaScript. Вы можете ознакомиться с его портфолио на сайте joecoyle.net или в его профиле на LinkedIn.