7
4

More than 3 years have passed since last update.

[Rails]TwitterAPI認証+deviseでのログインの実装方法

Last updated at Posted at 2020-04-21

経緯

railsにdeviseをインストールした状態でTwitterAPI認証でのログインを実装しました。
色んなサイトを参考にした結果、迷走し2日以上かけてしまいました。
今後も使うかもしれない自分用の備忘録的サムシングとして、またみなさんにササッと実装いただけたらと思い投稿しました。

開発環境

ruby 2.7.0
rails 5.2.4
AWS EC2/RDS

前提条件

・Twitterアカウントがある。
・deviseインストール済のアプリがある。
・環境変数の設定ができている。
・本番環境でアプリの動作ができている状態。

TwitterのAPI認証取得および設定

a. API取得

https://qiita.com/kngsym2018/items/2524d21455aac111cdee
私はこちらのサイトを参考にしました。

callbackURLには以下のように入れてください。
URL : https://[自分のサイトのリンク]/users/auth/twitter/callback
(https化されてない場合は、うまく動作しないかもしれません。)

追記:
ローカルで動かす場合は、callback URLに
URL : http://localhost:3000/users/auth/twitter/callback
と入れていただくと動作するようです。

Terms of service URLとPrivacy policy URL何か埋めてください。次の項目で必須となってます。
こんな感じになります。
スクリーンショット 2020-04-20 20.45.44.png

b. 取得できたAPI KeyとAPI Secretはメモ
スクリーンショット 2020-04-20 20.36.28.png

c. Permissionsの設定
read onlyなどは用途に合わせて選んでください。
ユーザー登録にメルアドが必要なので「Request email addresses from users」チェック
スクリーンショット 2020-04-20 20.48.48.png

Gemの設定

Gemfile
gem 'omniauth'
gem 'omniauth-twitter'

忘れずに

$ bundle

API keyとAPI secretの設定

a. メモしたAPI keyとAPI secretを.envファイルに記述します。
ここではそれぞれの名前はTWITTER_CONSUMER_KEYとTWITTER_CONSUMER_SECRETにしています。
ドメインネーム(アプリのドメインorIPアドレス)も記述します

.env
TWITTER_CONSUMER_KEY = "****************************"
TWITTER_CONSUMER_SECRET = "****************************"

DOMAIN_NAME = "*****************"

b. .gitignoreに記述

.gitignore
.
.
.env
.
.

deviseの設定

記述した認証用のキーをdeviseが識別できるように記述します。

config/initializers/devise.rb
config.omniauth :twitter, ENV['TWITTER_CONSUMER_KEY'], ENV['TWITTER_CONSUMER_SECRET'], scope: 'email', oauth_callback: "#{ENV['DOMAIN_NAME']}/users/auth/twitter/callback"
OmniAuth.config.logger = Rails.logger if Rails.env.development? # debug用

UserモデルとTwitter認証モデルを紐付ける

a. deviseに:omniauthable, omniauth_providers: [:facebook, :twitter, :google_oauth2]を追加
facebookとグーグル認証も将来的に使うかもしないので一応付けておきます。

app/models/user.rb
devise :database_authenticatable, :registerable,
       :recoverable, :rememberable, :validatable,
       # 外部API認証用に以下追加
       :omniauthable, omniauth_providers: [:facebook, :twitter, :google_oauth2]

b. マイグレーションファイルにカラムの追加

$ rails g migration AddColumnsToUsers uid:string provider:string
$ rails db:migrate

c. Userモデルにfindメソッドを実装

app/models/user.rb
# Twitter認証ログイン用
# ユーザーの情報があれば探し、無ければ作成する
def self.find_for_oauth(auth)
  user = User.find_by(uid: auth.uid, provider: auth.provider)

  user ||= User.create!(
    uid: auth.uid,
    provider: auth.provider,
    name: auth[:info][:name],
    email: User.dummy_email(auth),
    password: Devise.friendly_token[0, 20]
  )

  user
end

def self.dummy_email(auth)
  "#{Time.now.strftime('%Y%m%d%H%M%S').to_i}-#{auth.uid}-#{auth.provider}@example.com"
end

メールアドレスでの認証も実装している場合は、OAuthでの認証時もメールアドレスを保存する必要があります。
emailはダミー用のアドレスを作成して代用します。
email中に時間まで記載しているのは、認証後に退会などで論理削除された後も再度認証ログインできるように今回は設定しています。

d. omniauthコントローラーの設定
deviseのusers配下にあります。
無い方は$ rails g devise:controllers usersを実行すると見えるようになります。

app/controllers/users/omniauth_callbacks_controller.rb
def twitter
  callback_from :twitter
end

private
  # コールバック時に行う処理
  def callback_from(provider)
    provider = provider.to_s

    @user = User.find_for_oauth(request.env['omniauth.auth'])

    # persisted?でDBに保存済みかどうか判断
    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

ルーティングの設定

omniauth_callbacks_pathの追加

config/routes.rb
devise_for :users, :controllers => {
    :registrations => 'users/registrations',
    :sessions => 'users/sessions',
    :passwords => 'users/passwords',
    # このpathを通して外部API認証が行われる。
    :omniauth_callbacks => 'users/omniauth_callbacks'
   }

ビューに認証用リンクの設定

書き方はなんでもありだと思いますが一例として
a. loginページにリンク追加

app/views/devise/registrations/new.html.erb
<%= link_to user_twitter_omniauth_authorize_path do %>
  <i class="fab fa-twitter-square fa-2x"></i>
<% end %>

b. signupページにリンク追加

app/views/devise/sessions/new.html.erb
<%= link_to user_twitter_omniauth_authorize_path do %>
  <i class="fab fa-twitter-square fa-2x"></i>
<% end %>

c. cssにtwitterアイコンのカラーを追加

app/assets/stylesheets/application.css.scss
.fa-twitter-square {
  color: #1da1f2;
}

本番環境で動作確認

ここまでの操作でできているはずです。

a. アップロードの準備

.envのアップロード
ローカル環境でアプリケーション直下に移動して

$ scp -i ~/.ssh/practice-aws.pem .env ec2-user@××.××.×××.×××:[アプリ名]/

本番環境に入って、

// プリコンパイルを実行
$ bundle exec rails assets:precompile RAILS_ENV=production
// マイグレートを実行
$ bundle exec rails db:migrate RAILS_ENV=production
// サーバー起動
$ rails s -e production

b. ビューの確認
スクリーンショット 2020-04-21 14.16.42.png
ツイッターのアイコンが表示出来ています。

c. 認証ログイン後確認
スクリーンショット 2020-04-21 14.19.30.png
ツイッターでの表示名でログインできていることが確認できました。

まとめ

TwitterAPIを使ってワンクリックでサインアップすることができるようになったため、よりユーザービリティが上がったと思います。
はじめてAPI認証でのログインに挑戦してみて、WEBのつながりが見えてきて非常に勉強になりました。

今回時間がかかった要因

a. ローカルでの試験運用ができなかったこと
TwitterDeveloperのwebsiteURLに他サイトで推奨されているようなhttp://127.0.0.1:3000 などを入れても「invalid URL」といったメッセージが返ってくるため、(他のやりようがあったみたいですが少々面倒だったので)ローカル→本番→試験→NGを繰り返していました。

結果的にはめちゃめちゃ時間くっちゃいましたので、面倒でもローカルでの有効化方法を模索すればよかったと反省です。良い方法があれば教えていただけると嬉しいです。

b. deviseでの認証の場合、やり方が通常と異なること
通常では/config/initializers下にomniauth.rbというファイルを新規作成してコントローラーも別で作ってってやり方になると思いますが、そちらでやっていたためdeviseが入ってるとログイン認証はデバイスが絡んでいるため、エラーになっていました。
deviseの便利さに甘えて、大事なことに気づくことが遅れてしまいました。反省です。

参考

https://qiita.com/kazuooooo/items/47e7d426cbb33355590e
https://qiita.com/zenizh/items/94aec2d94a2b4e9a1d0b
https://qiita.com/puremoru0315/items/f1d459b663fd3b715dee
https://kurose.me/twitter-omniauth/#Twitter

7
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4