読者です 読者をやめる 読者になる 読者になる

【Rails】Authlogic + OmniAuth でソーシャル認証を実装する

Rails gem

Authlogicの導入は以下記事を参考にしてください。
【Rails】 Authlogicでユーザー認証機能

gem を追加

# Gemfile

gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-facebook'

認証するには Twitter/Facebook Developers にアプリを登録して認証情報を取得する必要があります。

Twitter Developers に登録する

https://dev.twitter.com/apps/new

  1. ログインする
  2. 必要な情報を入力する

    Name: authlogic+omniauth
    Description: authlogic + omniauth test
    Website: http://kzy52.com
    Callback URL: http://kzy52.com

  3. 「Consumer key」と「Consumer secret」をメモしておく

Facebook Developers に登録する

https://developers.facebook.com/apps

  1. ログインする
  2. 右上の「新しいアプリを作成」をクリックする
  3. 必要な情報を入力する

    App Name: Authlogic+Omniauth
    App Namespace:
    App Category:
    Web Hosting:
    Facebookでログインするウェブサイト http://localhost:3000/

  4. 「App ID」と「App Secret」をメモしておく

取得したプロバイダー情報を設定する

# config/initializers/omniauth.rb

# CONSUMER_KEY, CONSUMER_SECRET, APP_ID, APP_SECRETには先程メモしたものを設定する。
Rails.application.config.middleware.use OmniAuth::Builder do
    provider :twitter, "CONSUMER_KEY", "CONSUMER_SECRET"
    provider :facebook, "APP_ID", "APP_SECRET"
end

リンクとroutes を設定する

# app/views/layouts/application.html.erb

<%= link_to "Twitterでログイン", "/auth/twitter" %>
<%= link_to "Facebookでログイン", "/auth/facebook" %>
# app/views/portals/index.html.erb

<%= link_to "Twitter連携", "/auth/twitter" %>
<%= link_to "Facebook連携", "/auth/facebook" %>

<% current_user.authentications.each do |auth| %>
  <%= link_to "#{auth.provider.capitalize}との連携解除", authentication_path(auth), method: :delete %>
<% end %>

認証後にリダイレクトされるパスを設定する。

# config/routes.rb

resources :authentications, only: :destroy
get "/auth/:provider/callback", to: "authentications#create", as: "authentications"

コントローラーを作成する

$ rails g controller Authentications
# app/controllers/authentications_controller.rb

class AuthenticationsController < ApplicationController
  skip_before_action :require_login, only: :create

  # GET /auth/:provider/callback
  def create
    omniauth = request.env["omniauth.auth"]

    if current_user
      Authentication.create_from_hash(omniauth, current_user)
      flash[:notice] = "Authentication successful."
    elsif authentication = Authentication.find_by(provider: omniauth["provider"], uid: omniauth["uid"])
      UserSession.create(authentication.user)
      flash[:notice] = "Signed in successfully."
    else
      UserSession.create(Authentication.create_from_hash(omniauth).user)
      flash[:notice] = "User created and signed in successfully."
    end
    redirect_to root_url
  end

  # DELETE /authentications/:id
  def destroy
    authorization = current_user.authentications.find(params[:id])
    authorization.destroy
    redirect_to root_url, notice: "Successfully destroyed authentication."
  end
end

モデルとテーブルを作成する

$ rails g model Authentication
# db/migrate/20130719170436_create_authentications.rb

class CreateAuthentications < ActiveRecord::Migration
  def change
    create_table :authentications do |t|
      t.integer :user_id
      t.string  :provider
      t.string  :uid

      t.timestamps
    end
  end
end
$ rake db:migrate
# app/models/authentication.rb

class Authentication < ActiveRecord::Base
  belongs_to :user

  validates :user_id, :uid, :provider, presence: true
  validates :uid, uniqueness: { scope: :provider }
  validates :provider, inclusion: { in: ["twitter", "facebook"] }

  def self.create_from_hash(hash, user = nil)
    user ||= User.create_from_hash(hash)
    user.authentications.create(provider: hash["provider"], uid: hash["uid"])
  end
end
# app/models/user.rb

  has_many :authentications, class_name: Authentication

  def self.create_from_hash(hash)
    user = new(nickname: hash["info"]["nickname"] || hash["info"]["name"])
    user.save(validate: false)
    user.reset_persistence_token!
    user
  end

Faraday::Error::ConnectionFailed (SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed): エラーが出る場合

これで解決

$ brew install curl-ca-bundle
$ brew list curl-ca-bundle
$ cp /usr/local/Cellar/curl-ca-bundle/1.87/share/ca-bundle.crt /usr/local/etc/openssl/cert.pem

参考にしたサイト

http://emumair.wordpress.com/2011/03/17/social-network-authentication-with-omniauth-and-authlogic/
http://qiita.com/hotchpotch/items/12457815d5cee3723b97