Реализуйте Google OAuth в своем приложении Next.js с помощью NextAuth.js
В этой статье мы узнаем следующее:
- Использование NextAuth.js с Next.js.
- Сторонняя аутентификация Google с помощью NextAuth.js.
- Поддержание связи между пользователями и таблицами Notes.
- Выполнение операций CRUD с нашей базой данных для чтения и записи заметок.
Вступление
Итак, вы создали потрясающий блог с Next.js, который ежедневно привлекает миллионы пользователей. Чтобы получать доход от написания статей, вам пришла в голову идея заблокировать статьи за платный доступ. Так читатели смогут вас поддержать. Чтобы реализовать такую идею, вам потребуется выполнить следующие шаги:
- Создайте систему входа в систему.
- Убедитесь, что зарегистрированный пользователь подписался на ваш сайт.
- Если они являются платными участниками, позвольте им продолжить наслаждаться вашим контентом.
- С другой стороны, если посетитель не вошел в систему, предложите ему создать учетную запись или войти в систему.
Однако давайте посмотрим правде в глаза: аутентификация - это боль. Для этого требуется тонна кода, а в некоторых случаях обслуживание затруднено.
Здесь на помощь приходит Next-Auth.js. Он не только упрощает процесс создания аутентификации пользователей, но также имеет следующие преимущества:
- Файлы cookie: в паспорте, если вы перезапустите свой сервер, вы автоматически выйдете из системы. В Next-Auth.js это не проблема, поскольку он уже использует файлы cookie для хранения данных сеанса.
- Чрезвычайно безопасный: Next-Auth.js активно продвигает варианты входа без пароля. Кроме того, он использует токены CSRF в своем коде, чтобы гарантировать, что ваш проект не будет содержать эксплойтов и других лазеек.
Пришло время писать код!
Настройка проекта
Инициализация репозитория
Этот шаг довольно прост. Чтобы создать экземпляр проекта Next.js, выполните следующую команду терминала:

Затем создайте файл .env.local в корне вашего проекта следующим образом:

Здесь мы будем хранить переменные среды.
Теперь приступим к установке наших зависимостей.
Установка модулей
В этом проекте мы будем использовать следующие модули:
next-auth: Суть нашего проекта. Эта библиотека будет обрабатывать все наши процессы, основанные на аутентификации.mongodb: Поскольку мы будем использовать сервер MongoDB, Next-Auth.js будет использовать пакетmongodbкак одну из своих зависимостей.mongoose: Для взаимодействия с нашей базой данных и выполнения операций CRUD с нашими коллекциями.
Чтобы установить эти пакеты, выполните следующую команду терминала:

Давайте теперь инициализируем наш сервер MongoDB.
Настройка MongoDB Atlas
Рекомендую использовать MongoDB Atlas. Он настраивает для вас сервер базы данных в облаке без какой-либо дополнительной настройки.
Сначала войдите на страницу Атласа и выполните следующие действия, чтобы создать свой первый кластер. Когда это будет сделано, нажмите Подключиться:

Затем выберите «Разрешить доступ из любого места»:

Теперь создайте свое имя пользователя и пароль и нажмите «Создать пользователя базы данных», чтобы зарегистрироваться в качестве пользователя. Когда это будет сделано, нажмите «Подключить ваше приложение»:

Затем вы получите строку подключения. Скопируйте это и вставьте в свой .env.local файл:

Теперь займемся созданием учетных данных Google OAuth.
OAuth с Google
Перейдите в Консоль разработчика Google и нажмите Выбрать проект. Затем нажмите Новый проект:

Когда это будет сделано, перейдите на боковую панель и нажмите «API и службы». Затем нажмите «Панель управления»:

На верхней панели нажмите «Включить API и службы». Вы попадете на страницу библиотеки API. Найдите «Google+» и включите его.

Теперь веб-сайт приведет вас на страницу «Включенные API». Сначала выберите «Учетные данные», а затем щелкните ссылку «Учетные данные в API и службах»:

Это перенаправит вас на домашнюю страницу. Нажмите «Создать учетные данные», а затем «Идентификатор клиента OAuth»:

Выберите «Веб-приложение»:

Теперь дайте вашему приложению имя. Когда это будет сделано, прокрутите вниз до «URI авторизованного перенаправления» и настройте его следующим образом:

Теперь нажмите «Создать», чтобы сообщить Google о создании нашего клиента OAuth. Вы получите свой идентификатор клиента и секрет:

Скопируйте их в свой .env.local файл следующим образом:

И мы, наконец, закончили! В следующем разделе мы обсудим нашу файловую структуру.
Файловая структура проекта
В корневом каталоге вашего проекта создайте следующие папки:
models: Будем хранить наши модели Mongoose.helpers: будет содержать все наши функции промежуточного программного обеспечения.components: хранит наши пользовательские компоненты, которые можно повторно использовать в других файлах.
Теперь войдите в свою папку pages и создайте эти папки:
notesв каталоге/api: будет обрабатывать/api/notes/маршруты.authв каталоге/api: будет содержать логику аутентификации пользователя.notes: будет обрабатывать маршрут/notes.
В итоге структура вашего проекта должна выглядеть так:

Готово! А теперь давайте попробуем построить внутреннюю часть нашей системы входа в систему.
Создание нашей системы входа в систему
Настройка бэкэнда
В своем проекте перейдите в каталог /pages/api/auth и создайте файл с именем [...nextauth.js]. Это означает, что все маршруты, начинающиеся с /api/auth, будут обрабатываться файлом [...nextauth].js.
В /pages/api/[...nextauth].js напишите следующий фрагмент кода:
- Строки 1-2: Импортируйте модуль
NextAuthдля реализации аутентификации. Затем импортируйте пакетProviders, чтобы сообщить Next.js, что мы будем использовать стороннюю аутентификацию. - Строки 6-11: Сообщите Next.js, что мы будем использовать только Google OAuth для этого проекта. Мы также передаем наш идентификатор Google и секретный ключ через переменные среды.
- Строка 13: используйте наш экземпляр базы данных MongoDB. Строка подключения передается через переменные среды.
- Строка 14: Наш обратный вызов
sessionбудет запущен, когда пользовательский сеанс будет проверен. - Строка 16. Раскройте свойство сеанса
id, чтобы мы могли получить к нему доступ. Это будет полезно при создании заметок, связанных с каждым пользователем.
Давайте теперь создадим наш интерфейс.
Создание нашего интерфейса
В /pages/index.js замените весь свой код следующим:
- Строка 3. Используйте
useSessionHook, чтобы получить данные вошедшего в систему пользователя. - Строка 7: проверьте, не вошел ли пользователь в систему (если
sessionне имеет значения). Если да, предложите пользователю войти в систему. МетодsignInобрабатывает функции входа. - Строка 19: Если пользователь вошел в систему (если
sessionимеет значение), то показать возможность выхода. МетодsignOutсделает это за нас. - Строка 21: отображение имени пользователя на главной странице.
Последний шаг - изменить наш _app.js файл. В /pages/_app.js сначала импортируйте модуль Provider следующим образом:

Теперь найдите в /pages/_app.js следующий фрагмент кода:

Измените это так:

- Строки 2–4: оберните наш
ComponentтегамиProvider. Это сделает наши данные сеанса постоянными на всех маршрутах.
Запустите код. Это будет результат:

Большой! Наш код работает как задумано. Теперь создадим наш Note компонент.
В итоге ваш /pages/_app.js файл должен выглядеть так:
Компонент Note
В папке components создайте файл с именем Note.js. В этом файле напишите следующий фрагмент кода:
- Строка 4: Наш
Noteкомпонент будет иметь два свойства:idиtitle. - Строка 5: этот
useRouterэкземпляр поможет нам выполнять перенаправление на стороне клиента. - Строка 7: Создайте функцию
sendDelete. - Строки 8–10: выполнение запроса
DELETEк маршрутуapi/notes/delete/{id}. Это скажет серверу идентифицировать нашу запись поid, а затем удалить ее. - Строка 11: После запроса
DELETEперенаправьте пользователя на/dashboard. - Строки 16-21: отобразите опору
title. Если щелкнуть, перенаправить пользователя на маршрут/notes/{id}. Это отобразит полную информацию о заметке. - Строки 22-24: перенаправляют пользователя на страницу
/notes/update/${id}. Это позволит клиенту обновить указанный документ. - Строка 25: Если щелкнуть, вызвать функцию
sendDelete.
В следующем разделе мы создадим нашу страницу панели инструментов.
Страница панели инструментов
В папке /pages создайте файл с именем dashboard.js. В этом файле будут показаны все сохраненные заметки пользователя.
В pages/dashboard.js напишите следующий код:
- Строка 6:
useSessionHook сообщит нам, вошел ли пользователь в систему. - Строка 11: отображение приветственного сообщения, если пользователь вошел в систему.
- Строки 13–14: при нажатии пользователь будет перенаправлен на маршрут
notes/add. - Строка 15: Эта кнопка позволяет пользователю выйти из системы. В случае успеха наше приложение перенаправит их на страницу
/.
Запустите код. Должен быть результат:

Однако заставлять пользователя вручную переходить на страницу /dashboard - не очень удобно. Нам нужно это исправить.
В pages/index.js найдите следующий фрагмент кода:

Измените это так:

- Строка 3: Когда пользователь входит в систему, перенаправьте его на страницу
dashboard.
Запустите код. Должен быть результат:

Готово! Пришло время создать на его основе наше приложение для создания заметок.
В итоге /pages/index.js должен выглядеть так:
Приложение "Заметки"
Модель Notes
В папке /models создайте файл с именем Note.js. В /models/Note.js напишите следующий код:
- Строка 3: Определите наш
noteSchema. - Строка 4: В нашей коллекции будет поле
user, которое будет связано с вошедшим в систему пользователем. Это позволяет нам создать реляционную базу данных. - Строки 8–9: Наша модель будет иметь поля
titleиbody, которые будут содержать строковые значения. - Строка 13: Экспортируйте нашу
Noteмодель, которая будет производным отnoteSchema.
Давайте теперь поработаем над связыванием нашей базы данных с этим проектом.
Подключение к базе данных
В папке helpers создайте файл с именем dbConnect.js. Как следует из названия, этот файл содержит конфигурацию нашей базы данных.
В helpers/dbConnect.js напишите следующий код:
- Строки 3–9: Получите нашу строку подключения MongoDB от
.env.local. Если его нет, то выдает ошибку. - Строка 16: Здесь мы используем Globals для поддержания кэшированного соединения. Это предотвратит рост количества подключений во время использования.
- Строка 28-34: Укажите конфигурацию нашей базы данных.
- Строка 37: подключение к базе данных.
- Строка 45: Наконец, экспортируем нашу
dbConnectфункцию. Теперь мы можем использовать его в нашем проекте.
Мы сделали! Давайте теперь поработаем с CRUD-операциями с нашими заметками.
Добавление заметки
Перейдите в папку /pages/api/notes и создайте файл с именем add.js. Этот файл скажет нашей базе данных вставить запись.
В /pages/api/notes/add.js напишите следующий код:
- Строка 6: Метод
getSessionвернет данные пользователя. - Строка 8: Подключитесь к базе данных перед выполнением любых критически важных для базы данных функций.
- Строка 10: Если клиент не вошел в систему, отправьте сообщение об ошибке.
- Строка 14: Проверить, был ли выполнен запрос
POST. - Строки 15–16. Если верно, то создайте
Noteдокумент с полемuser, указывающим наidвошедшего в систему пользователя. Это позволяет нам строить отношения. - Строки 17-18: поля
titleиbodyбудут содержать введенные пользователем данные. - Строки 21-24: Сохраните документ и выйдите из сохраненной записи.
- Строка 26: Завершить ответ.
Давайте теперь закодируем наш интерфейс для этой функции. В /pages/notes создайте файл с именем add.js.
В pages/notes/add.js напишите следующий код:
- Строка 7: Создайте нашу функцию
addNote. - Строки 10-19: отправьте
POSTзапрос на/api/notes/add. Это скажет нашему серверу добавить данные в базу данных. Наши поляbodyиtitleбудут иметь значенияinput. - Строка 20: Когда запрос завершен, перенаправьте пользователя на
/dashboard. - Строка 26: Когда форма отправлена, вызовите функцию
addNote.
Запустите код. Должен быть результат:

Посмотрите на консоль:

Это доказывает, что наш документ был сохранен в базе данных. Наш код работает так, как ожидалось.
Теперь мы будем работать над отображением всех наших заметок.
Отображение наших заметок
Давайте сначала разработаем внутренний код этого раздела. В папке /pages/api/notes создайте файл с именем list.js. В этом файле напишите следующий код:
- Строка 11: Найдите все заметки пользователя. Это делается путем фильтрации заметок, содержащих поле
userполяidтекущего пользователя. Наконец, используйте методlean, чтобы вернуть документы в формате JSON. - Строка 12: отправьте результаты клиенту в формате JSON.
- Строка 13: Если пользователь не вошел в систему, вернуть ошибку.
Теперь поработаем с нашим интерфейсом. В /pages/dashboard.js добавьте следующий фрагмент кода:
- Строка 1: функция
getServerSidePropsполучит данные с сервера. - Строка 3: Создайте наши заголовки, чтобы сообщить NextAuth.js, что мы уполномочены просматривать наши документы.
- Строка 4: Выполните
FETCHзапрос к нашему серверу и отправьте эти заголовки. - Строка 6: Если возвращенные данные содержат ошибку, вместо этого перенаправьте пользователя на маршрут
/. - Строка 14: отправьте возвращенные данные как реквизиты.
Затем в /pages/dashboard.js найдите следующий фрагмент кода:

Измените это так:

Теперь мы можем использовать данные, возвращаемые сервером, в нашем компоненте.
В этом же файле найдите свой return блок:

Замени его так:

- Строка 2: Используйте функцию
mapдля отображения наших данных. - Строка 4: Каждый объект будет отображаться с компонентом
Note.
Запустите код. Должен быть результат:

Наш код работает! Давайте теперь поработаем над чтением конкретного документа.
В итоге /pages/dashboard.js должно выглядеть так:
Чтение заметки
В качестве первого шага нам нужно закодировать бэкэнд. В каталоге /pages/api/notes создайте файл с именем [id].js. Здесь напишите следующий код:
- Строка 10. Найдите заметку пользователя с конкретным
id. - Строка 12: вернуть документ в формате JSON.
Теперь нам нужно создать наш интерфейс. В папке /pages/notes создайте файл с именем [id].js. Это означает, что этот файл будет обрабатывать маршрут /pages/notes/{id}. Здесь {id} - это id нашей заметки.
В /pages/notes/[id].js напишите следующий код:
- Строка 1: свойство
dataсодержит наши данные, которые мы хотим отобразить. - Строки 6-7: отображают поля
titleиbodyнашего объекта. - Строка 14: Создайте функцию
getServerSidePropsдля получения данных с сервера. - Строки 18–22: выборка данных из базы данных и их возврат.
- Строки 24-31: Если была ошибка, вместо этого перенаправьте пользователя на
/. - Строка 33: вернуть данные в компонент
Specificв качестве свойств.
Запустите код. Должен быть результат:

Большой! Наш код работает так, как ожидалось.
На следующем шаге мы узнаем, как обновлять наши записи.
Обновление заметки
В каталоге /pages/api/note создайте папку с именем update. В этой папке создайте файл с именем [id].js.
В /pages/api/note/update/[id].js напишите следующий код:
- Строка 11: Проверить, был ли выполнен запрос
GET. - Строка 12: Если
true, найдите примечание с совпадающимid, которое находится в параметре URL-адреса. - Строка 13: Наконец, верните данные в формате JSON.
- Строка 16: Проверить, был ли выполнен запрос
PUT. - Строка 17: Найдите документ с совпадающим
idи затем обновите его. - Строка 22: Обновите поля
titleиbodyзначениями, введенными пользователем. - Строка 26: Завершить ответ.
Теперь напишем наш интерфейс. В папке /pages/notes создайте еще один каталог с именем update. Здесь создайте файл с именем [id].js.
В /pages/notes/update/[id].js напишите следующий код:
- Строка 3: Используйте опору
dataв нашем компоненте. Он будет содержать данные с сервера. - Строка 5: извлеките параметр
idиз URL-адреса. - Строка 7: Создайте функцию
updateNote. - Строка 10: Выполните
PUTзапрос кapi/notes/updateмаршруту и отправьте наши входные поляtitleиbodyв качестве полезной нагрузки. - Строка 20: По завершении запроса перенаправьте пользователя на страницу
/dashboard.
Когда это будет сделано, добавьте в тот же файл следующий код:
- Строка 6: После отправки формы запустите функцию
updateNote. - Строки 8-13: Создаем наш
inputэлемент. Его начальным значением будет полеtitleнашей заметки. - Строки 15-20: создайте наш
inputэлемент, который будет содержать полеbodyпримечания в качестве значения по умолчанию.
В качестве последнего шага нам нужно указать Next.js получить данные. Добавьте в этот файл следующий код:
Этот код функции идентичен коду файла /pages/notes/[id].js.
Запустите код. Это будет результат:

Вуаля! Результат оказался ожидаемым. Давайте теперь поработаем над удалением нашей записи.
В итоге /pages/notes/update/[id].js должен выглядеть так:
Удаление записи
В папке /pages/api/notes создайте каталог с именем delete. Здесь создайте файл с именем [id].js.
В /pages/api/notes/delete/[id].js напишите следующий код:
- Строка 11: Найдите заметку с совпадающими полями
idиuser. Если нашел, то удалите. - Строка 20: Завершить ответ.
Запустите код. Должен быть результат:

Готово! Результат оказался ожидаемым.
Дополнительные ресурсы
Репозиторий GitHub
Другой учебный материал
- Аутентификация с помощью NextJS-LogRocket
- Аутентификация NextJS с NextAuth - Джеймс Перкинс
- Создание клона Netflix с помощью Next.Js и Next Auth - Ли Робинсон
Заключение
NextAuth.js упростил разработчикам создание функций аутентификации пользователей в своих приложениях. Как следствие, это улучшает опыт разработчика. Более того, нам не нужно было создавать внешний сервер Express для построения нашей системы входа в систему. Все было сделано в Next.js, что обещало более быстрое и производительное приложение.
Если вы столкнулись с какими-либо проблемами, советую разобрать программу и поиграться с кодом. Спасибо, что дожили до конца!