Railsにこれから初めて触れる方を対象にしたチュートリアルです RailsにTwitterでのログイン機能を実装するチュートリアルになります
まず、rails newを実行し、アプリのひな型を作成します
rails new twitter_login
次に、作成したアプリのディレクトリへと移動します
cd twitter_login
Twitterでのログイン機能を実装するにあたって、Deviseを使用します
まず、Gemfileにgem 'devise'を追加してbundle installを実行します
gem 'devise'
bundle install
この時、sqlite3がインストールできないエラーが発生するかもしれません
その場合は以下のようにsqlite3のバージョンを修正してbundle installを実行してください
gem 'sqlite3', '1.3.13'
bundle install
bundle install後、以下のコマンドを実行してDeviseをインストールします
rails g devise:install
``
次に、`Devise`で使用する`View`ファイルを作成します
```shell
rails g devise:views
そして、Deviseで使用するModelを作成し、マイグレーションを実行します
rails g devise user
rails db:migrate
これでDeviseの導入は完了です!
Twitterでのログインを実装するためには、Twitterへアプリケーションの登録が必要になります
こちらでアプリケーションを作成します
作成手順は以下の記事が参考になります
Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ ※2018年9月時点の情報
アプリケーション作成後、API keyとAPI secret keyを取得しておきます
また、callback urlにhttp://localhost:3000/users/auth/twitter/callbackと追加し、
Allow this application to be used to Sign in with Twitterにチェックをいれておきます
Twitetrから取得したAPI keyとAPI secret keyをソースコードにそのまま貼り付けてしまうと悪意のある第三者に利用されてしまう可能性があります
実際に、発生した事例としては以下のようなものがあります
AWSが不正利用され300万円の請求が届いてから免除までの一部始終
こういったことを回避するためにもDotenvなどを使用してソースコードに直接書かないようにする必要があります
まず、Gemfileにgem 'dotenv-rails'を追加します
gem 'dotenv-rails'
その後、bundle installを実行します
bundle install
そして、先ほど取得したキーなどを.envに書き込みます
.envはGemfileと同じ位置に作成します
# Using Twitter API
TWITTER_API_KEY=API key
TWITTER_SECRET_KEY=API secret key
最後に、.gitignoreを編集し、.envをGitの管理対象から外します
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '~/.gitignore_global'
# Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore uploaded files in development
/storage/*
!/storage/.keep
/node_modules
/yarn-error.log
/public/assets
.byebug_history
# Ignore master key for decrypting credentials and more.
/config/master.key
.env
これでDotenvの導入は完了です!
Twitterアカウントでのログイン機能はOauthという認証を使用します
まず、必要なgemをGemfileに追加します
gem 'omniauth'
gem 'omniauth-twitter'
bundle installでgemをインストールします
bundle install
次に、Userモデルにカラムを追加してマイグレーションを行います
rails g migration AddColumnsToUsers uid:string provider:string
rails db:migrate
次に、config/initializers/devise.rbを編集してDevise側の設定を変更します
Devise.setup do |config|
  #<省略>
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  config.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['TWITTER_SECRET_KEY']
 #<以下省略>
end
Dotenv経由でTwitterのAPIキーなどを読み取っています
次に、userモデルに:omniauthableを追加します
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable
end
その後、self.find_for_oauth(auth)というメソッドを追加します
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable
  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,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20]
      )
      user.save!
    end
    current_user = user
  end
      
  private
      
    def self.dummy_email(auth)
      "#{auth.uid}-#{auth.provider}@example.com"
    end
end
このメソッドにより、アカウントが既に作成されているかをチェックし、アカウントがない場合は新しく作成することができるようになります
app/controllers/users/omniauth_callbacks_controller.rbというコールバック処理を行うコントローラーを作成します
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  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[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end
最後に、config/routes.rbにコールバック先のルーティングを追加します
Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
end
これでTwitterでのログイン機能は実装できました!
最後に、Twitterログインが実際に機能しているかどうかを確認するためのページを作成します
rails g controller web index
app/views/web/index.html.erbにTwitterログインのリンクなどを追加します
<h1>Web#index</h1>
<p>Find me in app/views/web/index.html.erb</p>
<%= link_to 'Twitter Login', user_twitter_omniauth_authorize_path %>
<% if user_signed_in? %>
    Your Welcome!
<% end %>
Twitter Loginをクリックしてログインできるようになっています
また、ログインするとYour Welcome!の文字が画面に表示されるようになっています
rails sでローカルサーバを起動し、localhost:3000にアクセスします
その後、Twitter LoginのリンクをクリックするとTwitterのアプリ認証の画面が表示されます
認証後、localhost:3000にYour Welcome!と表示されていればOKです!