activeadmin에서 Google 인증(omniauth-google-oauth2) 배포 절차

activeadminWiki에 쓰여진 대로라면 작동하지 않았기 때문에 Google 인증을 도입하는 절차를 정리해 보았습니다. 이용한 gem은 omniauth-google-oauth2 입니다.

환경


  • Rails 4.2.6
  • activeadmin 1.0.0.pre4
  • devise 4.2.0

  • 도입 절차



    ※ rails new..activeadmin의 설치 순서 등은 생략합니다.

    1. omniauth-google-oauth2를 Gemfile에 추가하여 bundle



    2. AdminUser에 :omniauthable 모듈 사용



    app/models/admin_user.rb
    class AdminUser < ActiveRecord::Base
      # パスワードでの認証を廃止するため :recoverable, :rememberable は削除(共用させる場合は残す)
      devise :database_authenticatable, :omniauthable, :trackable, :validatable
    end
    

    3. devise에 omniauth 설정 추가



    config/initializers/devise.rb
    config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], scope: "email"
    

    4. dotenv-rails를 Gemfile에 추가하여 bundle



    Gemfile
    gem 'dotenv-rails', require: 'dotenv/rails-now'
    

    5. .env에 필요한 환경 변수 설정



    .env
    GOOGLE_CLIENT_ID=**********YOUR_CLIENT_ID**********
    GOOGLE_CLIENT_SECRET=**********GOOGLE_CLIENT_SECRET**********
    

    클라이언트 ID와 클라이언트 시크릿의 설정 순서는 여기 에 쓰여진 대로입니다.

    단, 리디렉션 URI는 http://127.0.0.1:3000/admin/auth/google_oauth2/callback 로 설정해야 합니다. (localhost

    6. 마이그레이션 작성 및 실행


    $ bundle exec rails g migration change_columns_in_admin_users
    

    db/migrate/YYYYMMDDHHMMSS_change_columns_in_admin_users.rb
    class ChangeColumnsInAdminUsers < ActiveRecord::Migration
      def change
        add_column :admin_users, :provider, :string
        add_column :admin_users, :uid,      :string
    
        add_index :admin_users, [:provider, :uid], unique: true
    
        # パスワード認証を廃止するため、以下は削除(共存させる場合は残す)
        remove_column :admin_users, :reset_password_token,   :string
        remove_column :admin_users, :reset_password_sent_at, :datetime
        remove_column :admin_users, :remember_sent_at,       :datetime
      end
    end
    
    $ bundle exec rake db:migrate
    

    7. AdminUser에 AuthHash에 해당하는 메서드 추가



    app/models/admin_user.rb
    class AdminUser < ActiveRecord::Base
    
      devise :database_authenticatable, :omniauthable, :trackable, :validatable
    
      with_options presence: true do
        validates :email # whitelistでフィルタする場合、inclusionやformatのvalidationを追加
        validates :provider
        validates :uid, uniqueness: { scope: :provider }
      end
    
      # こちらは、ほぼ公式wiki通りに書いているが、パスワード認証しないなら、常時falseでよい
      # Devise override to ignore the password requirement if the user is authenticated
      def password_required?
        return false if provider.present?
        super
      end
    
      class << self
        def from_omniauth(auth)
          admin_user = where(email: auth.info.email).first || where(auth.slice(:provider, :uid).to_h).first || new
          admin_user.tap { |this| this.update_attributes(provider: auth.provider, uid: auth.uid, email: auth.info.email) }
        end
      end
    end
    

    8. 콜백을 받는 컨트롤러의 구현



    app/controllers/admin_users/omniauth_callbacks_controller.rb
    class AdminUsers::OmniauthCallbacksController < Devise::OmniauthCallbacksController
    
      def all
        admin_user = AdminUser.from_omniauth(auth_hash)
    
        if admin_user.persisted?
          flash.notice = "Signed in!"
          sign_in_and_redirect admin_user
        else
          flash.notice = "We couldn't sign you in because: " + admin_user.errors.full_messages.to_sentence
          redirect_to new_admin_user_session_url
        end
      end
    
      # providerを追加したら、aliasも追加
      # 追加予定ないなら、#all => #google_oauth2 に変更する感じ
      alias_method :google_oauth2, :all
    
      private
    
      def auth_hash
        request.env["omniauth.auth"]
      end
    end
    

    9. 라우팅에서 omniauth_callbacks 시에 사용할 컨트롤러를 assign



    config/routes.rb
    Rails.application.routes.draw do
      devise_config = ActiveAdmin::Devise.config
      devise_config[:controllers][:omniauth_callbacks] = 'admin_users/omniauth_callbacks'
      devise_for :admin_users, devise_config
      ActiveAdmin.routes(self)
      #...
    

    10. 로그인 양식에서 비밀번호 양식 삭제



    템플릿 activeadmin 원본 파일

    app/views/active_admin/devise/sessions/new.html.erb
    <div id="login">
      <h2><%= render_or_call_method_or_proc_on(self, active_admin_application.site_title) %> <%= title t('active_admin.devise.login.title') %></h2>
      <div style="text-align: center">
        <%- if devise_mapping.omniauthable? %>
          <%- resource_class.omniauth_providers.each do |provider| %>
            <%= button_to(
                  t('active_admin.devise.links.sign_in_with_omniauth_provider', provider: provider.to_s.titleize),
                  omniauth_authorize_path(resource_name, provider)) %><br />
          <% end -%>
        <% end -%>
      </div>
    </div>
    

    미안해.

    이제 Google 계정으로 인증할 수 있습니다.

    인증 전







    인증 후





    덧붙여 이하가 본 기사의 샘플 어플리케이션이 됩니다.
  • yhirano55/activeadmin_omniauth_sample

  • 참고


  • Log in through OAuth providers · activeadmin/activeadmin Wiki
  • Salesforce OAuth2 authentication with Active Admin
  • 좋은 웹페이지 즐겨찾기