Yuto Blog

Yuto Blog

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

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導入

Gemfile
gem 'devise'
gem 'devise-i18n' # 英語で使うなら不要
gem 'omniauth-rails_csrf_protection'
gem 'omniauth-facebook'
gem 'omniauth-twitter'

deviseのインストール

rails g devise:install

Userというモデルでdeviseを作る

rails g devise User

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

deviseのコントローラ作成

rails g devise:controllers users

deviseのビュー作成

rails g devise:views users

deviseの翻訳ファイル作成

rails g devise:it8n:locale ja

ビューのフォルダ名はdeviseではなくusersなどであれば、deviseの翻訳ファイルを編集する必要があります

config/locales/devise.views.ja.yml
ja:
  # ・・・省略
  devise: &devise
  # ・・・省略
  users: *devise

deviseの設定

config/initializers/devise.rb
  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ヘルパー:

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

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

config/routes.rb
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
app/controllers/users/registrations_controller.rb
    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

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

app/controllers/users/registrations_controller.rb
    protected

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

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

config/routes.rb
  devise_for :users, controllers: {
    confirmations: 'users/confirmations'
  }
app/controllers/users/confirmations_controller.rb
  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 } を入れる

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

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

FacebookとTwitterログイン

config/routes.rb
  devise_for :users, controllers: {
    omniauth_callbacks: 'users/omniauth_callbacks'
  }
app/models/user.rb
  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
app/controllers/users/omniauth_callbacks_controller.rb
    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 by Yuto at 2022-01-29 21:22
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.