2012-03-27 7 views
47

Мне нужно передать некоторые параметры для обратного вызова. Судя по исходному коду, OmniAuth должен добавить строку запроса для обратного вызова, но, как ни странно, это не так. Когда я открываюПередача параметров через OmniAuth

/auth/facebook?from=partner 

... и попадаю в Facebook, return_url просто

/auth/facebook/callback 

... без каких-либо параметров.

+2

http://stackoverflow.com/questions/7999907/passing-random-url-params-to-omniauth – Zabba

+37

Ваш «от» параметр может быть получен через окр [» omniauth.params "] –

+0

@David Оцените свой комментарий. Спасибо, я подтвердил, что ваш подход работал после обратного вызова! – GeorgeW

ответ

6

Что вы хотите сделать динамически установить функцию обратного вызова, чтобы включить имя партнера в URL (не параметры URL), на за одну транзакцию аутентификации основе, в зависимости от того, какой партнер был вовлечен. Это означает, что динамический адрес обратного вызова задается для каждого запроса на аутентификацию. См. this blog post to get started. URL-адрес обратного вызова автоматически отменяет параметры URL-адреса, как вы заметили, поэтому выполнение этого с параметрами не будет работать.

Так что, если вместо того, чтобы пытаться передать имя партнера/идентификатор в качестве параметра (который падает), вы структурированы ваши маршруты так, чтобы partner_id и OmniAuth provider были частью обратного вызова URL, то вы бы что-то вроде:

/auth/:omniauth_provider/callback/:partner_id 

... где действительный обратный вызов будет что-то вроде

/auth/facebook/callback/123456 

... то вы бы знали, что данный обратный вызов пришел из Facebook, с партнером ID 123456

+0

Хороший ответ, Нормальность. Я пытался понять это сам. Я не совсем уверен, как делать то, что вы прописали выше, и сообщение в блоге тоже не проливает свет. Вы могли бы опубликовать код? В частности, как будет генерировать этот маршрут, описанный выше, и как создать соответствующие действия контроллера для обработки различных обратных вызовов? Я специально хочу, чтобы обратный вызов обеспечивал контекст того, где пользователь ушел, таким образом я могу вернуть пользователя туда, где они были после завершения OAuth. – John

+0

URL-адрес, в котором пользователь «покинул», может быть сохранен в файле cookie, поскольку он перенаправляется на портал oauth, когда когда возвращается обратный вызов, cookie может быть просмотрен, извлеченное значение и файл cookie истек/удален , Что касается других вещей, я думаю, для меня может быть хорошей идеей бросить быстрое демо-приложение и опубликовать его как доказательство концепции, а затем я могу поделиться кодом на github. Затем, предполагая, что это работает, я могу отправить код обратно в ответ. Дайте мне несколько часов, чтобы взломать его. – jefflunt

+1

потратил 3 дня, пытаясь найти этот ответ. thankyou – MilesStanfield

1

Вы знаете, я думаю, что, возможно, я попытаюсь решить этот трудный путь.

Куки могут быть ответом. Я думаю, вы можете решить эту проблему, указав, что ваш файл входа в систему хранит куки-файл, а затем перенаправляется на правильный путь для проверки подлинности , и когда срабатывает обратный вызов (в SessionsController#create), вы просто читаете файл cookie, чтобы узнать, где его перенаправить ,

Итак, прямо сейчас ваша ссылка «login with facebook» (или все, что у вас есть в вашем приложении), вероятно, относится к /auth/facebook. Вместо этого, если вы создали пользовательское действие, как

POST /partner_auth 

... и назвал его с URL ...

POST example.com/partner_auth?from=partner&provider=facebook 

Тогда вы можете иметь контроллер, как:

class PartnerAuth < ApplicationController 
    def create 
    cookies[:from] = params[:from] # creates a cookie storing the "from" value 
    redirect_to "auth/#{params[:provider]" 
    end 
end 

Тогда в действии SessionsController#create, вы бы ...

def create 
    ... 

    destination = cookies[:from] 
    cookies[:from].delete 

    redirect_to destination # or whatever the appropriate thing is for your 
          # app to do with the "from" information 
end 

Я попытался создать демонстрационное приложение, чтобы выполнить то, что я описал в другом ответе, но вы правы - было слишком сложно попытаться динамически вставить специальный обратный вызов в код OmniAuth. Существует опция конфигурации, чтобы переопределить обратный вызов по умолчанию, но, как представляется, его легко установить динамически.

Итак, мне стало ясно, что файлы cookie будут проще, специфичны для пользователя, и поскольку вам теоретически нужно хранить эту информацию from в течение очень короткого времени (между тем, когда пользователь пытается аутентифицироваться, и когда обратный вызов запускается), нет ничего сложного в создании файла cookie, а затем удалите его, когда будет вызван обратный вызов.

21

Я думаю печенье вещь работает, но почему все, что, когда вы можете использовать переменные состояния как описано здесь: https://github.com/mkdynamic/omniauth-facebook

Это, как я использовал его:

при создании URL, вы можете просто добавить состояние в строке запроса, и оно будет доступно также в URL-адресе обратного вызова.

user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %> 

теперь обратный вызов URL будет

http://localhost:3000/users/auth/facebook/callback?state=123&code=ReallyLongCode#_=_ 

Теперь в обработчике обратного вызова вы можете обрабатывать государству

-2

Используйте переменную «состояние». Facebook позволяет пользователю устанавливать переменную STATE.

Вот как я это сделал, я приложил к AUTH URL с? STATE = ProviderName

http://localhost/users/auth/facebook?state=providername 

Этих пары возвращаются ко мне на обратном вызове, как Params [ 'ProviderName']

Я придумал решение от первоначального OmniAuth Пути Метод

user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %> 
70

После борьбы со всеми вышеперечисленными ответы, я понял, что делать в отношении Facebook, который по умолчанию не отображает параметры в request.env["omniauth.auth"].

Итак - Если вы используете строку запроса для обратного вызова, похожие на что-то вроде этого:

"/auth/facebook?website_id=#{@website.id}" 

Единственный способ получить, что website_id параметров является использование request.env["omniauth.params"]. ПРИМЕЧАНИЕ: УБЕДИТЕСЬ, ЧТО ВЫ ИСПОЛЬЗУЕТЕ omniauth.params, а не omniauth.auth - этот один отключил меня на некоторое время.

Затем, чтобы проверить это, вы можете проверить его в своем действии контроллера (обратите внимание на RAISE линию ...):

def create 
    raise request.env["omniauth.params"].to_yaml 
    # the rest of your create action code... 
end 

Вы должны увидеть параметр там. Отлично. Теперь вернитесь к контроллеру и удалите эту линию RAISE. Затем, вы можете получить доступ к следующим параметрам в своем действии контроллера:

params = request.env["omniauth.params"] 
website_id = params["website_id"] 

Примечания: в Params [ «website_id»] вы должны использовать кавычки, а не символ.

+0

Я получил выход в omniauth.auth но ноль в omniauth.params. Что не так? Я уже передаю параметр в URL. "/ auth/facebook/state = 123" – harsh4u

+1

@ harsh4u, вероятно, потому, что у вашего URL-адреса отсутствует '?' перед параметрами. Это должно быть «auth/facebook /? State = 123» –

+1

Спасибо за это! Я пытался захватить параметр состояния, чтобы достичь этого, прежде чем читать ответ. Благодаря! – septerr

8

Вы можете использовать :params варианты, как в

omniauth_authorize_path(:user, :facebook, var: 'value', var2: 'value2') 

, а затем в обратном вызове вы можете получить доступ к request.env['omniauth.params'], чтобы получить хэш! :)

(копируется из this answer)

+1

Живая заставка, длительная на самом дне :) – Aleks

Смежные вопросы