yonet77的な雑記帳

日々思いついたネタなどを書き留めておきます

OmniAuth + Salesforce を試してみた (1)

今回はgOMネタから離れて、Railsネタです。(実はRubyをちょこっと使うことがw えぇ、ほんのちょこっとです。)
というわけ(?)で、OmniAuthを使って、SalesforceをOAuthプロバイダにした認証を試してみました。

OmniAuth って?

Railsアプリに対して、Twitter, Facebook... etc によるOAuth認証機能を提供してくれます。詳しい話は、こっちを参照してもらえれば・・思います。

大抵の場合では、Twitter, FacebookをOAuthプロバイダに使ったサンプルが多いです。そのプロバイダとして「Salesforce」も使えるよ、ということで試してみた話となります。
なお、OmniAuthで使えるプロバイダのリストはこんな感じになっています。

そして、Salesforceもありますねー!スバラシイですね〜。

また、Force.comにおけるOAuth2.0の認証については、Digging Deeper into OAuth 2.0 on Force.comに記載していますので、併せてご参照下さい。


それじゃまぁ、やってみましょうか。ちなみに、自分の環境はこんな感じです。

※新しいのを入れろよ、自分... てへぺろ


Salesforce側の設定

Salesforceにログインして、

設定 → アプリケーションの設定 → 開発 → リモートアクセス

で、アプリケーションを登録しておきます。(以下、サンプルです)
なお、取引先責任者メールには連絡先を登録しておけば良いのでは・・?と思います。テキトーですみません。。
f:id:yonet77:20120402223514p:plain


登録した後、コンシューマ鍵コンシューマの秘密を確認しておきましょう。
※後で使います。
f:id:yonet77:20120402223854p:plain

ちなみに、

  • Consumer Key → コンシューマ鍵
  • Consumer Secret → コンシューマの秘密

と訳しているのかと思いますが、「コンシューマの秘密」って何か不思議ww


Railsアプリの作成

※ちなみに、Salesforceのアカウントは持ってるものとして話を始めますので、持ってない場合は先にコチラ(Developerforce)にて開発者用アカウントを用意しておいて下さい。。
Railsアプリをまずは作成しましょうか。

rails new salesforce -d postgresql

Gemfileに以下を追加しておきましょう。

gem 'omniauth'
gem 'omniauth-salesforce'
gem 'pg'

※DatabaseにpostgreSQLを指定しているので、 gem 'pg' も追加しています。
omniauthに該当するのは、上2行分だけです。
そして、gemをインストールしておきましょう。

$ bundle install

Databaseがなければ作成しておきましょう。
※database.yml は適宜修正しておいて下さい。

$ rake db:create

プロバイダ情報の設定

config/initializers/omniauth.rb を新規に作成して、以下を追記しておきましょう。

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :salesforce, ENV['SALESFORCE_KEY'], ENV['SALESFORCE_SECRET']
end

環境変数に格納している値は、とりあえずapplication.rbに追記しておきましょう。

#config/application.rb
module Salesforce
  class Application < Rails::Application
    ....
  end
end

ENV['SALESFORCE_KEY'] = (コンシューマ鍵)
ENV['SALESFORCE_SECRET'] = (コンシューマの秘密)


Sandbox環境や、Database.comにアクセスする場合は、以下のプロバイダ情報も設定しておきましょう。

Rails.application.config.middleware.use OmniAuth::Builder do
  provider OmniAuth::Strategies::SalesforceSandbox,
                       ENV['SALESFORCE_SANDBOX_KEY'],
                       ENV['SALESFORCE_SANDBOX_SECRET']
  provider OmniAuth::Strategies::DatabaseDotCom,
                       ENV['DATABASE_DOT_COM_KEY'],
                       ENV['DATABASE_DOT_COM_SECRET']
end

Model の生成 (User)

Userモデルを作成しておきましょう。

$ rails g model user

そして、作成したマイグレーションファイルを修正しましょう。

# db/migrate/XXXXXXXXXXXXXX_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :provider, :null => false
      t.string :uid, :null => false
      t.string :name, :null => false
      t.string :nickname, :null => false

      t.timestamps
    end
    add_index :users, [:provider, :uid]
  end

  def self.down
    drop_table :users
  end
end

そいでもって、Userモデルも修正します。

# app/models/user.rb
class User < ActiveRecord::Base
  def self.create_with_omniauth(auth)
    create! do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.name = auth["info"]["name"]
      user.nickname = auth["info"]["nickname"]
    end
  end
end

※コールバックで取得したデータからUserデータを作成する処理を追加している・・といった感じでしょうか。

そして、migrate コマンドを実行してUserテーブルを作成しておきましょう。

$ rake db:migrate

Controller の生成 (Sessions) & ルーティングの設定

SessionsController を作成しましょう。

$ rails g controller sessions

そして、SessionsControllerに以下の処理を追記します。

# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def callback
    auth = request.env["omniauth.auth"]
    user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth)
    session[:user_id] = user.id
    redirect_to root_path, :notice => 'Welcome to Salesforce!!'
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
end

※providerとuidで該当するUserデータがなければ、Userモデルに追加した User#create_with_omniauth を呼び出して新規作成してます。

ApplicationController には以下を追記しておきます。

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  ...

  helper_method :current_user

  private

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

そして、routes.rb に認証のためのルーティングを追記しておきます。

# config/routes.rb
match '/auth/:provider/callback' => 'sessions#callback'
match '/signout' => 'sessions#destroy', :as => :signout

View の生成 (テスト用のページ)

検証用のテストページを生成しましょう。

$ rails g controller test index

とりあえず、index.html.erb はこんな程度で・・

# app/views/test/index.html.erb
<h1>Test#Index</h1>
<% if current_user %>
  Welcome <%= current_user.name %>!
  <%= link_to "Sign Out", signout_path %>
<% else %>
  <%= link_to "Sign in with Salesforce", "/auth/salesforce" %>
<% end %>
<br/>
<p id="notice"><%= notice %></p>

そして、検証用のページのルーティングを追記しておきましょう。

# config/routes.rb
root :to => 'test#index'

あと、public/index.html があれば削除するか、リネームしておきましょう。


検証

サーバを起動しましょう。

$ rails s

http://localhost:3000/ にアクセスして、リンク 'Sign in with Salesforce' をクリックしてみましょう。
f:id:yonet77:20120402234620p:plain

認証後、Salesforce側に画面が遷移します。ここで(素直に)「許可」をクリックして下さい。
f:id:yonet77:20120403000631p:plain

そうすると、localhost側に戻ってきます。
f:id:yonet77:20120403000752p:plain



とまぁ、こんな感じでSalesforceをOAuthプロバイダに使った認証機能を作ることができます。いやー、ホント、こういうgemを作ってくれる開発者ってすごいですよね〜。多々感謝です。
ソースコードココ(Github)に置いておきます。何かの足しになれば...

ちなみに、Salesforceを使って認証させて何か嬉しいのか?と問われると・・回答に詰まってしまうので、そのうち勉強しておきます。。
まぁ、Ap○xとVisual何とか Pageとか、あまり好きじゃないんだよね・・という場合に、RailsからSalesforceにアクセスできるようになりまっせ、といったあたりはあるでしょうか。。


というわけで、この続きはどこかでできたらいーなーと思いつつ・・。
OmniAuthを使ってみた、というお話でした。ではでは〜!