Tag: Devise/Twitter認証

目次

参考情報

関連ページ

使用準備

  • Gemfileの編集
    gem 'devise'
    gem 'omniauth-twitter'
    
  • サンプルモデルなどを作成
    bundle exec rails g scaffold  book title:string author:string summary:text
  • deviseをインストールする
    bundle exec rails g devise:install
  • Userモデルの作成
    bundle exec rails  g devise user
  • Userモデルの変更。confirmableは実装せず画面上で登録が完結できるようにする。omniauthableを追加。
    class User < ApplicationRecord
      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, :validatable, :omniauthable
    end
    
  • migrationファイルdevise_create_user.rbの変更。
    class DeviseCreateUsers < ActiveRecord::Migration[5.1]
      def change
        create_table :users do |t|
          ## Database authenticatable
          t.string :email,              null: false, default: ""
          t.string :encrypted_password, null: false, default: ""
    
          ## Recoverable
          t.string   :reset_password_token
          t.datetime :reset_password_sent_at
    
          ## Rememberable
          t.datetime :remember_created_at
    
          ## Trackable
          t.integer  :sign_in_count, default: 0, null: false
          t.datetime :current_sign_in_at
          t.datetime :last_sign_in_at
          t.string   :current_sign_in_ip
          t.string   :last_sign_in_ip
    
          ## Confirmable
          # t.string   :confirmation_token
          # t.datetime :confirmed_at
          # t.datetime :confirmation_sent_at
          # t.string   :unconfirmed_email # Only if using reconfirmable
    
          ## Lockable
          # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
          # t.string   :unlock_token # Only if unlock strategy is :email or :both
          # t.datetime :locked_at
    
    
          t.timestamps null: false
    
          ## Twitter認証用
          t.string :provider
          t.string :uid
          t.string :username, default: "anonymous"
        end
    
        add_index :users, :email,                unique: true
        add_index :users, :reset_password_token, unique: true
        # add_index :users, :confirmation_token,   unique: true
        # add_index :users, :unlock_token,         unique: true
      end
    end
    
    
    
  • migration実行
    bundle exec rails db:migrate

Twitterアプリケーションの登録

  • https://apps.twitter.com/ からアプリケーションを登録する。
  • callback_urlは開発環境と本番環境で異なるので2個登録しておくとよい。
  • 開発環境の場合Callback URLは次のように設定する。localhostにするとエラーになるので注意。
    http://127.0.0.1:3000/users/omniauth_callbacks

Twitter認証のための準備

devise.rbの編集

  • config/initializers/devise.rbを編集
    config.omniauth :twitter, "Consumer Key", "Consumer Secret"
  • この段階で「http://localhost:3000/users/sign_in」にアクセスし、「Sign in with Twitter」からログインすると一応Twitterのログイン画面が表示される。
  • しかしコールバックが設定されていないのでラーになる。
    The action 'twitter' could not be found for Devise::OmniauthCallbacksController
    

コールバック用コントローラーの生成

  • Twitterログイン画面から戻ってきたときに呼び出される処理を行うコントローラーを生成する。
    bundle exec rails g controller omniauth_callbacks
  • 内容を編集。親クラスがDevise::OmniauthCallbacksControllerなので注意。
    class OmniauthCallbacksController < Devise::OmniauthCallbacksController
      def twitter
        @user = User.from_omniauth(request.env["omniauth.auth"].except("extra"))
        if @user.persisted?
          flash.notice = "ログインしました!"
          sign_in_and_redirect @user
        else
          session["devise.user_attributes"] = @user.attributes
          redirect_to new_user_registration_url
        end
      end
    end
    

Userモデルの変更

  • from_omniauthとnew_with_sessionを作成する。
    class User < ActiveRecord::Base
      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, :validatable,
    #         :confirmable, :lockable, :timeoutable, :omniauthable, omniauth_providers: [:twitter]
              :timeoutable, :omniauthable, omniauth_providers: [:twitter]
      def self.from_omniauth(auth)
        where(provider: auth["provider"], uid: auth["uid"]).first_or_create do |user|
          user.provider = auth["provider"]
          user.uid = auth["uid"]
          user.username = auth["info"]["nickname"]
    #      user.email = Devise.friendly_token[0,20]
          user.email =  "#{auth.provider}-#{auth.uid}@example.com"
          user.password = Devise.friendly_token[0,20] #これが必要?
        end
      end
    
      def remember_me
        # http://stackoverflow.com/questions/14417201/how-to-automatically-keep-user-remembered-in-devise
        true
      end
    
      def self.new_with_session(params, session)
        if session["devise.user_attributes"]
          new(session["devise.user_attributes"], without_protection: true) do |user|
            user.attributes = params
            user.valid?
          end
        else
          super
        end
      end
    
      def password_required?
        super && provider.blank?
      end
    
      def email_required?
        super && provider.blank?
      end
    end
    
    
    

ルートの設定

  • routes.rbを編集。omniauth_callbacks_controllerが呼ばれるようにする。
    devise_for :users, controllers: { :omniauth_callbacks => "omniauth_callbacks" }
    

画面の修正

  • application.html.erbの修正
    <!DOCTYPE html>
    <html>
      <head>
        <title>Rails5DeviseTwitterDemo</title>
        <%= csrf_meta_tags %>
    
        <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
        <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
      </head>
    
      <body>
      <header>
        <nav>
          <% if user_signed_in? %>
            <strong<%= link_to current_user.username, pages_show_path %></strong>
            <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
          <% else %>
            <%= link_to 'ログイン', user_twitter_omniauth_authorize_path %>
          <% end %>
        </nav>
      </header>
      <p class="notice"><%= notice %></p>
      <p class="alert"><%= alert %></p>
      <%= yield %>
      </body>
    </html>
    
  • ログインしていない場合は、「ログイン」リンクが表示される。クリックされるとTwitter認証画面にとぶ。
  • ログインしている場合はユーザー名と「ログアウト」リンクが表示される。
  • 初回の登録とそれ以降のログインに差は無い。

ビューの変更

  • Deviseのビューをカスタマイズする場合以下のコマンドを実行
    bundle exec rails g devise:views

Tips

認証済みユーザーでないと表示できないページ

  • 例えば認証済みユーザーでないとログインできないページ。
    class UsersController < RegularController
      include ApplicationHelper
    
      #http://stackoverflow.com/questions/7458723/using-devise-to-create-private-profiles ユーザー以外がアクセスするとリダイレクト
      before_action :verify_owner, only: [:show, :edit, :destroy]
      def verify_owner
        redirect_to root_url unless current_user.username == params[:id]
      end
    

トラブルシューティング

急にログインできなくなった

  • 2018年6月、Twitter側の仕様変更により設定されたcallback_urlを正しく送信しないとログインできなくなった模様。
  • これには以下の変更が必要。
  • Twitter Appの変更。本番のほかテスト用のcallbackを追加しておかないと開発環境でログインできなくなる。
    http://本番サイトのURL/users/auth/twitter/callback
    http://localhost:3000/users/auth/twitter/callback
  • アプリ側の設定。callback_urlの設定は本番と開発環境で切り替える必要あり。
    Devise.setup do |config|
      config.omniauth :twitter, "TWITTER_CONSUMER_KEY", "TWITTER_CONSUMER_SECRET", callback_url: 'http://localhost:3000/users/auth/twitter/callback'
    end
    
  • callback urlはroutesでcallbackをgrepするとわかる。
    $ bundle exec rake routes   | grep callback
     user_twitter_omniauth_callback GET|POST /users/auth/twitter/callback(.:format)
    

添付ファイル: filetest.jpg 101件 [詳細] filesign_up.png 662件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-07-05 (木) 16:00:07