Cuộc sống Nhật Bản
Yuto Blog

[Ruby on Rails] Devise + Omniauth Authentication

Nội dung chính

Sample Application

Copy Gemfile
1
2
3
4
5
6
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

Copy config/routes.rb
1
2
3
4
devise_for :users, controllers: {
  omniauth_callbacks: 'users/omniauth_callbacks',
  registrations: 'users/registrations'
}
Copy config/initializers/devise.rb
1
2
3
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']
Copy config/environments/production.rb
1
2
3
4
5
6
7
8
9
10
11
12
  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']
    }
  }
Copy app/models/user.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  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
Copy app/controllers/users/registrations_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
Copy app/controllers/users/omniauth_callbacks_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  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
Copy app/views/layouts/application.erb.slim
1
2
3
4
5
6
7
8
9
10
          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 というエラーが発生した場合

Copy config/initializers/paperclip.rb
1
Paperclip::DataUriAdapter.register
Updated at 2023-05-09
Nếu bài viết có ích thì các bạn hãy chia sẻ nhé
Rate this article: 5/5 (33 ratings)
You didn't rate yet
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.