2

I installed SSO for Discourse following the official implementation instructions (here) and this answer on Stackoverflow (here). However, it's not working. The SSO payload is dropped between the Get users/sign_in and Post users/sign_in actions.

Here's the Heroku log:

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

Here is the Discourse SSO Controller per the official instructions (above):

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

I customized the Devise views and installed the Devise sessions controller with scope users (class Users::SessionsController < Devise::SessionsController).

Looking at the Devise Sessions Controller source code on Github, the Get / New and Post / Create methods are:

GET /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

POST /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

The first line of the Create method references the last line of the New method via auth_options (which is protected):

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

The last line of the New method (I believe) creates the params that are posted. They're the serialize_options(resource), another protected method:

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

The SSO payload isn't being passed as a serialize_options.

Here's what appears to be a similar issue devise and oauth OmniAuth Single Sign On with Devise, invalid_credentials resolved by scraping the token.

Any guidance or thoughts are appreciated. Thanks.

Community
  • 1
  • 1
user3763682
  • 391
  • 1
  • 5
  • 17
  • Did you ever resolve this? – D-Nice Apr 18 '21 at 21:17
  • @D-Nice I frankly don't recall. My vague recollection is that a Discourse employee resolved it for me. They are - or were five years ago - very helpful. – user3763682 Apr 21 '21 at 15:50
  • 1
    Fwiw, I was able to resolve the issue I was having. My problem was that I had set the discourse connect URL to my domain endpoint without a www, but my webserver was redirecting to www and dropping the query parameters. Adding the www to my Discourse connect URL fixed it for me. – D-Nice Apr 21 '21 at 18:48

0 Answers0