Official Single-Sign-On for Discourse (sso)


(Simon King) #280

I think you are getting confused by the “\n” on the end of the base64-encoded payload. This is meant to be a newline character (LF, ASCII value 0x0a), but you’ve pasted the two characters “backslash” and “n” into that web page.

I can’t get that web page to generate the right HMAC because even if you add an actual newline after the encoded string, the site treats that as a windows-style CRLF rather than the plain LF that you really want, giving you the incorrect 200c03f1e5d7b859170be102b436d74f761040261be9682b4afec67eb908fabf

If you have access to Python, here are some examples:

import hmac, hashlib
def makesig(secret, payload):
    hasher =, payload, hashlib.sha256)
    return hasher.hexdigest()

secret = 'd836444a9e4084d5b224a60c208dce14'

# Using newline character, LF
print makesig(secret, 'bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\n')
# correct (2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56)

# Using literal backslash-n
print makesig(secret, 'bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\\n')
# incorrect (a265194763a84c4d9ad1f17e113f2bbc8d356441d44ec9dec13ad442928547d4)

# Using CRLF
print makesig(secret, 'bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\r\n')
# incorrect (200c03f1e5d7b859170be102b436d74f761040261be9682b4afec67eb908fabf)

(Adli Bazuli) #281


You are correct, I found out the 0x0A LF was stripped out. I had to manually access un-decoded query string in my code and all is fine.

(Sam Saffron) #282

Note, I just added optional rich logging for SSO via:

This site setting verbose_sso_logging can help you debug your SSO provider, however, be careful it gets very loud… only enable while you are debugging issues with your provider.


I’ve had SSO enabled on an active Drupal site with 1000+ users connected to a Discourse instance with many of those users. I am the only admin on both sites and I just recently logged in and noticed that I was in a new Discourse account (old username with “1” appended). Upon further investigation, I noticed that another Drupal user had taken over my Discourse account.

Neither the external_id or email values changed, but somehow the user replaced my admin info. I immediately disabled that user’s (my old user) admin privileges, but am wondering how that would happen???

(Jeff Atwood) #284

This usually means there is a mistake in the SSO implementation on the parent site side.


Any idea where to start looking?

Technically the emails can change, but I don’t know how that would override an existing email. Can you confirm that the email is the mapping key?

(Dean Taylor) #286

You really want to be using external_id.


I’m passing both the external_id and email. However, the documentation above states:

Discourse uses emails to map external users to Discourse users…

Is there a way to make the external_id the mapping key?

(Felix Freiberger) #288

Discourse always uses external_id. The email address is used only if the external id is unknown (then it will look up the address and permanently assign the external id).

(Kane York) #289

I just added some detail explaining how those are different to the first post.


Is there any way to make this WooCommerce compatible?

WooCommerce login occurs on rather than on wp-login.php.

Maybe we can have an option to turn on for this to “Use WooCommerce My Account page for login” on the backend of the plugin.

(Erick Guan) #291

Can avatar_url be accepted without enabling sso_overrides_avatar? Thus the new user will be assigned an avatar without being disabled changing the avatar in the future. It’ll still fits the semantics like sso_overrides_{email,username,name}.

(Sam Saffron) #292

Sure, PR welcome to add that support

(Michael Ravits) #296


We’ve implemented SSO successfully and users login to Discourse using our main application.

We would like to get users automatically logged in into discourse if they are already logged in with the application. i.e by just navigating to Discourse site without clicking the Login button in Discourse.

Is this something supported by Discourse? Or maybe there are extensions to help with this flow?


(Erick Guan) #297

Sending your user (302/307) to /session/sso. Discourse will start a sso login process.

(Michael Ravits) #298

Hi Erick,

Thanks for your answer!

Is there anything we could do to automatically login users which navigate directly to the discourse site?

One thing which comes to mind is to embed a JS code which checks if the app login cookie exists and then redirect the user to the SSO login.
Or maybe an extension which does the same but on the server side, before the discourse page loads?


(Erick Guan) #299

Isn’t a HTTP redirection just do that? Please say more on what you are intended to do. Click a button? User logined?

Are you saying when user enter Discourse, something checks for cookies and redirect user to the SSO login?
In this case, your cookies may or may not be a session cookies. JS can’t decrypt other site’s session cookie since it probably is encrypted.

I don’t know how to do that or whether it’s possible. And you probably need to say more on how you setup your domains/web server. Sharing cookies across subdomain is delicate.

Change right gutter to vertical timeline + topic controls
(Lapinot) #300

it is widely told that internet protocol design especially for authentification is a tough thing, so I don’t quite get it why you are designing your own where you could just use an existing sso protocol like SAML, OpenID, OAuth (not quite sso), CAS, LDAP… And without checking I am sure there is a ruby library for each of these. It simply seems weird to me.

Edit: I discovered this evening and it looks a bit like your custom protocol for secure payload transmitting. Wouldn’t it be better to switch to that?

(Sam Saffron) #301

All of which we support, some in core, some via plugins, so I am not really following the question here.

If you find it easier to integrate using a different protocol, go for it

(Michael Ravits) #302

Hi Erick,

My goal is to have the user automatically logged in to discourse if he is logged in to our application, without requiring the user to click the login button.

Regarding the JS solution I proposed, this could be a JS file loaded from the application domain/subdomain - this should give the script access to the app cookie. The script would simply check for the existence of that cookie - if it’s present then the code would redirect the user to the SSO URL.

Looks like sharing a cookie between a domain and a subdomain is feasible.

So regarding the server side solution, I’m also only theorizing since I’m not familiar yet with what’s possible in Discourse plugins.
It would be great if someone knowledgeable could say whether it’s feasible and possibly a good way to go.