Discourse SSO with Auth0 🚀

TL;DR

Discourse SSO with Auth0 🚀

TL;DR

You can achieve a very seamless SSO experience with Discourse and Auth0 using one of the best features Auth0 has: rules. Check the “Implementation” section for the code.

Background

I don’t know you but I discovered Discourse a while back when I selected it to be part of the online platform for the new political party we are creating in Uruguay based on ICT.

We needed an easy way people can engage talking and discussing about ideas to be part of the Government Programme. It needed to be something familiar for people, like a forum but adapted to this era. It fitted perfectly.

Now, I also had the fantastic idea (modesty aside) to use a service to handle all the users in order to have a consistent experience throughout all the tools in the platform. Something easy to configure, vast to customize and most importantly, free of charge, as we are just growing and we just get funding based on donations (check out OpenCollective, very recommended). That’s why I decided to use Auth0. Very neat service which supports open source projects like the political party I work for and support.

So, anyway, although there is a nice Discourse plugin to hook up Auth0 authentication, I always struggled with how it handled the creation of a user which needed to be re-created in Discurse database to work. What’s the point of having a super user handling service if at the end the user needs to tackle a user creation dialog on Discourse?

Understanding the problem

After a while trying to understand how stuff worked on both ends, Discourse and Auth0, I got the idea of implementing what Discourse needed on Auth0’s side.

When I say a while trying to understand how stuff worked on both ends, I mean submitting a bunch of questions which got very good answers most of the times.

These are some of my attemps:

Official Single-Sign-On for Discourse (sso)
Discourse now ships with official hooks to perform auth offsite. The Problem Many sites wish to integrate with a…
Customize login modal · Issue #20 · auth0/discourse-plugin
Hello! This is a great plugin, I'm hoping to use it on our Discourse instance for our political party on Uruguay based…
SSO vs Oauth2 difference?
Hello I'm working on a website with django CMS. I would like to link the user accounts of my site to discourse. In the…

And that last one was key for the finding relevant to this blog post.

Thanks to Michael Brown’s super neat reply with the following diagrams, I got the realization that something could be done from the authentication service side.

How Discourse handles OAuth2 authentication
How Discourse handles SSO with whatever authentication mechanisms is behind (OAuth2 in this case)

What a journey! But anyway, here comes the code.

Implementation

First of all, a big shoutout to Johan Jatko for creating the discourse-sso node.js package that simplified a lot of code for me to implement this.

This code goes into a new Auth0 rule which is going to be run when a user signs in from Discourse using SSO:

Please replace CLIENT_ID and DISCOURSE_URL with your information. And on line 10, context.clientMetadata.sso_secret is a variable (can be a just a string with the value but avoid doing that as much as possible) set on your Auth0 Client advanced configuration, like this:

Auth0 Client Advanced settings to setup sso_secret

Then, in your Discourse instance, under Settings > Login, you will find these options:

Discourse Admin Login SSO options

The important fields are:
- enable sso
- sso url: https://AUTH0_DOMAIN/authorize?client_id=CLIENT_ID&response_type=code
- sso secret: same as the one included in Auth0 Client variables above

The following ones are just to customize how SSO information from Auth0 can override Discourse information. I suggest enabling verbose sso logging so you can debug better any potential issues related to SSO.

Note: The rule you create to handle this flow will execute and then as the authentication attempt will stop there (no call to /continue?state=STATE_ID will happen), no other subsequent rule will execute, so mind the order of the rules.

Hope it helps someone as lost as I was 👍

And continue giving me feedback, don’t hesitate to let me know if you can think of any improvement.