Проблема CORS с файлом cookie Facebook JS SDK и omniauth-facebook

Я реализую Sign In с Facebook в своем проекте, который состоит из двух приложений:

  • Внешний интерфейс: обычный HTML+CSS+JS;
  • Бэкенд: Rails 5 API (omniauth 1.3.1, omniauth-facebook 3.0.0);

Даже в моей локальной среде оба приложения работают в разных доменах (frontend.dev.azk.io и api.dev.azk.io).

Я запускаю FB SDK в своем внешнем приложении, и после успешного входа в систему я должен пропинговать обратный вызов OAuth (http://api.dev.azk.io/api/v1/users/auth/facebook/callback), чтобы omniauth-facebook мог получить доступ к файлу cookie fbsr_XXX, проанализировать его и обменять текущий accessToken на долгосрочный.

Основная проблема в том, что кука, установленная FB SDK, принадлежит фронтенд-домену и не отправляется в заголовке запроса к API, т.е. omniauth-facebook не может получить к нему доступ:

ERROR -- omniauth: (facebook) Authentication failure! no_authorization_code: OmniAuth::Strategies::Facebook::NoAuthorizationCodeError, must pass either a `code` (via URL or by an `fbsr_XXX` signed request cookie)

В этот момент я подумал о двух возможных подходах:

1) Проверить конфиги CORS и AJAX, чтобы куки можно было отправлять в запросе к API;

2) Проанализируйте Ответ FB во внешнем интерфейсе (используя этот алгоритм) и отправьте атрибут code к API;

Подход 1

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

routes.rb

devise_for :users, path_prefix: 'api/v1', controllers: {
  sessions:           'api/v1/sessions',
  registrations:      'api/v1/registrations',
  omniauth_callbacks: 'api/v1/omniauth_callbacks',
}

application.rb

config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'frontend.dev.azk.io'
    resource '*',
      headers: :any,
      credentials: true,
      methods: [:get, :put, :post, :patch, :delete, :options]
  end
end

devise.rb

config.omniauth :facebook, oauth_providers['facebook']['app_id'], oauth_providers['facebook']['secret'], {
  scope: 'email,user_birthday,user_about_me,public_profile',
  provider_ignores_state: true
}

Клиентское приложение

$.ajax({
  type: 'GET',
  url: 'http://api.dev.azk.io/api/v1/users/auth/facebook/callback',
  crossDomain: true,
  xhrFields: { withCredentials: true },
}) . . .

Однако этого недостаточно для отправки файла cookie fbsr_XXX (присутствует в браузере). Есть ли что-то, что я упускаю?

Подход 2

Поскольку omniauth-facebook не может получить доступ к вышеупомянутому файлу cookie, я решил проанализировать значение signedRequest, возвращаемое FB, и отправить code атрибут для API.

Однако кажется, что omniauth-facebook генерирует callback_url, который не соответствует тому, который использовался в предыдущем запросе:

ERROR -- omniauth: (facebook) Authentication failure! invalid_credentials: OAuth2::Error, : 
{"error":{"message":"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request","type":"OAuthException","code":100,"fbtrace_id":"BavpcDFblHy"}}

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


person Felipe Arenales    schedule 29.04.2016    source источник
comment
в моем случае, используя серверную часть внешнего интерфейса и API, я больше не использую файлы cookie, потому что API должны быть без гражданства, я использую JsonWebTokens (JWT). Когда вы вызываете логин FB SDK из интерфейса, вы должны получить токен на интерфейсе и сохранить его в локальном хранилище браузера. затем в любой транзакции с API вы должны отправить токен, вы не должны хранить токен в API, чтобы он не сохранял состояние   -  person Cristian Sepulveda    schedule 23.12.2016