omniauth-twitter で Twitter ログインを試してみた

環境

  • Ruby v2.5.0
  • rails v5.2.0
  • omniauth v1.8.1
  • omniauth-twitter v1.4.0

雑に試しただけなので色々と変なところあるので注意。

Twitter APP を作成

key value
Website http://127.0.0.1:5000
Callback URLs http://127.0.0.1:5000/auth/twitter/callback

開発環境の場合は localhost ではエラーになるので 127.0.0.1 を使用する。
ポートは rails が動いているポートに適宜変更すること。

この後使用するので

  • Consumer Key (API Key)
  • Consumer Secret (API Secret)

は控えておく。

config/secrets.yml に API 情報を記述

twitter_app: &twitter_app
  consumer_key: xxxxx
  consumer_secret: xxxx

development:
  secret_key_base: xxxxx
  twitter_app:
    <<: *twitter_app

test:
  secret_key_base: xxxxx
  twitter_app:
    <<: *twitter_app

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  twitter_app:
    consumer_key: <%= ENV["TWITTER_CONSUMER_KEY"] %>
    consumer_secret: <%= ENV["TWITTER_CONSUMER_SECRET"] %>

secret_key_base は以下のコマンドで生成できる。

$ bundle exec rake secret

※ config/secrets.yml は rails 起動中だと反映されないので、起動している場合は再起動する。

Gemfile

最新版を確認して Gemfile に追記

gem 'omniauth', '~> 1.8.1'
gem 'omniauth-twitter', '~> 1.4.0'

インストール

$ bundle install

config/initializers/omniauth.rb を作成

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter,
           Rails.application.secrets.twitter_app[:consumer_key],
           Rails.application.secrets.twitter_app[:consumer_secret]
end

Rails.application.secretssecrets.yml の値を取得できる。
本当は Rails.application.secrets.twitter_app.consumer_key みたいに取りたかったけどエラーになった。

Model を作成

$ bundle exec rails generate model user provider:string uid:string nickname:string image_url:string
$ bundle exec rake db:migrate

app/models/user.rb を編集

class User < ApplicationRecord
  def self.find_or_create_from_auth_hash(auth_hash)
    provider = auth_hash[:provider]
    uid = auth_hash[:uid]
    nickname = auth_hash[:info][:nickname]
    image_url = auth_hash[:info][:image]

    User.find_or_create_by(provider: provider, uid: uid) do |user|
      user.nickname = nickname
      user.image_url = image_url
    end
  end
end

https://github.com/arunagw/omniauth-twitter#authentication-hash

で認証のレスポンスの形式が見れるので必要に応じてカラムを増やすと良い。

Controller を作成

$ bundle exec rails generate controller sessions

app/controllers/sessions_controller.rb を編集

class SessionsController < ApplicationController
  def index

  end
  def create
    @user = User.find_or_create_from_auth_hash(request.env['omniauth.auth'])
    session[:user_id] = @user.id
    redirect_to root_path
  end
end

view にファイルを追加

app/views/sessions/index.html.erb

<h1>Sessions#index</h1>
<p>Find me in app/views/sessions/index.html.erb</p>

<%= link_to 'Twitterログイン', '/auth/twitter' %>

<% if session[:user_id] %>
  <p>ログイン済み</p>
<% else %>
  <p>未ログイン</p>
<% end %>

config/routes.rb に認証コールバック用の URL を追加

root to: 'sessions#index'
get '/auth/:provider/callback', to: 'sessions#create'

omniauth が /auth/:provider にアクセスした時に各認証画面に遷移してくれるので、コールバックだけ用意すれば良い。

動作確認

起動

$ bundle exec rails server

ブラウザでアクセス 127.0.0.1:5000 にアクセスしてリンクをクリックしてみる。 (ポートは適宜変更)

トラブルシューティング

403 Forbidden が出る

  • Twitter APP で設定した URL と異なる URL から認証しようとすると起きる
    (うっかり localhost でアクセスしていたら出た。 127.0.0.1 でアクセスする。)
  • Twitter APP 側のコールバックURL と omniauth でのコールバックURLの設定が違う

参考