Devise / Omniauth - Как иметь дело с провайдером, который не включает электронную почту - PullRequest
1 голос
/ 20 февраля 2012

У меня есть приложение Rails, которое использует Devise и Omniauth для обработки аутентификаций.Как предписано, я получаю обратные вызовы от провайдеров в моем omniauth_callbacks_controller, где я проверяю, существует ли аутентификация, и существует ли уже пользователь с электронной почтой, предоставленной провайдером, создавая нового пользователя при необходимости.

Мне нужен действующий адрес электронной почты для каждого пользователя.Моя проблема связана с обратными вызовами из Twitter.Твиттер не предоставляет электронную почту для своих пользователей, поэтому я не могу создать действительного пользователя.Чтобы решить эту проблему, я сохраняю данные провайдера в сеансе и отправляю пользователю новую страницу регистрации, прося его предоставить свой адрес электронной почты, чтобы я мог создать действительного пользователя.Когда эта форма отправлена, я столкнулся с проблемой.Форма создала нового пользователя, но вполне возможно, что пользователь с таким адресом электронной почты уже существует (в этом случае мне необходимо добавить аутентификацию для этого пользователя).

В данный момент я проверяюпосмотреть, существует ли уже пользователь с таким же адресом электронной почты, что и новыйЕсли это так, я игнорирую нового пользователя и применяю аутентификацию к пользователю, который уже существует.Тем не менее, это кажется действительно хакерским.

Как мне это сделать?

class Users::RegistrationsController < Devise::RegistrationsController

def build_resource(*args)
    super
    if session[:omniauth]
      #If a user with this email already exists then use them instead
      existing_user = User.find_by_email(@user.email)
      if(existing_user)
          existing_user.email = @user.email
          @user = existing_user
      end
      #If there is a session available, we know it contains data for adding an authentication
      @user.apply_omniauth_data_as_authentication(session[:omniauth])
      #Ensure validations are passed on to next page
      @user.valid?
    end
  end

Ответы [ 2 ]

1 голос
/ 29 апреля 2012

Вот, пожалуйста.Я постараюсь вспомнить, откуда я получил исправление, и выложу ссылку, если я сделаю:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  # This controller handles callbacks from Omniauth providers. If a user already exists with this provider we sign them in.
  # Otherwise we either add an authentication to the current user, or create a new user if one doesn't exist.

  def facebook
    authorize
  end

  def twitter
    authorize
  end

  private

    def authorize
      omniauth_data = request.env["omniauth.auth"]
      #Check to see if we have an authentication for this provider already stored for any User
      authentication = Authentication.find_by_provider_and_uid(omniauth_data['provider'], omniauth_data['uid'])
      #If an authentication already exists, sign the owning User in
      if authentication
        flash[:notice] = "Signed in successfully with " +  omniauth_data['provider'].titleize
        sign_in_and_redirect(:user, authentication.user)
      #Otherwise if there is a current User, add a new authentication for them
      elsif current_user
        current_user.authentications.create(:provider => omniauth_data['provider'], :uid => omniauth_data['uid'], :token => omniauth_data['token'])
        flash[:notice] = "Authentication successful"
        redirect_to user_profile_url
      #Otherwise we check if a user exists with the email address provided by the provider (if provided at all))
      else
        email = omniauth_data['info']['email']
        user = User.find_by_email(email)
        #If no user exists, create a new one
        if(!email || !user)
            user = User.new
        end
        user.apply_omniauth_data_as_authentication(omniauth_data)
        #If they save successfully (meaning we have enough data from the authorisation) sign them in
        if user.email?
          #We got all we needed from the provider so we don't need them to confirm'
          user.skip_confirmation!
          user.save!
          flash[:notice] = "Signed in successfully with " +  omniauth_data['provider']
          sign_in_and_redirect(:user, user)
        #Otherwise we need to have the visitor manually submit missing information
        else
          #save the omniauth data in a session so we can add the authentication once registration is complete
          flash[:alert] = "Please complete registration"
          session[:omniauth] = omniauth_data.except('extra')
          redirect_to new_user_registration_url
        end
      end
    end

end
0 голосов
/ 02 октября 2014

Мне нравится решение, используемое по этой ссылке http://www.orhancanceylan.com/rails-twitter-and-facebook-authentications-with-omniauth-and-devise/

Он использует учетные данные провайдера для регистрации в обычном процессе разработки (а также для заполнения атрибутов провайдера и uid у пользователя или в отдельной таблице). Таким образом, когда новый пользователь пытается зарегистрироваться с помощью провайдера, он должен будет ввести адрес электронной почты и пароль, создавая меньше головной боли в будущем (например, желая войти в систему обычным способом, но не имея пароля для ввода, и тогда тебе придется с этим справиться).

Хотя это решение несколько отрицает удобство регистрации в социальных сетях в первый раз, оно создает долгосрочные положительные эффекты при минимальных усилиях.

Если вы абсолютно не хотите такого рода требования из-за страха потерять регистрацию или из-за того, что ваш веб-сайт выглядит менее отточенным, найдите другое решение и сделайте всю работу для обработки этих последующих случаев.

...