Реализуйте 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. Используйте useSession Hook, чтобы получить данные вошедшего в систему пользователя.
  • Строка 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: useSession Hook сообщит нам, вошел ли пользователь в систему.
  • Строка 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

Другой учебный материал

Заключение

NextAuth.js упростил разработчикам создание функций аутентификации пользователей в своих приложениях. Как следствие, это улучшает опыт разработчика. Более того, нам не нужно было создавать внешний сервер Express для построения нашей системы входа в систему. Все было сделано в Next.js, что обещало более быстрое и производительное приложение.

Если вы столкнулись с какими-либо проблемами, советую разобрать программу и поиграться с кодом. Спасибо, что дожили до конца!