2

我按照官方实施说明(此处)和 Stackoverflow 上的答案(此处)为 Discourse 安装了 SSO 。但是,它不起作用。SSO 有效负载被丢弃在 Get users/sign_in 和 Post users/sign_in 操作之间。

这是 Heroku 日志:

Started GET "/users/sign_in?sso=PAYLOAD & SIG [GET]
Processing by Users::SessionsController#new as HTML [NEW ACTION]
Parameters: {"sso"=> etc. [SSO PAYLOAD PRESENT]
- rendering html -
heroku[router]: at=info method=GET path="/users/sign_in?sso= [PAYLOAD PRESENT]
Processing by Users::SessionsController#create as HTML [CREATE ACTION]
Parameters: {"utf8"=>"✓", "authenticity_token"=> etc [NO SSO PAYLOAD,
  Google Recaptcha added]
Started GET "/"
Started POST "/users/sign_in"
Processing by StaticPagesController#home as HTML
- rendering html -
heroku[router]: at=info method=POST path="/users/sign_in"  host=our_site.com

这是按照官方说明(上图)的 Discourse SSO 控制器:

class DiscourseSsoController < ApplicationController

  def sso
    secret = "SECRET STRING"
    sso = SingleSignOn.parse(request.query_string, secret)
    sso.email = current_user.email # from devise
    sso.name = current_user.name # this is a custom method on the User class
    sso.username = current_user.email # from devise
    sso.external_id = current_user.id # from devise
    sso.sso_secret = secret

    redirect_to sso.to_url("http://DISCOURSE_sub-domain_of.OUR_SITE.com/
      session/sso_login")
  end

end

我自定义了 Devise 视图并使用范围用户(类 Users::SessionsController < Devise::SessionsController)安装了 Devise 会话控制器。

查看 Github 上的 Devise Sessions Controller源代码,Get / New 和 Post / Create 方法是:

获取 /resource/sign_in

def new
  self.resource = resource_class.new(sign_in_params)
  clean_up_passwords(resource)
  yield resource if block_given?
  respond_with(resource, serialize_options(resource))
end

发布 /resource/sign_in

def create
  self.resource = warden.authenticate!(auth_options)
  set_flash_message(:notice, :signed_in) if is_flashing_format?
  sign_in(resource_name, resource)
  yield resource if block_given?
  respond_with resource, location: after_sign_in_path_for(resource)
end

Create 方法的第一行通过auth_options(即protected)引用了 New 方法的最后一行:

def auth_options
  { scope: resource_name, recall: "#{controller_path}#new" }
end

New 方法的最后一行(我相信)创建了发布的参数。它们是serialize_options(resource)另一种protected方法:

def serialize_options(resource)
  methods = resource_class.authentication_keys.dup
  methods = methods.keys if methods.is_a?(Hash)
  methods << :password if resource.respond_to?(:password)
    { methods: methods, only: [:password] }
end

SSO 有效负载未作为serialize_options.

这似乎是一个类似的问题 devise 和 oauth OmniAuth Single Sign On with Devise,invalid_credentials通过抓取令牌解决。

任何指导或想法表示赞赏。谢谢。

4

0 回答 0