【rails】DeviseでTwitter認証を実現!

  • このエントリーをはてなブックマークに追加
twitter画像

railsを使用していて、SNS認証機能を実装したいと思ったことはありませんか??

SNS認証は、ユーザとサイト管理者の双方にメリットがあります!ユーザは、SNSアカウントを使用することで個別のパスワード管理をしなくてすみます。サイト管理者は、認証機能を作成する負担が減ります。
今回は、Railsとdevise、omniauthを使用します。それでは、実際に見ていきましょう!

※実装したコードはGitHubにあげています。
deviseで実現するTwitter認証

devise、omniauthの導入!

1.Gemfileの準備(該当する部分のみ抽出しています!)

[Gemfile]

・・・
gem 'rails', '~> 5.2.0'
gem 'devise', '~> 4.4'
gem 'omniauth-twitter'
・・・
group :development, :test do
  ・・・
  gem 'rspec-rails'
  ・・・
end

2.インストール

$ cd app
$ bundle exec install --path=vendor/path

omniauthの設定!

1.マイグレーションファイルの作成

$ bundle exec rails g maigration AddColumnToUser
-> 「db/migrate/20180706135816_add_columns_to_users.rb」が作成されます。 

2.Twitter認証で必要なカラムをUserテーブルに追加

以前の記事「【rails】deviseで実現するユーザ認証機能」でUserテーブルは作成済みとします。)

[db/migrate/20180706135816_add_columns_to_users.rb]

class AddColumnsToUsers < ActiveRecord::Migration[5.2]
  def change
    # provider には、「twitter」などのSNS提供元名が入ります。
    add_column :users, :provider, :string

    # uidには、oauth認証時のリクエストに含まれるユーザIDが入ります。(ユーザを識別する値)
    add_column :users, :uid, :string

    # SNSで使用しているユーザ名が入ります。
    add_column :users, :user_name, :string
  end
end

3.マイグレートの実行

$ bundle exec rails db:migrate

4.モジュールの追加

[app/models/user.rb]

# 「:omniauthable」、「omniauth_providers: [:twitter]」を追加する。
devise :database_authenticatable, :registerable,
       :recoverable, :rememberable, :trackable, :validatable,
       :confirmable, :lockable, :timeoutable
       :confirmable, :lockable, :timeoutable, :omniauthable, omniauth_providers: [:twitter]
 end

5.twitterのAPI keyとAPI secretを追加

環境変数を使って、登録します。

ENV.fetch()

は、環境変数が設定されていないときは例外を発生させるメソッドになります。

Twitter APIのKeyとAccess Tokenを取得するまでの手順」などを参考にAPI keyとAPI secretを取得しておきます。

[config/initializers/devise.rb]

config.omniauth :twitter, ENV.fetch("TWITTER_API_KEY"), ENV.fetch("TWITTER_API_SECRET"), callback: ENV.fetch("TWITTER_CALLBACK_DEV")

6.コールバック用のコントローラーを作成

$ bundle exec rails g controller OmniauthCallbacks

### 7.ルーティングの追加
コールバック用のルーティングを追加require ‘rails_helper’

[config/routes.rb]

devise_for :users, controllers: { omniauth_callbacks: "omniauth_callbacks" }

つづいて、テストコードの作成!

追加する機能は以下。rspecを使用して、テストコードを作成していきます。
・Twitter認証で取得したuidなどをUserテーブルに保存する機能

1.「Twitter認証で取得したuidなどをUserテーブルに保存する機能」のテストコード

[spec/models/user_spec.rb]

require 'rails_helper'
require 'securerandom'
 
RSpec.describe User, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"

  describe "#self.from_omniauth" do
    let(:auth){ 
      { 
        "provider" => "test_provider",
        "uid" => "test_uid",
        "info" => { "nickname" => "testuser" }
      } 
    }
    context "when user is not created" do
      it "succeeded in creating user." do
        expect{ User.from_omniauth(auth) }.to change{ User.count }.by(1)
      end
    end
    context "when user has already been created" do
      it "succeeded in creating user." do
        User.from_omniauth(auth)
        expect{ User.from_omniauth(auth) }.not_to change{ User.count }
      end
    end
  end

end

いざ、実装!

1.「Twitter認証で取得したuidなどをUserテーブルに保存する機能」の追加

find_or_create_by!

は、該当のレコードが存在しなければ作成し、作成に失敗すると例外を発生させることができるメッソドです。
また、今回はEmail認証機能も有効にしています。

[app/models/user.rb]

def self.from_omniauth(auth)
  user = find_or_create_by!(provider: auth["provider"], uid: auth["uid"]) do |user|
  user.skip_confirmation!
  user.provider = auth["provider"]
  user.uid = auth["uid"]
  user.user_name = auth["info"]["nickname"]
  user.email = auth["email"].nil? ? auth["provider"] + auth["uid"] + "@login.function" : auth["email"]
  user.password = SecureRandom.urlsafe_base64(16)
  end
end

2.「Twitter認証で使用するコールバック処理機能」の追加

from_outh()

は、テスト実施済み。

sign_in_and_resirect

は、deviseの機能。従って、テストコードは作成していません。

[app/controllers/omniauth_callbacks_controller.rb]

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def twitter
    @user = User.from_omniauth(request.env["omniauth.auth"].except("extra"))
    sign_in_and_redirect @user
  end
end

まとめ

以上で、Twitter認証の実装が完了です!そこまで複雑なロジックでは無いですが、とてもシンプルなわけでもないです。従って、ミスを発見するためにも、しっかりとテストコードを書くことが今回の一番のポイントかもしれません。是非、参考にしてみて下さい!

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメントを残す

*