5

У меня было много проблем, пытаясь заставить логин на стороне клиента работать, поэтому я собираюсь освободиться от ссылки на массу других вопросов здесь ... нет привели к ответу, который сработал для меня.Facebook NoAuthorizationError после прохождения signed_parameters вручную

КОНТЕКСТ

  • Серверный Войти работает отлично
  • Клиентский вход с помощью JS SDK отлично работает на Safari * (не тестировал в Firefox или IE или мобильный без Chrome), но не в Chrome, что и этот вопрос о (и большинство моих пользователей используют Chrome, так что это очень важно)
  • Gem версии:
    • рубинового (2.1.2)
    • рельсы (4.1.1)
    • OAuth (0.4.7)
    • oauth2 (1.0.0)
    • OmniAuth (1.2.2)
    • OmniAuth-facebook (2.0.0)
    • OmniAuth-oauth2 (1.2.0)
  • Это для приложения в режиме разработки, где, как разработчик, я определенно уполномочен войти

* По отлично работает, я имею в виду, если вы просто скопировали код из Райан Бейтса RailsCast (http://railscasts.com/episodes/360-facebook-authentication?view=asciicast) работает без какого-либо дополнительного ничего


TL: DR; Я передаю следующий URL-адрес, который должен работать ...

`http://localhost:3000/auth/facebook/callback?signed_request=ASDF.JOUYOUY` 
// Obviously signed_request is a much longer string 

... но я все еще получаю ошибкуOmniAuth::Strategies::Facebook::NoAuthorizationCodeError (must pass either a код parameter or a signed request (via signed_request parameter or a fbsr_XXX cookie)):


НЕИСПРАВНОСТЕЙ К НАСТОЯЩЕМУ + ОБЗОР МНОГИХ ДРУГИХ ОШИБКОВ/ПОТЕНЦИАЛЬНЫХ РЕШЕНИЙ

Кодовые решения ниже сборки на код из RailsCast Райан Бейтса:

$('#sign_in').click (e) -> 
    e.preventDefault() 
    FB.login (response) -> 
    window.location = '/auth/facebook/callback' if response.authResponse 

Препятствие # 1: блокированы 3-печенье партии?

Не обязательно приводит к ошибке, просто делает это так, что вы не можете подключить приложение к Facebook.

Подключив ваше приложение к Facebook, сначала необходимо войти в систему с Facebook, потому что код FB.login (response) -> window.location = "/auth/facebook/callback" if response.authResponse зависит от действительности authResponse и его содержащегося параметра signedRequest.

Если печенье заблокировано (т., Настройки Chrome> Расширенные настройки> Конфиденциальность> Настройки содержимого> Заблокировать сторонние файлы cookie проверено), вы никогда не получите объект authResponse. Это комбинация вопросов/ответов здесь: FB.getLoginStatus always returns status='unknown'. Другими словами, если вы делаете FB.getLoginStatus, независимо от того, сколько раз вы нажимаете кнопку «Логин», статус всегда возвращается обратно как unknown для документов: https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus.

кода Решение до сих пор ...: Если FB.login возвращает ответ unknown отбракованных обратно на стороне сервера входа в систему.

$('#sign_in').click (e) -> 
    e.preventDefault() 
    FB.login (response) -> 
    if response.status is "unknown" 
     window.location = "/auth/facebook" 
    else 
     window.location = "/auth/facebook/callback" 

Препятствие # 2: передаются соответствующим образом параметры?

Если у вас есть третья сторона печенье разблокирован, вы можете потом столкнуться с ошибкой:

OmniAuth::Strategies::Facebook::NoAuthorizationCodeError (must pass either a `code` parameter or a signed request (via `signed_request` parameter or a `fbsr_XXX` cookie)): 

Несмотря на установление cookie: true в FB.init, иногда PARAMS до сих пор не прошло. Как указано в:

... Вы, возможно, придется вручную передать в signed_request. Быстрое наблюдение. В документах на Facebook (https://developers.facebook.com/docs/facebook-login/using-login-with-games) у signedRequest должно быть два компонента, разделенных .. Не знаете, как, но я получил один без .. Разделение важно, потому что это последнее половина это base64url закодированный объект JSON, содержащий информацию о code.

кода Решение до сих пор ...: Вручную добавьте signed_request параметр не обратный вызов URL-адрес

$('#sign_in').click (e) -> 
    e.preventDefault() 
    FB.login (response) -> 
    if response.status is "unknown" 
     window.location = "/auth/facebook" 
    else 
     window.location = ("/auth/facebook/callback?signed_request=" + response.authResponse.signedRequest) 

Препятствие # 3: до сих пор ничего ... все еще такая же ошибка, как # 2

Может быть только я в этот момент?

кода Решение до сих пор ...: Go супер педантичный, разобрать на code из signedRequest и добавить к URL-адресу обратного вызова

$('#sign_in').click (e) -> 
    e.preventDefault() 
    FB.login (response) -> 
    if response.status is "unknown" 
     window.location = "/auth/facebook" 
    else 
     parsed_signed_Request = response.authResponse.signedRequest.split(".") 
     key_info = base64_decode(parsed_signed_Request[1]) 
     // decoded via http://www.simplycalc.com/base64-source.php 
     key_info_object = jQuery.parseJSON(key_info) 
     window.location = ("/auth/facebook/callback?code=" + key_info_object["code"]) 

Препятствие # 4: CSRF обнаружен, но не для того, почему ты 'd think

Теперь я переехал прямо в кирпичную стену. Когда я запускаю код, как указано выше, я получаю сообщение об ошибке CSRF. По этой причине вы можете получить эту ошибку:

  • Вы можете получить эту ошибку, если ваше приложение Facebook находится в режиме Dev, и вы пытаетесь войти в систему. В этом случае FB не разрешает входам не включенных в систему разработчиков.См первого ответа на этот вопрос: Rails + omniauth + facebook - csrf detected

Но проблема в моем случае не была выше, это было то, что параметр code был представлен без параметра state. Теперь были ответы, в которых говорилось, что вы можете исправить это, установив provider_ignores_state: true в файле конфигурации omniauth.rb, см. Второй ответ на вопрос, упомянутый выше, но это не исправление для меня. Зачем? Потому что 1) мне не нравятся поворот, специально предназначенный для противодействия CSRF, и 2) он появляется, когда настройки запускаются только для входа на сервер. Добавление его просто ничего не делало для меня.

Что означает большую проблему решения # 3 было то, что он пытался объединить на стороне сервера входа подход (принимает code и state Params) с клиентской стороны входа подхода (требуется signed_request параметров).

Это означает, что я вернусь к исходному вопросу ... как пройти signed_request, чтобы клиентский логин работал?


Поскольку я уже слишком много болтал об этом, позвольте мне указать на еще одну ошибку, которую я видел. У этого есть ответы, связанные с ошибками Facebook (Dealing with Oauth 2.0-facebook gem error 100: This authorization code has been used), но помимо этого я нашел что-то еще, что могло бы вызвать его.

Как и предлагалось в этом учебном пособии (https://coderwall.com/p/bsfitw), вы match маршрут обратного вызова через оба get и post. Но когда я это делаю, мой logger показывает два запроса на Facebook, второй, очевидно, заблокирован и вызывает ошибку. (Также означает, что первый запрос прошел, и пользователь уже авторизовался/данные сохранены, что угодно). Моим решением было установить маршрут следующим образом:

match 'auth/:provider/callback', to: 'signups#create_facebook', via: [:get] 
+1

Я голосую, чтобы закрыть этот вопрос как не по теме, потому что это эссе, в том числе несколько действительных ответов, а не вопрос. Пожалуйста, разделите ответы на реальные ответы. – Flimzy

+1

Это единственное сообщение на SO, которое точно отражает все несоответствия использования клиентской стороны Omniauth с помощью SDK для Facebook. Я согласен, что формат не соответствует SO-совместимому, но спасибо за вклад. – Laurent

ответ

0

Для тех, кто все еще испытывает эту проблему. Старайтесь не использовать «localhost: 3000» или что-то еще. Изменить/и т.д./хосты на новый адрес, как

127.0.0.1 abc.com 

Изменение facebook установки приложения на developers.facebook.com, чтобы указать на новый адрес (вместо использования Localhost: 3000, назовем его abc.com:3000)

и повторите попытку входа в систему с помощью js facebook login снова. Должен работать нормально!

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