Yuto Blog

Yuto Blog

[Ruby on Rails] Devise + Omniauth Authentication

Sample Application

Gemfile
gem 'devise'
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'paperclip'
gem 'fog'

rails g devise:install
rails g devise User
rails g devise:controllers users
rails g migration AddAttributesToUsers name uid provider token
rails g paperclip user image

config/routes.rb
devise_for :users, controllers: {
  omniauth_callbacks: 'users/omniauth_callbacks',
  registrations: 'users/registrations'
}
config/initializers/devise.rb
config.omniauth :facebook, ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_API_SECRET'],
  secure_image_url: true
config.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['TWITTER_API_SECRET']
config/environments/production.rb
  config.paperclip_defaults = {
    use_timestamp: false,
    url: '/:attachment/:class/:id/:style.:extension',
    storage: :fog,
    fog_directory: ENV['FOG_DIRECTORY'],
    fog_credentials: {
      provider: :aws,
      region: 'ap-northeast-1',
      aws_access_key_id: ENV['AWS_API_KEY'],
      aws_secret_access_key: ENV['AWS_API_SECRET']
    }
  }
app/models/user.rb
  devise :database_authenticatable, :registerable, :omniauthable,
         :recoverable, :rememberable, :trackable, :validatable

  has_attached_file :image, styles: { thumb: '50x50#' }
  validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/

  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first
    unless user
      user = User.create(
        uid: auth.uid,
        provider: auth.provider,
        token: auth.credentials.token,
        name: auth.info.name,
        email: User.get_email(auth),
        password: Devise.friendly_token[0, 20]
      )
    end
    if auth.info.image
      user.update_attribute(:image, auth.info.image)
    end
    user
  end

  private

  def self.get_email(auth)
    auth.info.email || "#{auth.provider}-#{auth.uid}@example.com"
  end
app/controllers/users/registrations_controller.rb
protected
  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :image])
  end

  # If you have extra params to permit, append them to the sanitizer.
  def configure_account_update_params
    devise_parameter_sanitizer.permit(:account_update, keys: [:name, :image])
  end

  # Can update without current password
  def update_resource(resource, params)
    # Require current password if user is trying to change password
    return super if params['password']&.present?

    # Allows user to update registration information without password
    resource.update_without_password(params.except('current_password'))
  end
app/controllers/users/omniauth_callbacks_controller.rb
  def facebook
    callback_from :facebook
  end

  def twitter
    callback_from :twitter
  end

  private

  def callback_from(provider)
    provider = provider.to_s
    @user = User.find_for_oauth(request.env['omniauth.auth'])
    if @user.persisted?
      flash[:success] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      if provider == 'twitter'
        session["devise.#{provider}_data"] = request.env['omniauth.auth'].except('extra')
      else
        session["devise.#{provider}_data"] = request.env['omniauth.auth']
      end
      redirect_to new_user_registration_url
    end
  end
app/views/layouts/application.erb.slim
          ul.nav.navbar-nav.navbar-right
            - if user_signed_in?
              li = image_tag current_user.image(:thumb)
              li.navbar-text = current_user.name
              li = link_to 'Sign out', destroy_user_session_path, method: :delete
            - else
              li = link_to 'Sign in', new_user_session_path
              li = link_to 'Sign up', new_user_registration_path
              li = link_to 'Sign up with Facebook', user_facebook_omniauth_authorize_path
              li = link_to 'Sign up with Twitter', user_twitter_omniauth_authorize_path

スクリーンショット 2017-06-13 18.23.21.png

Paperclip::AdapterRegistry::NoHandlerError というエラーが発生した場合

config/initializers/paperclip.rb
Paperclip::DataUriAdapter.register
Created by Yuto at 2022-01-21 17:42
0
Like this article
Le Minh Thien Toan

Tác giả:Yuto Yasunaga

Xin chào các bạn. Mình là kỹ sư IT đang làm việc ở Nhật Bản. Mình tạo blog này để chia sẻ về cuộc sống và những kinh nghiệm trong quá trình học tập và làm việc.
Hy vọng bài viết này sẽ có ích cho bạn.