Rails & Oauth: several vendors

I have an application that allows users to post on LinkedIn, Facebook and Twitter. I would like to authorize each user account to as many of these providers as possible, as the user would like.

There are several columns in my user model that will help authorize one provider at a time:

class User < ActiveRecord::Base
  ...
  attr_accessible :provider, :uid, :oauth_token, :oauth_expires_at, :oauth_token_secret, :access_token, :access_token_secret ...
  ...
end

Here's the model method:

def self.from_omniauth(user, auth)
  user.provider = auth.provider
  if auth.provider == "facebook"
    user.uid = auth.uid
    user.oauth_token = auth.credentials.token
    user.oauth_expires_at = Time.at(auth.credentials.expires_at)
  elsif auth.provider == "twitter"
    # not sure which one twitter uses
    user.oauth_token = auth["credentials"]["token"]
    user.oauth_token_secret = auth["credentials"]["secret"]
    user.access_token = auth["credentials"]["token"]
    user.access_token_secret = auth["credentials"]["secret"]
  end
  user.save!
end

And the controller auth method is as follows:

def authorise
  user = User.from_omniauth(current_user, env['omniauth.auth'])
  session[:user_id] = current_user.id
  redirect_to root_url
end

Any help would be great! Really not sure how to proceed from here. If x (3 in the above case, is yet to come), the number of columns :providerseems ridiculous.

+4
1

, , has_many . Identity ( omniauth):

class Identity < ActiveRecord::Base
  belongs_to :user

  attr_accessible :provider, :uid,
                  :description, :email, :first_name, :image,
                  :last_name, :location, :name, :nickname,
                  :phone, :raw_info, :urls

  validates_presence_of :provider, :uid
  validates_uniqueness_of :uid, scope: :provider

  def self.find_with_omniauth(auth)
    find_by_provider_and_uid(auth['provider'], auth['uid'])
  end

  def self.create_with_omniauth(auth)
    create(provider:      auth['provider'],
            uid:          auth['uid'],
            name:         auth['info']['name'],
            email:        auth['info']['email'],
            nickname:     auth['info']['nickname'],
            first_name:   auth['info']['first_name'],
            last_name:    auth['info']['last_name'],
            location:     auth['info']['location'],
            description:  auth['info']['description'],
            image:        auth['info']['image'],
            phone:        auth['info']['phone'],
            urls:         auth['info']['urls'].to_json,
            raw_info:     auth['extra']['raw_info'].to_json
          )
  end
end

, , User :

class User < ActiveRecord::Base
  ...
  has_many :identities, dependent: :destroy
  ...

, omniauth . , (), - :

class SessionsController < ApplicationController

  def create
    auth = request.env['omniauth.auth']
    origin = request.env['omniauth.origin']
    destination = origin.blank? ? root_path : origin
    @identity = Identity.find_with_omniauth(auth)
    @identity = Identity.create_with_omniauth(auth) if @identity.nil?

    if signed_in?
      if @identity.user == current_user
        # Identity is already associated with this user
        redirect_to destination, notice: "Already logged in and linked"
      else
        # Identity is not associated with the current_user
        @old_user = @identity.user
        if @old_user
          current_user.posts << @old_user.posts
          current_user.galleries << @old_user.galleries
          current_user.favorites << @old_user.favorites
        end
        @identity.user = current_user
        @identity.save()
        @old_user.destroy if @old_user && @old_user.identities.blank?
        redirect_to destination, notice: "Account was successfully linked"
      end
    else
      if @identity.user.present?
        # Identity has a user associated with it
        self.current_user = @identity.user
        redirect_to destination
      else
        # No user associated with the identity so create a new one
        user = User.create_with_omniauth(auth['info'])
        @identity.user = user
        @identity.save()
        self.current_user = @identity.user
        redirect_to destination, notice: "Registration successful"
      end
    end
  end

  def destroy
    self.current_user = nil
    redirect_to root_url, notice: "Signed out successfully"
  end

  def omniauth_failure
    origin = request.env['omniauth.origin']
    destination = origin.blank? ? root_path : origin
    redirect_to destination, alert: "Connection failed"
  end
end

, , , . . https://github.com/intridea/omniauth/wiki/Managing-Multiple-Providers .

+5

All Articles