Cookie Based Authentication in discourse via Plugin

Hi All,

I am trying to use cookie-based authentication in discourse (session is being controlled by parent domain). Here, I am making an API call to the parent website backend to find the user from the session cookie. The issue here is that when a user gets changed, then on the client side, a user has to refresh the page 5-10 requests in order to the user being shown logined (i.e. the user avatar is shown and other user login related features like option of logout are shown). I am not able to understand the reason behind the delay. In the logs, the current user returns the desired user from the first call itself, but it’s not propagated for some time. I am not able to understand reason behind it. Any tips in this regard please? The code for the plugin is as follows.

class ExCurrentUserProvider < Auth::DefaultCurrentUserProvider
  TOKEN_COOKIX ||= "logged_in".freeze
  LOCAL_SERVER ||= true
  
  TOKEN_COOKIE ||= "SAMPLE_TOKEN_COOKIE"
  X_API_KEY = "SAMPLE_X_API_KEY"

  def make_auth_request()
    url = 'https://www.example.com/api/auth'
    
    uri = URI.parse(url)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true    
    http.ssl_version = :SSLv3

    request = Net::HTTP::Get.new uri
    request["Cookie"] = "#{TOKEN_COOKIE}=#{@request.cookies[TOKEN_COOKIE]}"
    request["X_API_KEY"] = "#{X_API_KEY}"

    response = http.request(request)
    response.body
  end

  def get_auth_username()
    @request.cookies[TOKEN_COOKIE] = TOKEN_COOKIE_VALUE
    raw_info = make_auth_request(false)    
    return raw_info["data"]["username"]
  end

  def current_user
    return @env[CURRENT_USER_KEY] if @env.key?(CURRENT_USER_KEY)
  
    username = get_auth_username
    user = User.find_by(username: username)

    if !user.nil?
      @env[CURRENT_USER_KEY] = user
    end
    user
  end

end

You really should be using our official SSO support.

3 Likes

@codinghorror: We were earlier planning to use SSO only. But it doesn’t seem to work for our scenario. We have main website let us say example.com. Now, the discourse will be running as discuss.example.com. If a user is loginned in example.com, and when he lands on the discuss.example.com, he should be automatically logined.

Also, if the user signs out from any of the domains, he should be logged out from the other one automatically. This is not going to be handled by SSO properly.

Can this be achieved through SSO?

If session cookie is found (user logged-in in main site) then just redirect to discourse.example.com/login instead of doing the magic yourself.

https://meta.discourse.org/t/discourse-sso-logout/28509/4?u=vinothkannans

3 Likes

@vinothkannans:

In our case, we set the session cookie even for guest users. So, it’s not possible to make this identification by that.

Also, regarding the signout. What if someone clears the cookies on the parent website, then the user will still be logined at discourse.example.com. Relying on logout on the parent website to expire the session cookies of discourse might not work for all scenarios.

Then create a dedicated wildcard cookie / API endpoint in parent website. It should tell whether the user is logged_in or not.

If you use wildcard cookie then you can check the existence in Discourse itself.

2 Likes

To handle logout, your main site can use the Discourse API to log out the user from Discourse when the session on the main site is terminated. This requires two API calls, one to resolve the external ID from your main site to a Discourse user id, and one to log out said user.

2 Likes