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

Rails 7 + Devise + omniauth-facebook + omniauth-twitterでログイン機能作成(基本から詳細まで)

Nội dung chính
Rails 7 + Devise + omniauth-facebook + omniauth-twitterでログイン機能作成(基本から詳細まで)

この記事は devise、omniauth-facebook、omniauth-twitterのGemを使って、メールとFacebookとTwitterでログイン機能を作ります。

まずはFacebookとTwitter側の設定から始めます。

Facebook側の設定

アプリを作成URL:https://developers.facebook.com/apps/create

スクリーンショット 0003-11-07 10.58.46.png

スクリーンショット 0003-11-07 10.59.42.png

新規アプリを作成してから「Facebookログイン」を設定します。

スクリーンショット 0003-11-07 11.00.17.png

Facebookログインの設定画面ではまず public_profileをAdvanced Accesssに切り替えて、それから「有効なOAuthリダイレクトURI」に <ホスト>/users/auth/facebook/callback を入力します。

スクリーンショット 0003-11-07 11.01.47.png

設定のベーシック画面でアプリのデータ使用状況の確認を完了を開始してから、アプリIDアプリシークレットをコピーしときます。

っっs.png

Twitter側の設定

App detailsの設定の例は以下のようで、注意するところは二つ:

  • Enable Sign in with Twitterをチェック
  • Callback URLs<ホスト>/users/auth/twitter/callbackを入力

名称未設定のコピー.png

デフォルトはメール情報を取得できなくて、メール情報を取得するにはPermissionsタブでRequest email address from usersをチェックして保存する必要があります。

スクリーンショット 0003-11-07 11.22.59.png

最後は Keys and tokensタブで API keyApi secret keyをコピーしておきます。

スクリーンショット 0003-11-07 11.23.18.png

ここまではFacebookとTwitterの設定が完了なので、次はソースコードに着手します!

Gem導入

Copy Gemfile
1
2
3
4
5
gem 'devise'
gem 'devise-i18n' # 英語で使うなら不要
gem 'omniauth-rails_csrf_protection'
gem 'omniauth-facebook'
gem 'omniauth-twitter'

deviseのインストール

Copy
1
rails g devise:install
Userというモデルでdeviseを作る

Copy
1
rails g devise User
カスタムのため、コントローラとビューと翻訳ファイルをコピーしておく

deviseのコントローラ作成

Copy
1
rails g devise:controllers users
deviseのビュー作成
Copy
1
rails g devise:views users
deviseの翻訳ファイル作成
Copy
1
rails g devise:it8n:locale ja
ビューのフォルダ名はdeviseではなくusersなどであれば、deviseの翻訳ファイルを編集する必要があります

Copy config/locales/devise.views.ja.yml
1
2
3
4
5
ja:
  # ・・・省略
  devise: &devise
  # ・・・省略
  users: *devise

deviseの設定

Copy config/initializers/devise.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  config.omniauth :facebook,
                  ENV['FACEBOOK_APP_ID'],
                  ENV['FACEBOOK_APP_SECRET'],
                  {
                    scope: 'email',
                    image_size: 'large',
                    locale: 'en' # 英語で情報を取得
                  }
  config.omniauth :twitter,
                  ENV['TWITTER_CONSUMER_API_KEY'],
                  ENV['TWITTER_CONSUMER_API_SECRET_KEY'],
                  {
                    image_size: 'original',
                    lang: 'en' # 英語で情報を取得
                  }

  config.mailer_sender = 'LANGMEMO <notification@langmemo.com>' # deviseから送信するメールのアドレス

  config.scoped_views = true # カスタマイズのビューを使う場合

アカウント登録、ログイン、ログアウトなどのURLヘルパー:

Copy slim
1
2
3
= link_to 'アカウント登録', new_user_registration_path
= link_to 'ログイン', new_user_session_path
= button_to 'ログアウト', destroy_user_session_path, method: :delete, 'data-turbo': false

アカウント登録時のカスタムフィールドを追加する場合

Copy config/routes.rb
1
2
3
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
Copy app/controllers/users/registrations_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    before_action :configure_sign_up_params, only: [:create]
    before_action :configure_account_update_params, only: [:update]

    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])
    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])
    end

アカウント情報更新時に現在のパスワードを無くする場合

Copy app/controllers/users/registrations_controller.rb
1
2
3
4
5
    protected

    def update_resource(resource, params)
      resource.update_without_password(params)
    end

アカウント登録して、メールで確認URLをクリックしてから自動ログインしたい場合

Copy config/routes.rb
1
2
3
  devise_for :users, controllers: {
    confirmations: 'users/confirmations'
  }
Copy app/controllers/users/confirmations_controller.rb
1
2
3
4
5
6
7
8
  protected

  # The path used after confirmation.
  def after_confirmation_path_for(resource_name, resource)
    # super(resource_name, resource)
    sign_in(resource)
    root_path
  end

Deviseのフォームで送信した後のリダイレクトにturbofalseにしたい場合

html: { 'data-turbo': false } を入れる

Copy sessions/new.html.erb
1
2
  <%= form_for(resource, as: resource_name, url: session_path(resource_name), html: { 'data-turbo': false }) do |f| %>

ここまではメールでアカウント登録、ログインができるようになりました。

FacebookとTwitterログイン

Copy config/routes.rb
1
2
3
  devise_for :users, controllers: {
    omniauth_callbacks: 'users/omniauth_callbacks'
  }
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, :recoverable,
         :rememberable, :validatable, :confirmable, :trackable,
         :omniauthable # これを追加

  class << self
    def find_for_oauth(auth)
      @user = User.find_or_initialize_by(uid: auth.uid, provider: auth.provider)
      assign_info(auth)
      attach_image(auth.info.image) if auth.info.image
      @user.skip_confirmation!
      @user.save!
      @user
    rescue StandardError => e
      e.message
    end

    def assign_info(auth)
      @user.uid = auth.uid
      @user.provider = auth.provider
      @user.name = auth.info.name
      @user.email = auth.info.email
      @user.password = Devise.friendly_token[0, 20]
    end

    def attach_image(image_url)
      @user.image.attach(io: URI.parse(image_url).open, filename: "user_#{@user.id}_image")
      # ファイルの一番上に require 'open-uri' が必要
    end
  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
    def facebook
      callback_from :facebook
    end

    def twitter
      callback_from :twitter
    end

    private

    def callback_from(provider)
      @user = User.find_for_oauth(request.env['omniauth.auth'].delete_if { |k, _v| k == 'extra' })
      if @user.instance_of?(User)
        flash[:notice] = t('devise.omniauth_callbacks.success', kind: provider.to_s.capitalize)
        sign_in_and_redirect @user, event: :authentication
      else
        session["devise.#{provider}_data"] = request.env['omniauth.auth']
        redirect_to new_user_registration_path, alert: @user
      end
    end
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 (36 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.