У меня было много проблем, пытаясь заставить логин на стороне клиента работать, поэтому я собираюсь освободиться от ссылки на массу других вопросов здесь ... нет привели к ответу, который сработал для меня.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 до сих пор не прошло. Как указано в:
- Этот SO ответ (OmniAuth Strategies Facebook NoAuthorizationCodeError (must pass either a `code` parameter or a signed request (via `signed_request` parameter):
- OmniAuth-facebook автора в окончательном комментарии этого вопроса Github (https://github.com/mkdynamic/omniauth-facebook/issues/110)
... Вы, возможно, придется вручную передать в 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]
Я голосую, чтобы закрыть этот вопрос как не по теме, потому что это эссе, в том числе несколько действительных ответов, а не вопрос. Пожалуйста, разделите ответы на реальные ответы. – Flimzy
Это единственное сообщение на SO, которое точно отражает все несоответствия использования клиентской стороны Omniauth с помощью SDK для Facebook. Я согласен, что формат не соответствует SO-совместимому, но спасибо за вклад. – Laurent