10
11

More than 3 years have passed since last update.

[Rails]deviseを使ったTwitter認証でログイン

Posted at

今回は、Twitter APIを利用して、deviseのログインでTwitterアカウントでログインできるようにしていきます。

APIを使うことで、かんたんにTwitterと連携ができます。

では、さっそくいきましょう!

完成イメージ

完成イメージはこちらです
TwitterアカウントでログインをクリックするとTwitterアカウントでログインできます。

スクリーンショット 2021-08-06 11.19.15.png

動作確認したい方は、ぼくのポートフォリオに実装してますので、確認してみてください。

開発環境

ruby 2.6.3
Rails 5.2.6

前提

今回のTwitterでのログインは、deviseを使用しますので、deviseを使ったログイン機能の実装を済ませておいてください。
deviseのかんたん導入手順
さくっとdeviseをつかってみる

TwitterAPI登録

まずは、TwitterAPIに登録することから始めます。
登録にはTwitterアカウントが必要なので、開発用であれば新規にアカウントを作成するのもアリかもです。

少し古い記事ですが、ぼくはこの記事を参考にしました。
画面キャプチャと実際の画面は少し違いましたが、問題なく登録できたので、問題ないと思います。
Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ

その場ですぐ登録完了ではなく、審査がありますので、先に申請しておくことをおすすめします。
ぼくの場合は申請してから、1日後には承認されました。

callbackURL

TwitterAPIの画面でcallbackURLを設定できます。

callbackURLに記載のURLのみが、Twitter認証が許可されますので、本番環境URLと開発環境URLを登録しておきましょう。(何個でも登録可能)

・本番環境
https://[ドメインまたはIPアドレス]/users/auth/twitter/callback

・開発環境
https://localhost:3000/users/auth/twitter/callback

・開発環境がcloud9の場合
cloud9でブラウザを開いたURLが入るので、https://のあとからamazonaws.comまでのURLをコピペ
https://[amazonaws.comまでのURL]/users/auth/twitter/callback

これで、本番環境、開発環境で登録しておけば、どちらの環境でも動作確認ができます。

API KeyとAPI Secret Key

取得したAPI KeyAPI Secret Keyはあとで、使うのでメモしておいてください。

Gemのインストール

Gemは2つのGemをインストールしていきます。

omniauthというGemは、SNSなどの複数の外部サービスのログインや登録を管理できるGemです。

omniauthは、各SNSごとに別のGemが用意されているので併用して使います。

gem 'omniauth', '1.9.1'
gem 'omniauth-twitter'

ここで注意してほしいのが、omniauthのバージョンを指定している点です。

現在の最新のバージョンは、2.いくらなのですが、仕様が変更して、最新のバージョンだと今回の方法ではうまく動作しません。

実際このバージョンを指定しなかったため、2日ほど時間を無駄にしました。。。(初心者にバージョン違いのエラーは厳しすぎる...)

$ bundle install

お忘れなく。

API KeyとAPI Secret Keyを環境変数に

API KeyとAPI Secret Keyは、だれにも知られたくないので、.envファイルに記述して環境変数にしていきます。

環境変数わからない方向けに、ざっと説明

環境変数にせずにファイルにそのままAPI KeyやAPI Secret Keyを記述して、GitHubにあげてしまうと、全世界に向けて大事な大事な情報を公開してしまいます。

なので、GitHubに大事な情報はあげないように設定をします。

手順としては、以下

  • gem 'dotenv-rails'をインストール
  • .envファイルを作成しその中に環境変数を定義
  • gitignoreファイルに.envを追加

今回は、環境変数を定義するところから解説していきます。

.envファイルに記述

環境変数として、
API Keyは、TWITTER_CONSUMER_KEY
API Secret Keyは、TWITTER_CONSUMER_SECRET

DOMAIN_NAMEには、動作確認したい環境のドメインまたはIPアドレスを入れてください。

TWITTER_CONSUMER_KEY = "メモしたAPI Key"
TWITTER_CONSUMER_SECRET = "メモしたAPI Secret Key"

DOMAIN_NAME = "ドメインまたはIPアドレス"

まずは開発環境で動作確認して問題なければ、本番環境のドメインまたはIPアドレスを入れるといいと思います。

EC2サーバーを使う場合は、cloud9では開発環境、ES2サーバー上では本番環境のドメインまたはIPアドレスに変更する方法もあります。(こっちのほうが、デプロイ後も開発環境で動作確認できるのでいいかも)

gitignoreに追加

せっかく.envファイルに環境変数を定義しても、このままだとGitHubにあがってしまうので、gitignoreファイルに.envを追加してGitHubにあげないように設定します。

:
.env

deviseの設定

deviseで、Twitter認証が行われるように.envファイルに環境変数として定義した値を用いて設定を記述します。

config/initializers/devise.rb
:
  # Twitter認証
  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用
end

omniauthでtwitterが使えるように設定を追加します。

models/user.rb
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         # Twitter API認証用に追加
         :omniauthable, omniauth_providers: [:twitter]
:

Twitter認証時にUserモデルでデータを作る

Twitter認証でログインした際に、
はじめてのログインの場合は、Twitterの情報を元に新しくユーザーを登録する。
すでに作成済みの場合は、Userテーブルから同じデータを持ってくる。
という処理を記述していきます。

Userテーブルにカラムを追加

Twitter認証をしているユーザーかを判断するために、uidカラムとproviderカラムを追加します。

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

userモデルに処理を記述

userモデルに、Twitter認証時のログインに関する処理を記述していきます。

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

userテーブルにemailを保存する必要がある場合は、ダミーのメールアドレスを作成します。

omniauthコントローラーの設定

コールバック時の処理を記述していきます。

controllers/users/omniauth_callbacks_controller.rb
:
  # コメントアウト外して、処理追加(8行目あたり)
  def twitter
    callback_from :twitter
  end
:
  # 最後の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
end

ルーティング

omniauth_callbacksのルーティングを設定します。

devise_forに追加してください。

config/routes.rb
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    passwords: 'users/passwords',
    registrations: 'users/registrations',
    # Twitter API認証用
    :omniauth_callbacks => 'users/omniauth_callbacks',
  }

ビュー

最後に、ビューにTwitter認証用のリンクを作成していきます。

今回は、deviseの_links.html.erbファイルに記述していきます。

他にもregistrationやsessionの、newファイルに直接記述する方法もあります。
ご自身のお好きなスタイルにあわせて、カスタマイズしてください。

views/devise/shared/_links.html.erb
:
<%- if devise_mapping.omniauthable? %>
  <%- resource_class.omniauth_providers.each do |provider| %>
    <!--以下1行を編集-->
    <%= link_to "#{OmniAuth::Utils.camelize(provider)}アカウントでログイン", omniauth_authorize_path(resource_name, provider), class:'fab fa-twitter', method: :post %>
  <% end %>
<% end %>

これで、この作成したリンクをクリックすることで、Twitter認証画面に飛んで、認証できればログインできるようになります!

まとめ

はじめてAPIを使ったので、苦労しましたが、いい経験になりましたし、ユーザーも新しいアカウントを作る手間がなくなるので、使い勝手も上がりました!

苦労した点としては、
TwitterAPIとdeviseを組み合わせる方法が、deviseの無しの方法より難しかった。
なにより、omniauthのバージョン指定にはやられましたw

今後はTwitter以外のFacebookやGoogleなんかの認証にもチャレンジしていきたいですね!

同じようなところで詰まってる方の参考になれば幸いです。

10
11
0

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
10
11