Статьи

Аутентификация с помощью Google

GooglePlus-Logo-Official

У меня есть блестящая идея. Я собираюсь создать сайт, который облегчает *insert verb*ing для *insert noun* . Хотя есть проблема: мне нужны люди, чтобы иметь возможность войти в систему, но я не хочу заниматься регистрацией пользователей, сбросом их паролей и т . Д. Поэтому я решил, что использование входа в Google — лучший вариант. Как я могу это реализовать?

С комбинацией Devise и Omniauth процесс не так болезнен, как кажется. По сути, я собираюсь использовать процесс, изложенный в спецификации OAuth 2.0, для реализации аутентификации для моего NounVerber.

Подтяните подтяжки

rails new это хорошо, но мне нравится немного больше функциональности из коробки, поэтому я собираюсь использовать драгоценный камень Susbders от Thinkbot . Давайте создадим наше приложение:

 $ gem install suspenders $ suspenders login_with_google # lots and lots of rails app creation output $ cd login_with_google 

Во-первых, нам нужно создать несколько страниц для посещения:

  • home — корневая страница, которая не защищена.
  • secure — только просмотр с логином.

Мы создадим контроллер pages который имеет эти методы. Очевидно, это просто заполнитель, так как логин Google для статического контента будет несерьезным:

 $ rails g controller pages home secure 

Установите корневую страницу на pages#home :

 # config/routes.rb Rails.application.routes.draw do root to: 'pages#home' get 'pages/secure' end 

Потрясающие. Но прежде чем мы начнем создавать аутентификацию, нам нужно создать модель User. Мы используем только API Google для аутентификации, поэтому нам понадобятся только следующие атрибуты:

  • uid — уникальный идентификатор провайдера (Google) для нашего пользователя
  • provider — провайдер аутентификации
  • name — имя сохранено из их профиля Google
  • email — электронная почта, сохраненная из их профиля Google

Давайте сгенерируем эту модель:

 $ rails g model user uid provider name email 

Это должно создать нашу модель пользователя. Проверив миграцию, мы можем не беспокоиться о rake db:migrate .

Примечание. Поскольку Suspenders пытается быть готовым к Heroku, для работы миграций на вашем компьютере должен быть установлен PostgreSQL. Если вы просто хотите использовать SQLite3, поменяйте местами конфигурацию базы данных и гемы.

Добавление Devise и Omniauth

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

Сначала добавьте драгоценные камни:

 # Gemfile # ... gem 'devise' gem 'omniauth-google-oauth2' # ... 

Драгоценный камень omniauth-google-oauth2 — это то, что делает магию. Теперь bundle install и мы готовы к работе!

Чтобы это работало правильно, настройте несколько вещей:

  1. Установить Devise
  2. Настройте промежуточное программное обеспечение стойки
  3. Добавить Devise маршруты
  4. Добавить Devise к модели User
  5. Создать контроллер обратных вызовов
  6. Добавить аутентификацию на защищенные страницы

Установка Devise

Devise предоставляет команду установки для легкой настройки:

 $ rails g devise:install 

Настройка промежуточного программного обеспечения Omniauth Rack

Нам нужно создать инициализатор промежуточного программного обеспечения omniauth для аутентификации нашего клиентского приложения в Google. Это делается с помощью идентификатора клиента и секрета:

 # 'config/initializers/omniauth.rb' Rails.application.config.middleware.use OmniAuth::Builder do provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"] end 

Вау, подожди минутку! Мы только что попросили учетные данные, которые еще не существуют? Да, мы сделали. Нам нужно, чтобы Google генерировал их для нас.

Сначала перейдите на https://console.developers.google.com/ и создайте проект. Затем, под «API & auth» на боковой панели, нажмите «Credentials», а затем нажмите «Create new Client ID». Теперь скопируйте и вставьте учетные данные, которые вы получите, в свой файл .env как GOOGLE_CLIENT_ID и GOOGLE_CLIENT_SECRET . Suspenders предоставляет гем dotenv, который позволяет нам помещать переменные среды в файл .env, который запускается Rails при запуске. Это хорошая практика, которая гарантирует, что мы не помещаем секреты в систему контроля версий.

Еще одна вещь, которая может сбить вас с толку позже — это включение API. Для нашей цели нам просто нужен Google+ API. Перейдите на страницу своего проекта в Google, нажмите «API» и включите Google+.

Добавление разработанных маршрутов

Devise создает метод devise_for для создания пользовательских маршрутов для аутентификации, и нам нужно добавить маршруты для обработки потока OAuth:

 # 'config/routes.rb' devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" } 

Обратите внимание, что мы определили контроллер, который еще не существует. Мы вернемся к этому позже.

Добавление устройства в модель пользователя

У Devise есть еще один вспомогательный метод devise , который настраивает нашу модель для использования функций Devise. Добавьте следующее в модель User :

 # 'app/models/user.rb' devise :omniauthable, omniauth_providers: [:google_oauth2] 

Создание контроллера обратных вызовов

Когда пользователь входит в систему, он отправляется поставщику (в данном случае Google), а затем возвращается на исходный сайт по URL-адресу обратного вызова. Этот обратный вызов выполняет аутентификацию для пользователя на основе данных от провайдера. Давайте создадим этот обратный вызов:

 # 'app/controllers/users/omniauth_callbacks_controller.rb' class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def google_oauth2 @user = User.from_omniauth(request.env['omniauth.auth']) if @user.persisted? sign_in_and_redirect root_path, event: :authentication else redirect_to root_path, flash: { error: 'Authentication failed!' } end end end 

Метод google_oauth2 в контроллере обратного вызова будет применяться только к маршруту: /users/auth/google_oauth2/callback . Когда этот метод вызывается, он находит существующего пользователя или создает нового. Если пользователь существует или только что был создан, он вошел в систему и перенаправлен на корневой путь. В противном случае пользователь перенаправляется обратно в корень и мигает ошибка.

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

Подожди минуту! Мы вызвали метод с именем User.from_omniauth , который не существует! Давайте перейдем к модели User и создадим ее. Этот метод примет хэш пользовательских аргументов и найдет или создаст нового пользователя:

 # 'app/models/user.rb' ... def self.from_omniauth(auth) where(provider: auth[:provider], uid: auth[:uid]).first_or_create do |user| user.name = auth[:info][:name] user.email = auth[:info][:email] end end ... 

Добавление аутентификации на защищенные страницы

Мы уже многое сделали, так что давайте сделаем это и проверим аутентификацию. Откройте браузер и перейдите по http://localhost:3000/users/auth/google_oauth2 и выполните шаги (вы знаете, что делать). Если это работает, вы будете перенаправлены на пустую страницу! Как здорово! Почти революционный! А если серьезно, то для обычного пользователя это выглядит так, как будто он абсолютно ничего не сделал.

Нам нужно добавить небольшой раздел информации для входа на нашу домашнюю страницу. Откройте приложение / view / home :

Скучно.

 # 'app/views/pages/home.html.erb' <h1>Pages#home</h1> <p>Find me in app/views/pages/home.html.erb</p> 

Захватывающе!

 # 'app/views/pages/home.html.erb' <div class="container"> <% if user_signed_in? %> <p>Welcome back, <a href="mailto:<%= current_user.email %>"><%= current_user.name %></a>!</p> <% else %> <p><%= link_to 'Sign in.', user_omniauth_authorize_path('google_oauth2') %></p> <% end %> </div> <h1>Pages#home</h1> <p>Find me in app/views/pages/home.html.erb</p> 

Теперь, если мы посетим домашнюю страницу, вот что мы получаем!

Logged in With Google

Теперь мы вошли в систему с Google! Трудная часть сделана.

Только авторизованный персонал

Помните, когда мы создавали наш контроллер страниц? Хорошо, эта secure страница пригодится сейчас.

Сначала добавьте get 'pages/secure' в config / rout.rb, а затем откройте контроллер страниц. Мы собираемся убедиться, что пользователь вошел в систему перед просмотром защищенной страницы.

 # 'app/controllers/pages_controller.rb' class PagesController < ApplicationController def home end def secure unless user_signed_in? redirect_to root_path, flash: { error: 'Please sign in first.' } end end end 

Если мы попытаемся перейти по http://localhost:3000/pages/secure без входа в систему, мы вернемся на домашнюю страницу с мигающей ошибкой. И вот оно!

Вывод

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

Весь пример кода проекта можно найти на GitHub .