ls -al

仮想通貨やプログラミングに関する事などをつらつらと書き綴ります

Rails5でOmniAuthを使ったTwitter連携(認証編)

Rails5.1.5でOmniAuthを使ったTwitter連携機能を実装してみます。
今回の記事は参考記事の追試の側面が大きいので、参考記事を見たほうが速いかもしれません。

目標

以下のようなアプリの制作を目標とします。

  • / → アカウント情報表示、未ログインで/loginに遷移
  • /auth/twitter → Twitter認証実行
  • /auth/twitter/callback → Twitter認証後のコールバック先
  • /logout → ログアウト処理
  • /login → ログインを促す画面表示

準備

こちらで[Create New App]ボタンを押し、新規にツイッターアプリを作ってください。Name~Websiteの項目は好きに埋めてください。Callback URLのみ、

<アプリのURL>/auth/twitter/callback  

としてください。後ほどこのURLをコールバック先としてアプリを作ります。

アプリを作ったらAPIキーを控えます。APIキーはKeys and Access Tokensタブ内のApplication Settings欄に表示されています。~/.bashrcや~/.bash_profile等の設定ファイルに以下を追記し、環境変数にAPIキーを保存します。

export TWITTER_API_KEY=<API_KEY>
export TWITTER_API_SECRET=<API_SECRET>

OmniAuthの導入

gemfileに以下を追記します。

gemfile

gem 'omniauth'
gem 'omniauth-twitter'

追記後、bundle installを実行します。

config/secrets.ymlにAPIキーを追記します。

config/secrets.yml

twitter: &twitter
  twitter_api_key: <%= ENV["TWITTER_API_KEY"] %>
  twitter_api_secret: <%= ENV["TWITTER_API_SECRET"] %>

development:
  secret_key_base: <hogehoge>
  <<: *twitter

test:
  secret_key_base: <fugafuga>
  <<: *twitter

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  <<: *twitter

config/initializers/omniauth.rbにconfig/secrets.ymlを利用した設定を追記します。

Rails.application.config.middleware.use OmniAuth::Builder do
    provider :twitter,Rails.application.secrets.twitter_api_key,Rails.application.secrets.twitter_api_secret
end

ルーティング

以下のようにルーティングを行います。

config/routes.rb

root :to => 'home#index'
get '/auth/twitter/callback', to: 'sessions#create'
get '/logout', to: 'sessions#destroy'
get '/login', to: 'home#login'

モデルの制作

認証後に得られるユーザーの情報を格納するuserモデルを制作します。

rails generate model User provider:string uid:string nickname:string name:string image_url:string description:string
rails db:migrate

できたモデルに、認証後にデータの検索及び生成を実行するメソッドを追加します。

models/user.rb

class User < ApplicationRecord
  def self.find_or_create_from_auth(auth)
    provider = auth[:provider]
    uid = auth[:uid]
    nickname = auth[:info][:nickname]
    name = auth[:info][:name]
    image_url = auth[:info][:image]
    description = auth[:info][:description]
    self.find_or_create_by(provider: provider, uid: uid) do |user|
      user.nickname = nickname
      user.name = name
      user.image_url = image_url
      user.description = description
  end
end

コントローラの制作

セッションを管理するSessionsと、ログイン画面及びアカウント情報を表示するHomeの二つのコントローラーを制作します。

rails generate controller Sessions create destroy
rails generate controller Home index login

sessions_controller.rbの中身を書いていきます。コールバック先のリクエスト内容に含まれる認証情報をuserモデルのfind_or_create_from_auth()に渡し、生成及び取得を行い、セッションにidを格納するcreateメソッドとreset_sessionを行い、セッション内容を破棄することでログアウトを行うdestroyメソッドを作成します。

sessions_controller.rb

class SessionsController < ApplicationController
  def create
    user = User.find_or_create_from_auth(request.env['omniauth.auth'])
    session[:user_id] = user.id
    redirect_to root_path
  end

  def destroy
    reset_session
    redirect_to root_path
  end
end

home_controller.rbの中身を書いていきます。session内のuser_idの存在を確認し、nilならば未ログインと見做し、login画面に遷移します。存在していれば、@user内に対象ユーザーのデータを格納します。

home_controller.rb

class HomeController < ApplicationController
  def index
    if session[:user_id].nil?
      redirect_to action:'login'
    else
      @user = User.find(session[:user_id])
    end
  end
  
  def login
    
  end
end

ビューの制作

ユーザー情報を表示するビューを制作します。@user内にユーザー情報を格納してあるので、これらを全て表示し、さらにログアウト用のリンクも追加します。

home/index.html.erb

<p><%= "name:" + @user[:nickname]%></p>
<p><%= "screen_name:" + @user[:name]%></p>
<p><%= "image_url:" + @user[:image_url]%></p>
<p><%= "description:" + @user[:description]%></p>
<%= link_to "logout" ,:controller => "sessions", :action => "destroy" %>

ログインを促すビューを制作します。といっても、認証を行う/auth/twitterに遷移するリンクを表示するだけです。

home/login.html.erb

<%= link_to "login" ,"/auth/twitter" %>

参考

RailsでTwitterのユーザー情報と連携して認証を行う