Petros Kyriakou
Petros Kyriakou

Reputation: 5343

How to counter multiple accounts from same user because of Auth Providers

I have implemented Auth providers (twitter, facebook, soundcloud) for an app(ruby on rails) but the constraint i have in place so that no new User accounts are created is based on email, but some providers do not provide email address.

Whats a good counter measure to avoid creating multiple accounts for same user?

user.model

class User < ActiveRecord::Base

  has_many :usertracks, :dependent => :destroy
    mount_uploader :image, ArtistPhotoUploader

  TEMP_EMAIL_PREFIX = 'change@me'
  TEMP_EMAIL_REGEX = /\Achange@me/

  # Include default devise modules. Others available are:
  # :lockable, :timeoutable
  devise :database_authenticatable, :registerable, :confirmable,
    :recoverable, :rememberable, :trackable, :validatable, :omniauthable

  validates_format_of :email, :without => TEMP_EMAIL_REGEX, on: :update

  validates_presence_of   :image
  validates_integrity_of  :image
  validates_processing_of :image

  def self.find_for_oauth(auth, signed_in_resource = nil)

    # Get the identity and user if they exist
    identity = Identity.find_for_oauth(auth)

    user = signed_in_resource ? signed_in_resource : identity.user

    # Create the user if needed
    if user.nil?

     UsersController.finish_signup
      email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
      email = auth.info.email if email_is_verified
      user = User.where(:email => email).first if email

      # Create the user if it's a new registration
      if user.nil?
        firstname = auth.info.name.split(' ')[0]
        surname = auth.info.name.split(' ')[1]
        user = User.new(
          firstname: firstname,
          surname: surname,
          #username: auth.info.nickname || auth.uid,
          email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
          password: Devise.friendly_token[0,20],
          remote_image_url: auth.info.image.gsub('http://','https://')
        )
       user.oauth_token = auth.credentials.token
       user.oauth_secret = auth.credentials.secret

        user.skip_confirmation!
        user.save!
      end
    end

    # Associate the identity with the user if needed
    if identity.user != user
      identity.user = user
      identity.save!
    end
    user
  end

  def email_verified?
    self.email && self.email !~ TEMP_EMAIL_REGEX
  end

end

Upvotes: 0

Views: 413

Answers (1)

trh
trh

Reputation: 7339

There really isn't a good way to keep someone from signing up again. You aren't a magician and can't predict how someone will sign up / sign in.

You are already doing the logical thing.

The best way to move forward is to allow someone to merge 2 accounts, and then allow them to link multiple providers.

The adding multiple providers part is easy. Just give a link inside a profile where they can click to authorize each available one.

Merging accounts can be trickier. Every place where user_id is stored (including polymorphic associations) needs to be updated to reflect the user_id that is kept. The other user should be deleted afterward.

Upvotes: 1

Related Questions