SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

これだけは押さえておきたい! Rails開発で使えるgemパッケージ/ツール

RailsでSNS認証機能を実装しよう~定番gem「OmniAuth」活用法

これだけは押さえておきたい!Rails開発で使えるgemパッケージ/ツール 第3回

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

Facebook認証機能の実装(2)

gemを追加

 Facebook/Twitter認証に必要なgemを追加します。今回追加するgemは以下の通りです。

表:Facebook認証機能実装にあたり追加するgem
gem 機能
omniauth omniauth本体
omniauth-facebook omniauthのFacebook連携用ストラテジー
omniauth-twitter omniauthのTwitter連携用ストラテジー
dotenv-rails アプリIDやapp secretを環境変数で管理

 なおdotenv-railsは、Railsアプリのルートディレクトリ直下に .envファイルを配置すると、 .envファイル内に記述されている環境変数を読み込んでくれる機能を提供するgemです。FacebookアプリのアプリIDやapp secretなどは、センシティブな情報なので設定ファイルに直接記述するより、環境変数としてGitの外で管理する方がよいです。

 dotenv-railsは、Railsがdevelopment/testモード時にのみ有効となるようにインストールします。

[リスト 1]Gemfile
…(中略)…
gem 'devise'
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-twitter'

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '~> 2.13'
  gem 'selenium-webdriver'
  gem 'dotenv-rails'
end
…(中略)…

 以下のコマンドでgemをインストールします。なお、bundle installコマンドの「install」は以下のように「inst」と省略可能です。

bin/bundle inst

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

 OmniAuthによるSNS連携では、サービス名を「provider」というカラム名で、サービスごとのユーザーIDを「uid」というカラム名で保存して管理します。また、SNS連携時に外部サービスで登録済みの名前(name)などを取得することもできます。今回は「name」というカラム名も合わせて追加します。

 以下のコマンドでこれらのカラムを追加するマイグレーションファイルを作成します。

bin/rails g migration AddColumnsToUsers name:string provider:string uid:string

 作成されたマイグレーションファイルを以下のコマンドで適用します。

bin/rails db:migrate

FacebookのアプリIDとapp secretを設定

 deviseの設定ファイルにOmniAuth連携用の設定を記述する箇所があります。デフォルトではGitHub用の設定がコメントアウトされているので、その下に以下の通り設定を追加します。

[リスト 2]config/initializers/devise.rb
…(中略)…
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET']
…(中略)…

 次に、.envファイルにFacebookのアプリIDとapp secretを環境変数として指定します。

[リスト 3].env
FACEBOOK_APP_ID=[アプリID]
FACEBOOK_APP_SECRET=[app secret]

 このように環境変数を設定することで、Railsアプリ側ではENV['環境変数名']として.envに指定した値を利用することができます。

ルーティング/コントローラーの作成

 deviseのコントローラーは、前回までの連載記事で紹介した通り、Rails enginesの仕組みを通してgemに組み込まれています。そのため、特にカスタマイズが不要であればgemに定義したものをそのまま流用することができます。

 しかしOmniAuthとの連携を通じては、deviseが提供するコントローラーをカスタマイズする必要があります。具体的には、SNS認証後のコールバック時に外部サービスからアクセスされるエンドポイントに処理を実装するなどの対応が必要です。

 deviseにはこういった場合に備えて、コントローラーを自動生成するコマンドが用意されているので、以下のコマンドを実行してdeviseが提供するコントローラーを作成します。

bin/rails g devise:controllers users

 ▼

      create  app/controllers/users/confirmations_controller.rb
      create  app/controllers/users/passwords_controller.rb
      create  app/controllers/users/registrations_controller.rb
      create  app/controllers/users/sessions_controller.rb
      create  app/controllers/users/unlocks_controller.rb
      create  app/controllers/users/omniauth_callbacks_controller.rb
===============================================================================

Some setup you must do manually if you haven't yet:

  Ensure you have overridden routes for generated controllers in your routes.rb.
  For example:

    Rails.application.routes.draw do
      devise_for :users, controllers: {
        sessions: 'users/sessions'
      }
    end

===============================================================================

 最後の引数のusersは、認証に使うユーザーテーブルの物理名を指定します。今回は、前回記事から継続してusersテーブルを使用していますのでusersを指定します。実行結果の通り、deviseが提供するコントローラーがapp/controllers/users配下に自動生成されます。

 実行結果に示されるように、作成したコントローラーが使われるようにルーティングを再定義します(リスト4)。

[リスト 4]config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    omniauth_callbacks: 'users/omniauth_callbacks',
    registrations: 'users/registrations'
  }
  root to: 'home#index'
end

 このように定義することで、deviseでは呼び出されるコントローラーを指定することができます。今回の機能実現のためにはSNS認証時のコールバック処理(omniauth_callbacks)とユーザー登録/編集処理(registrations)の実装をカスタマイズするため、これらのコントローラーの定義を追加しています。

 次に、作成されたコントローラーのうち、SNS認証時のコールバック処理を定義するomniauth_callbacks_controller.rbを以下のように修正します。

[リスト 5]app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniAuthCallbacksController < Devise::OmniAuthCallbacksController
  # You should configure your model like this:
  # devise :omniauthable, omniauth_providers: [:twitter]

  # You should also create an action method in this controller like this:
  def twitter
    callback
  end

  def facebook
    callback
  end
…(中略)…
  private

    def callback
      @user = User.find_or_create_for_oauth(request.env['omniauth.auth'])

      if @user.persisted?
        sign_in_and_redirect @user
      else
        session['devise.user_attributes'] = @user.attributes
        redirect_to new_user_registration_url
      end
    end
end

 deviseが提供するジェネレーターコマンドで作成したコントローラーは、継承元がDevise::OmniAuthCallbacksControllerとなっていることに注目してください。deviseが提供するコントローラーを継承しているので、あらかじめdeviseによって用意されたメソッドがコメントアウトされた状態となっており、修正が必要な部分のコメントアウトを外し、処理を追加してカスタマイズしていきます。なお、今回のFacebook/Twitter連携では処理を共通化できるので、privateメソッドであるcallbackメソッドに共通化した処理を定義して呼び出しています。

 callbackメソッドの1行目にあるUserモデルのクラスメソッドfind_or_create_for_oauthは、OAuth認証の情報から取得されるユーザーが登録済みであればfind結果を、未登録であれば新規作成したユーザーのインスタンスを返すメソッドです。具体的な処理はこの後Userモデルに実装していきます。ここでは、request.env['omniauth.auth']とすることで、OAuth認証後にユーザー情報が得られることを理解してください。

 後続のif文において、ユーザー情報が正常に保存できた(persisted?メソッドがtrueを返す)場合は、該当ユーザーでログインしてユーザー情報の画面にリダイレクトします。ユーザー情報が正常に保存できなかった場合は、セッションにユーザー情報を代入しつつユーザー登録画面にリダイレクトします。

次のページ
Facebook認証機能の実装(3)

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
これだけは押さえておきたい! Rails開発で使えるgemパッケージ/ツール連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 竹馬 力(チクバ ツトム)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10970 2018/07/30 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング