maehachi08 Anything Blog

2012年10月23日
Rails3.2.8でomniauthによるOauth認証の実装(twitter編)

omniauthとは

omniauthとはRailsのWebアプリケーションにOAuth認証を実装するためのライブラリであり、複数の認証プロバイダーをサポートしています。複数の認証プロバイダーをサポートするので開発者は多くのユーザを認証することが可能になります。
(バージョン1.0.0からは)strategiesという考え方が導入されました。strategiesとは認証プロバイダー単位で分割された認証モジュールを指します。つまり、OAuth認証に使用する認証プロバイダーがtwitterなのかfacebookなのかでGemfileに記述するgemモジュール名が変わってきます。もちろん、複数のgemモジュールを組み合わせることも出来ます。このstrategiesという考え方のお陰で、認証プロセスが認証プロバイダーごとに微妙な差異があったとしても、開発者がそれを意識せずにomniauthの規約に沿った記述方法でOauth認証を実装出来るのです。どの認証プロバイダーに対応しているのかは、strategiesのリストを参照しましょう。
(バージョン1.0.0からは)omniauthでは認証プロバイダーによって認証されたユーザのユーザ情報をハッシュ形式で返しますが、このハッシュのスキーマが変更されました。これは(omniauthで一般的に使われる)sessionsコントローラの記述が以前の0.3系から変更せざるを得ないことを意味します。0.3系と1.0系でのスキーマ情報の差異についてはAuth Hash Schemaを参照してください。

Gemfile追記とbundle install

今回はTwitterを認証プロバイダーとして使用しますので、strategiesはomniauth-twitterを選択します。

gem 'omniauth'
gem 'omniauth-twitter'

gemをインストールします。

# bundle install

Railsに組み込むミドルウェア定義

omniauthをRailsアプリケーションに組み込む場合はconfig/initializersディレクトリ以下にミドルウェアを追加します。

# vim config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, 'APP KEY', 'APP SECRET'
end

セッション情報管理用コントローラを生成

Oauth認証では、認証プロバイダー側のWebページへリダイレクトされてアカウント認証を行い、認可されるとOauth認証を実装したWebページへコールバックします。このコールバック先のアクションと、ログアウト時の処理を記述したアクションをsessionsコントローラに記述します。

# rails g controller sessions
      create  app/controllers/sessions_controller.rb
      invoke  erb
      create    app/views/sessions
      invoke  test_unit
      create    test/functional/sessions_controller_test.rb
      invoke  helper
      create    app/helpers/sessions_helper.rb
      invoke    test_unit
      create      test/unit/helpers/sessions_helper_test.rb
      invoke  assets
      invoke    js
      create      app/assets/javascripts/sessions.js
      invoke    css
      create      app/assets/stylesheets/sessions.css
# vim app/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def login
    auth = request.env['omniauth.auth']
    user_info = request.env['omniauth.auth']['info']
    user = User.find_by_provider_and_uid(auth['provider'], auth['uid']) || User.create_with_omniauth(auth,user_info)
    session[:user_id] = user.id
    redirect_to root_url, :notice => 'login success'
  end

  def logout
    session[:user_id] = nil
    redirect_to root_url, :notice => 'logout successs'
  end

end

userモデル生成

OAuth認証では、認可判定は認証プロバイダーが行うが、自Webサービスにて最低限のユーザ情報を管理する必要があります。OAuthはそのユーザ情報をハッシュ形式で提供します。ハッシュの中からnicknameやプロバイダー名などを取得し、データベースに格納しておく必要があります。これらの情報を管理するモデル「user」を生成します。

# rails g model user provider:string uid:string name:string
# rake db:migrate

app/models/user.rbにメソッドを記述します。

class User < ActiveRecord::Base

  def self.create_with_omniauth(auth,user_info)
    create!do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.name = user_info["name"]
    end
  end

end

ビュー設定

ビュー内にOAuth認証を実行するためのリンクとログアウトするためのリンクを実装する必要があります。この2つのリンクはOauthにてログイン済みか否かを判定して表示させる必要があります。

# vim app/views/layouts/application.rb
      <% if current_user %>
        <a href=# class=login_user>Logged as <%= current_user.name%></a>
        <%= link_to "Logout", "/logout" ,{ :class => "menu_link" } %>
      <% else %>
        <%= link_to 'Login as Twitter', { :controller => 'auth',
                                          :action     => 'twitter'},
                                        { :class      => "menu_link" } %>
      <% end %>