3

概要:

CORSに問題があります。Rails API を使用して React アプリから Facebook で認証しようとしています。

アプリは localhost:8080 で実行され、API は Heroku で実行されます。

Facebook にログインしてコールバックでセッションを作成することはできますが、Facebook によって設定された Cookie が omniauth によって取得されません。omn​​iauth-facebook クライアント側認証を使用しています。

私のラックコアの構成のどこかに問題があると思います。localhost:3000 で API を実行すると機能します。

以前、エラーを受け取りましたが、これはomniauth 構成csrf-detectedに追加することで解決されました 。後で、 cors 呼び出しが Cookie を渡すために必要でprovider_ignores_state: trueあることがわかりました。xhrFields: { withCredentials: true }

最終的な解決策: 最後に、アプリケーションを AWS 53 にドメインと共にデプロイexample.comし、Heroku の API に CNAMES 'api.example.com` を作成して、この問題を解決します。

CNAMES の解決には 1 日かかります。example.comコマンド hostおよび hostを使用して、ターミナルでセットアップをテストできますapi.example.com

別の解決策は、nginx をプロキシとして使用することです。

バージョン:

Rails 4.2.2
Omniauth-facebook 3.0.0
Omniauth-oauth2 1.4.0
Rack-cors 0.4.0

問題:

Getting error: no_authorization_code.

ルート:

  namespace :api do
    match "/auth/:provider/callback", to: "sessions#create", via: [:get, :post]
    get "/auth/failure", to: "sessions#failure"
    get "/logout", to: "sessions#destroy"

アプリケーション.rb:

config.middleware.insert_before 0, "Rack::Cors" do
  allow do
    origins "localhost:8000", "example.com"
    resource "*",
      :headers => :any,
      :methods => [:get, :post, :delete, :put, :options],
      :max_age => 1728000
  end
end

Omniauth.rb:

OmniAuth.config.path_prefix = "/api/auth"

OmniAuth.config.logger = Rails.logger

OmniAuth.config.on_failure = Proc.new { |env|
  OmniAuth::FailureEndpoint.new(env).redirect_to_failure
}

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook,
    Rails.application.secrets.facebook_key,
    Rails.application.secrets.facebook_secret, {
      provider_ignores_state: true,
      client_options: {
        :ssl => { :ca_file => "/usr/lib/ssl/certs/ca-certificates.crt" }
      }
    }
  provider :identity,
    fields: [:email],
    on_failed_registration: lambda { |env|
      Api::IdentitiesController.action(:new).call(env)
    }
end

Secret.yml:

development:
facebook_key: <%= ENV["FACEBOOK_KEY"] %>
facebook_secret: <%= ENV["FACEBOOK_SECRET"] %>

クライアント:

$.ajax({
  url: http://localhost:3000/api/auth/facebook,
  dataType: "json",
  type: "GET",
  xhrFields: { withCredentials: true },
  success: function(data) {
  }.bind(this),
  error: function(xhr, status, err) {
  }.bind(this)
})

セッションコントローラー:

module Api
  class SessionsController < ApplicationController
    skip_before_action :verify_authenticity_token
    skip_before_action :restrict_access
    skip_after_action :verify_authorized

def create
  user = User.from_omniauth(auth_params)
  session[:user_id] = user.id
  render json: user, status: :ok
end

def destroy
  session[:user_id] = nil
  render json: {}, status: :ok
end

def failure
  render json: { errors: params[:message] }, status: :unauthorized
end

private

def auth_params
  request.env.fetch("omniauth.auth")
end end end

アプリケーションコントローラー:

class ApplicationController < ActionController::Base
  include Pundit
  before_action :restrict_access
  after_action :verify_authorized, :except => :index
  after_action :verify_policy_scoped, :only => :index

    respond_to :json

    protected

    attr_reader :current_user

    # Allows access to current_user in serializators.
    serialization_scope :current_user

    def restrict_access
      authenticate_or_request_with_http_token do |token, options|
      @current_user = User.find_by(token: token)
    end
  end
end
4

3 に答える 3

2

xhrFields: { withCredentials: true } Cookie を omniauth に渡すには、Ajax 呼び出しに含める必要があることがわかりました 。

これは、クロスドメイン コールであるためです。

詳細については、 http://api.jquery.com/jquery.ajax/を参照してください。

于 2015-11-30T17:47:39.217 に答える
0

RailsアプリでDeviseを使用してomniauthを実行しているときに、この同じ問題に遭遇していました。最終的に、私にとっての問題は、Facebook が 7 月の初めに API を更新したことでした。現在、info_fieldsparam のフィールドを具体的に要求する必要があります。

omniauth.rb以下を含めるように変更してみます。

provider :facebook,
 Rails.application.secrets.facebook_key,
 Rails.application.secrets.facebook_secret, {
   :scope => "email, user_birthday",
   :info_fields => "email, user_birthday", #<== this made the difference for me
   provider_ignores_state: true
 }

これは、問題に言及しているdevise wikiからのリンクです。あなたがdeviseを使用していないことは知っていますが、役立つかもしれません。https://github.com/plataformatec/devise/wiki/OmniAuth:-概要

于 2015-09-14T16:32:03.763 に答える