すべてがヒントだ

mk-laboratory管理人であるkodashoのブログ

RailsアプリケーションにTwitterとFacebookの認証機能をつける

概要

新しいサービスを利用するのにユーザ登録が必要な場合、利用者にとっては手間がかかり利用するハードルが上がってしまいます。

しかし、現在広く使われているTwitterFacebookアカウントを利用した認証機能を使うことで、ユーザは気軽にアプリケーションを利用できるはずです。

本記事ではRailsアプリケーションでOmniAuthを用いてTwitterFacebookアカウントの認証をする方法を記します。

環境

1.TwitterAPI,FacebookAPIにアプリケーションを登録する

以下のURLからそれぞれアプリケーション登録を行い、アプリケーションID(APIキー)とSecretキー(APIシークレット)をメモしておきます。

それぞれの詳しい登録方法は以下のサイトを参考にしてください

※FacebookAPIでは、基本データから、「+Add Platform」で「ウェブサイト」を選択し、「サイトURL」の入力を忘れないで下さい。

2. アプリケーションの作成

  • 実際にRailsアプリケーションを作成します
  • Railsアプリを開発する上での基本的なコマンドの説明は省略します

2.1 OmniAuthのインストール

  • プロジェクトを作成したらGemfileに必要なgemを追加します
  • 本環境では、'omniauth-facebook'のバージョン1.4.1以上では動作を確認できませんでしたので1.4.0を利用しています
$ vim Gemfile
--

# 以下を追記
gem 'omniauth-twitter'
gem 'omniauth-facebook', '1.4.0' 
  • bundle installを実行
$ bundle install

2.2 モデルの作成

  • 認証したユーザ情報を保存する為のモデルを作成
  • 以下のコマンドを実行しUserという名のモデルを作成します
$ rails g model User provider uid name image oauth_token oauth_expires_at:datetime
  • db:migrateを実行します
$ rake db:migrate
  • Userモデルのレコード作成をOmniAuthのデータを用いて行う関数を用意
$ vim app/models/user.rb
--
class User < ActiveRecord::Base

  def self.from_omniauth(auth)
    where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      
      unless auth.info.blank?
        user.name = auth.info.name
        user.screen_name = auth.info.screen_name
        user.image = auth.info.image
      end

      user.oauth_token = auth.credentials.token
      user.oauth_expires_at = Time.at(auth.credentials.expires_at) unless auth.credentials.expires_at.nil? 
      user.save!
    end
  end

end

2.3 セッション管理設定

  • ApplicationControllerにアプリケーション内で共通に利用出来るヘルパーメソッドと呼ばれる関数を作成
  • ここでは現在のユーザ情報を取得するcurrent_user関数を作成
$ vim app/controllers/application_controller.rb
--
class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception

  private
  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
  helper_method :current_user

end
  • セッション管理のためのコントローラ"sessions"を作成
  • 内部ではOmniAuthのサインイン情報から、登録されているユーザかどうかの検索を行う
  • サインイン中はsession[:user_id]にユーザIDが保存される
  • サインアウト時にはsession[:user_id]を削除
$ rails g controller sessions
$ vim app/controllers/session_controller.rb
--
# coding: utf-8

class SessionsController < ApplicationController

  def create
    user = User.from_omniauth(env["omniauth.auth"])
    session[:user_id] = user.id

    redirect_to root_path, :notice => 'サインインしました'
  end

  def destroy
    session[:user_id] = nil

    redirect_to root_path, :notice => ' サインアウトしました'
  end

  def oauth_failure
    redirect_to root_path, :notice => ' サインイン処理が中断されました'
  end

end

2.4 OmniAuthの設定

  • /config/initializer/omniauth.rbを新規作成します
  • ここでtwitterFacebookのIDとシークレットキーを入力します
  • APPIDやAPP_SECRETは先程メモしておいたキーを入力します
$ vim config/initializer/omniauth.rb
--

OmniAuth.config.logger = Rails.logger

OmniAuth.config.on_failure = SessionsController.action(:oauth_failure)

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, 'APPID', 'APP_SECRET' 
  provider :twitter, 'Consumer Key’,’Consumer Secret’
end

2.5 ルーティング設定

  • 認証を可能にするために以下のルーティングを追加します
$ vim config/routes.rb
--

match 'auth/:provider/callback', to: 'sessions#create', via: [:get, :post]
match 'auth/failure', to: redirect('/'), via: [:get, :post]
match 'signout', to: 'sessions#destroy', as: 'signout', via: [:get, :post]

2.6 サインインリンクとユーザ情報の表示

  • すべての画面でサインイン状態を示すためapplication.html.erbを編集
  • 2.4で作成したヘルパーメソッドでcurrent_userが取得できる
  • サインインしていない場合はサインインリンクを表示
$ vim app/view/layout/application.html.erb
--
<body>
 <div id="user-widget">
  <% if current_user %>
    ようこそ<%= current_user.name %>
    <%= link_to "Sign out", signout_path, id: "sign_out" %>
  <% else %>
    <%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %>
    <%= link_to "Sign in with Twitter", "/auth/twitter", id: "sign_in" %>
  <% end %>
</div>
<%= yield %>
</body>
</html>

注意

  • 2.6のコード内の/auth/twitterのようにリンク先が設定されている箇所について
    • サーバー内でRailsアプリケーションをサブディレクトリ内で動作させている場合、ルーティングが上手くいきません
    • /hogeディレクトリで動作させている場合、/hoge/auth/twitter のように記述する必要があります

おわりに

以上のステップでRails4でサインインとサインアウトの処理が可能になったと思います。 この先はcurrent_userのIDやセッション情報と各種データ、APIを紐付けて様々なウェブサービスの開発ができることに期待します。

参考