2014-01-21 17 views
20

私はRailsCastを開発し、オムニバスで見て、これらの宝石を使用する認証システムを設定するための関連チュートリアルに行きました。私はRailsCastが古くなっていると思って、他のチュートリアルとのギャップを修正しようとすると、あらゆる種類の問題が生じています。Rails 4、Devise、Omniauth(複数のプロバイダで)

私はこのシステムを実装するための基礎として使用できる現在のチュートリアルをお勧めします。私は別々のユーザーモデルと認証モデルを持っています(ユーザーは多くの認証を持っています)。

私は本当にレール4にdeviseとomniauth(CanCanと一緒に)を使いたいのですが、基本的なセットアップ(psqlをデータベースとして使用)を見つけようとしているときに私の髪を引き裂いています。もし初期化子で

+0

公式の文書は、行く方法です – emaillenin

+0

私はこの同じ問題を抱えています...任意のソリューションですか? –

+0

私はこれを見つけました:https://github.com/mohitjain/social-login-in-railsしかし、私はそれがユーザー/認証をTwitterからリンクするという問題を解決できるとは思いません。 Twitterは電子メールを共有せず、彼のUserモデルはその電子メールを使って以前のレコードを探します。うーん...うまくいけば、誰かがこのすべてに対して良い解決策を見つけることができます。 – robertwbradford

答えて

29

のようなものをやってみてください - ユーザーモデルのコードがあり認証

#authorization.rb 

# == Schema Information 
# 
# Table name: authorizations 
# 
# id   :integer   not null, primary key 
# user_id  :integer 
# provider  :string(255) 
# uid   :string(255) 
# token  :string(255) 
# secret  :string(255) 
# created_at :datetime 
# updated_at :datetime 
# profile_page :string(255) 
# 

class Authorization < ActiveRecord::Base 
    belongs_to :user 
end 

#user.rb 

SOCIALS = { 
    facebook: 'Facebook', 
    google_oauth2: 'Google', 
    linkedin: 'Linkedin' 
} 


has_many :authorizations 

def self.from_omniauth(auth, current_user) 
    authorization = Authorization.where(:provider => auth.provider, :uid => auth.uid.to_s, 
             :token => auth.credentials.token, 
             :secret => auth.credentials.secret).first_or_initialize 
    authorization.profile_page = auth.info.urls.first.last unless authorization.persisted? 
    if authorization.user.blank? 
    user = current_user.nil? ? User.where('email = ?', auth['info']['email']).first : current_user 
    if user.blank? 
     user = User.new 
     user.skip_confirmation! 
     user.password = Devise.friendly_token[0, 20] 
     user.fetch_details(auth) 
     user.save 
    end 
    authorization.user = user 
    authorization.save 
    end 
    authorization.user 
end 

def fetch_details(auth) 
    self.name = auth.info.name 
    self.email = auth.info.email 
    self.photo = URI.parse(auth.info.image) 
end 
例えば

そして、あなたはプロバイダのいくつかが必要な場合は最後に、あなたは工夫コントローラ

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 

    def all 
    user = User.from_omniauth(env['omniauth.auth'], current_user) 
    if user.persisted? 
     sign_in user 
     flash[:notice] = t('devise.omniauth_callbacks.success', :kind => User::SOCIALS[params[:action].to_sym]) 
     if user.sign_in_count == 1 
     redirect_to first_login_path 
     else 
     redirect_to cabinet_path 
     end 
    else 
     session['devise.user_attributes'] = user.attributes 
     redirect_to new_user_registration_url 
    end 
    end 

    User::SOCIALS.each do |k, _| 
    alias_method k, :all 
    end 
end 

するためのメソッドをオーバーライドする必要があり、 Twitterはユーザーのメールを提供しないので、Twitterの方法を無効にする必要があり、他の方法でそれを保存する必要があります。

はまた、あなたはあなたがこの宝石を試してみる必要があるルート

devise_for :users, 
      :controllers => { 
      :omniauth_callbacks => 'users/omniauth_callbacks', 
      } 
+6

コードを共有してくれてありがとう!権限とは認証とは区別されていますが、omniauthの関心事はユーザー認証(あなたは誰ですか?)ですが、専門家やCancanのような宝石は認可に対応しています(あなたが誰であるかを知っています。初心者向けのプログラミングを明確にするために。 –

+2

ありがとうございます。最新の完全かつ実用的なソリューションを見つけることは、実際には本当に難しいことです。 – ahnbizcad

+0

'users'のオムニオスコールバックのネストは何ですか、なぜそれが必要ですか? – ahnbizcad

2

あなたが1つのより多くのモデル必要な複数の認証プロバイダと工夫を使用するには、この

#config/initializers/devise.rb 
    #provider1 
    config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET'], 
    :site => 'https://graph.facebook.com/', 
    :authorize_path => '/oauth/authorize', 
    :access_token_path => '/oauth/access_token', 
    :scope => 'email, user_birthday, read_stream, read_friendlists, read_insights, read_mailbox, read_requests, xmpp_login, user_online_presence, friends_online_presence, ads_management, create_event, manage_friendlists, manage_notifications, publish_actions, publish_stream, rsvp_event, user_about_me, user_activities, user_birthday, user_checkins, user_education_history, user_events, user_groups, user_hometown, user_interests, user_likes, user_location, user_notes, user_photos, user_questions, user_relationships, user_relationship_details, user_religion_politics, user_status, user_subscriptions, user_videos, user_website, user_work_history' 

    #provider2 
    config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'], 
    :scope => { 
    :secure_image_url => 'true', 
    :image_size => 'original', 
    :authorize_params => { 
     :force_login => 'true' 
    } 
    } 

    #provider3 
    config.omniauth :google_oauth2, ENV["GOOGLE_KEY"], ENV["GOOGLE_SECRET"] 
+1

これは私がTwitterにユーザーを再ログインさせるように強制してくれませんでした。私は前回のブラウザで以前にログインしたときと同じアカウントを使用しています。ユーザーが複数のアカウントを自分のサイトアカウントにリンクできるようにしようとしています。 – Dex

+0

あなたが所有する認証コントローラを作成することができます。ユーザーとユーザーhas_many auths – MZaragoza

+0

答えが見つかりました。 ':scope =>'を取り出し、 'omniauth-twitter'という宝石を使ってうまく動作します。 'スコープ'はFacebookや他のサービスのためのものです。 – Dex

3

でいくつかの変更を行う必要があります。 https://github.com/AlexanderZaytsev/domp すばやく簡単に統合できます。私は約30mで作業セットアップをしていました。

+0

その宝石は私のために働いていませんでした。 – fenec

+0

これは私が持っていた問題です。 https://github.com/AlexanderZaytsev/domp/issues/16 – fenec

+0

私はこの宝石を使用しています。しかし、少し問題があります。私がgoto(localhost:3000/users/auth/facebook)を実行すると、経路の一致エラーは表示されません。 rakeコマンドでは、そこに定義されていることがわかります – zaingz

関連する問題