Как добавить Github OmniAuth аутентификацию?
Если в Rails-приложении уже используется Devise, легко!
Введение
При разработке Rails-приложений библиотека Devise зачастую становится основным инструментом для аутентификации пользователей. Однако в современных веб-приложениях часто требуется предоставить возможность авторизации через сторонние сервисы, такие как GitHub. Это можно легко реализовать с помощью библиотеки omniauth-github, которая интегрируется с Devise и добавляет OmniAuth-аутентификацию.
Решение
Шаг 1: Регистрация OmniAuth приложения на GitHub
Первым шагом необходимо зарегистрировать OmniAuth-приложение на GitHub, сделав это по ссылке.
Пример Homepage URL:
http://localhost:4000
Пример Authorization callback URL:
http://localhost:4000/users/auth/github/callback
После успешной регистрации OmniAuth приложения, вы получите GITHUB_KEY
и GITHUB_SECRET
, которые понадобятся для дальнейшей настройки.
Шаг 2: Настройка Rails приложения
Теперь, когда ваше OmniAuth-приложение создано, выполните следующие шаги:
- Включите необходимые библиотеки. Добавьте следуюшие гемы в
Gemfile
# Gemfile gem 'omniauth-github' gem 'omniauth-rails_csrf_protection'
- Выполните команду для установки гемов:
bundle install
- Настройте OmniAuth для работы с GitHub в файле
config/initializers/devise.rb
. Добавьте следующую строку:# config/initializers/devise.rb config.omniauth :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET']
и создайте в ваш
.env
файл переменныеGITHUB_KEY
иGITHUB_SECRET
со скопированными выше значениями из зарегистрированного GitHub приложения. - Добавьте необходимые поля для хранения данных OmniAuth в модель пользователей. Для этого создайте и примените миграцию:
rails g migration AddProviderAndUidToUsers provider:string uid:string rails db:migrate
- Обновите модель User, чтобы она поддерживала OmniAuth-аутентификацию:
# app/models/user.rb devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:github]
- Создайте контроллер для обработки OmniAuth-колбэков:
# app/controllers/users/omniauth_callbacks_controller.rb class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController skip_before_action :verify_authenticity_token, only: :github def github @user = User.from_omniauth(request.env['omniauth.auth']) if @user sign_in_and_redirect(@user, event: :authentication) set_flash_message(:notice, :success, kind: 'Github') else redirect_to new_user_registration_url end end def failure redirect_to root_path, alert: "Failure. Please try again, #{params[:message]}" end end
- Добавьте метод для обработки данных OmniAuth в модель
User
:# app/models/user.rb def self.from_omniauth(auth) find_or_create_by(provider: auth.provider, uid: auth.uid) do |user| user.email = auth.info.email user.password = Devise.friendly_token[0, 20] user.name = auth.info.name end end
- Добавить кнопку аутенфикации через GitHub на форму регистрации
<% provider = 'github' %> <%= button_to omniauth_authorize_path(resource_name, provider), id: "#{provider}-button", data: { turbo: false } %>
Шаг 3: Тестирование
Для тестирования будут использоваться популярные библотеки rspec
и faker
.
- Создайте
authorazation.rb
файл в папкеspec/support/shared
- В этом файле создайте
shared_examples
(подробнее о данной фиче тут) с контекстом# spec/support/shared/authorization.rb shared_examples 'with GitHub authentication', :with_github_auth do context 'when authenticated with Github' do before do OmniAuth.config.test_mode = true OmniAuth.config.add_mock(:github, OmniAuth::AuthHash.new(Faker::Omniauth.github)) Rails.application.env_config['devise.mapping'] = Devise.mappings[:user] Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[:github] post user_github_omniauth_callback_path follow_redirect! end after do OmniAuth.config.test_mode = false Rails.application.env_config['omniauth.auth'] = nil end it 'successfully authenticated' do expect(response).to have_http_status(:success) end end end
- В тестах, где требуется аутентификация пользователя через GitHub, добавьте вызов созданного shared_examples:
it_behaves_like 'with GitHub authentication'
# Пример describe 'POST /competitions' do subject(:create_competition_response) do post '/competitions/', params: { name: 'New Competition' } end it_behaves_like 'with GitHub authentication' end
Bonus
Если вы хотите улучшить функционал и использовать данные GitHub, даже если пользователь не был сохранён при авторизации через OmniAuth, можно автоматически подставлять их при дальнейшей регистрации. Это позволит упростить процесс для пользователей.
- Обновите метод
github
в контроллереUsers::OmniauthCallbacksController
, чтобы сохранять данные из сессии, если пользователь не создан:# app/controllers/users/omniauth_callbacks_controller.rb def github @user = User.from_omniauth(request.env['omniauth.auth']) if @user sign_in_and_redirect(@user, event: :authentication) set_flash_message(:notice, :success, kind: 'Github') else session['devise.github_data'] = request.env['omniauth.auth'].except(:extra) redirect_to new_user_registration_url end end
- В модели
User
переопределите метод библиотеки Devisenew_with_session
, чтобы автоматически заполнять поля регистрации из данных GitHub, сохранённых в сессии:# app/models/user.rb def self.new_with_session(params, session) super.tap do |user| if data = session['devise.github_data'] && session['devise.github_data']['info'] user.email = data['email'] if user.email.blank? user.name = data['name'] if user.name.blank? end end end
Теперь, если регистрация прервана, пользователь сможет продолжить её, а данные из GitHub будут автоматически подставлены.
Заключение
Добавление GitHub OmniAuth через Devise и OmniAuth — это простой и быстрый способ улучшить пользовательский опыт в вашем Rails-приложении. Это не только избавляет пользователей от необходимости создавать новые аккаунты, но и делает процесс авторизации безопасным и удобным.