【发布时间】:2015-09-11 00:07:05
【问题描述】:
总结:
我遇到了 CORS 问题。我正在尝试从带有 Rails API 的 React 应用程序向 Facebook 进行身份验证。
我的应用在 localhost:8080 上运行,我的 api 在 Heroku 上运行。
我能够登录到 facebook 并在回调时创建会话,但 facebook 设置的 cookie 没有被omniauth 获取。我使用omniauth-facebook 客户端身份验证。
我认为问题出在我的 rack-cors 配置中。当我在 localhost:3000 上运行我的 api 时,它可以工作。
早些时候,我收到了错误csrf-detected,但通过添加解决了这个问题
provider_ignores_state: true 到omniauth 配置。后来发现cors调用传递cookie需要xhrFields: { withCredentials: true }。
最终解决方案:最后,我通过将我的应用程序部署到域为 example.com 的 AWS 53 并在 Heroku 上为我的 api 创建 CNAMES 'api.example.com' 来解决此问题。
解决 CNAMES 需要一天的时间。您可以使用命令 host example.com 和 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"
Application.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
【问题讨论】:
-
您的 API 控制器中可能需要
skip_before_action :verify_authenticity_token。 -
嗨,Tute,我在上面的问题中添加了我的 SessionsController 和 ApplicationController。我按照您的建议更改了我的 ApplicationController。但是,这并没有解决 CSRF 问题。
-
@Ravindra,很遗憾没有,我无法登录 facebook 和 google,但我收到了这条消息:请求中没有“Access-Control-Allow-Origin”标头资源。因此,不允许访问 Origin 'null'。
-
您能否同时发布 Facebook 登录请求以及对您的 API 的调用的请求和响应标头和正文?尽管您进行了配置,但错误似乎是在抱怨标头不存在,因此您应该确保它存在。
标签: ruby-on-rails heroku cors omniauth-facebook