Skip to content

Tag: Discourse

Discourse SSO login/logout state synchronization tips

Discourse provides SSO integration funtionality which allows using account from an external service to log in. The official Discourse SSO document already provided detail of how to setup Discourse to integrate with external SSO provider. That one should be read very carefully.

Here I’m going to talk about how to made the login/logout state synchronized between Discourse and the reset part of the website(the SSO provider). This is quite important if you would like your visitors to have a good and consistent experience on the site. Without proper setup, the experience is bad in several ways, as described below in each section.

The term “website” in this post refers to the part of the site that is not backed by Discourse. It is the SSO provider for Discourse. If you are using WP or some other site builder, it is similar to implement.

Synchronize state from website to Discourse

Login

When a user is logged in on the website, the URL that link to the forum site should be set to forum.example.com/session/sso

If your site allows anonymous browsing, make sure you detect the user login state and only append the /session/sso part for logged in user. For anonymouse user just direct them to forum.example.com/

Without this setup, when a user navigates to Discourse, he will need to click the Discourse login button to login.

Logout

When a user logout on the website, the website need to send a Discourse API request to this URL:

https://forum.example.com/admin/users/{user_id}/log_out

The user_id here is the user ID in Discourse, it maybe different from the user ID the website uses.

How to get the user_id of Discourse

Quote from the official SSO document.

User profile data can be accessed using the /users/by-external/{EXTERNAL_ID}.json endpoint. This will return a JSON payload that contains the user information, including the user_id which can be used with the log_out endpoint.

So the website need to send the the user ID as above and get back the Discourse user ID, then logout the user.

Without this setup, when a user logs out from website, he is still in login state on Discourse. If he navigates back and forth between the site and Discourse, he will see unmatched login state, very confusing.

Synchronize state from Discourse to website

Login

No special handling required. When SSO is turned on in Discourse and a user click login button in Discourse, he will be redirected to website login page. Once logged in, he will be in logged in state on both website and Discourse.

Logout

The website needs to implement a logout URL such as https://example.com/logout

In Discourse site settings -> users -> logout redirect, fill in that URL. Then when user logs out from Discourse, he will be redirect to the website and log out there also.

Without this, when a user logs out from Discourse, he is still in login state on website.

After followed above tips, your user will have consistent login/logout state on the website.

I’ve also posted this on meta.discourse.org.

Leave a Comment

Fix strange chown error during Discourse bootstrap or rebuild

TL;DR

Discourse is an forum software runs in Docker. When using overlayfs/overlayfs2 storage driver, Docker requires the backing filesystem supports d_type. Or else some strange error will just pop up during some very basic file operations, such as chown command.

The symptom

When bootstrapping or rebuilding Discourse on CentOS, the process fails with chown command related errors.

# ./launcher bootstrap app
FAILED
--------------------
Pups::ExecError: cd /var/www/discourse && chown -R discourse /var/www/discourse failed with return # Location of failure: /pups/lib/pups/exec_command.rb:108:in `spawn'
exec failed with the params {"cd"=>"$home", "hook"=>"web", "cmd"=>["gem update bundler", "chown -R discourse $home"]}
d5f9b0e0bb45020d8b9e1f25cc8b96091eba69a505a60b4178e641530e4ac159
** FAILED TO BOOTSTRAP **

How to confirm whether you are hit by this problem.

If you are running CentOS 7 and the filesystem was created all by default, you get it. CentoOS installer and the mkfs.xfs command both by default create XFS with ftype=0, which does not meet Docker requirement for filesystem d_type support.

Check the xfs_info command output, mind the ftype=0 thing.

# xfs_info /
......
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
......

Then run docker info command to see if Docker pointed it out. You will have to use a new enough Docker version, older ones don’t report d_type information. Below is the output from Docker 1.13.

......
Storage Driver: overlay
Backing Filesystem: extfs
Supports d_type: false
......

If you see above in your system, then you are in trouble now. Not only Discourse but other container apps may run into strange problem when they do file operations on the overlayfs. Fix it ASAP!

The solution

The key is to get your Docker a filesystem with d_type support. Unfortunately this option can only be set while creating the filesytem. Once filesystem creation is done, the only way to change it is to:

  1. Backup data
  2. Recreate filesystem
  3. Restore data.

Step #1 & 3 is out of the scope of this post. Let’s focus on step #2, how to create the filesystem in the correct way. Two options exist, use XFS or Ext4.

If you prefer XFS

When you run mkfs.xfs command to create XFS on your partition/volume, make sure you pass the -n ftype=1 parameter. The command line looks like below

mkfs.xfs -n ftype=1 /path/to/your/device

If you prefer Ext4 FS

Ext4 filesystem created with default option supports d_type, so there is no special parameter to use when you create Ext4 filesystem on your partition/volume. Easy!

Tips for Docker and Discourse

Since Docker puts its files under /var/lib/docker directory, you only need to make sure d_type is supported for this specific directory. So if you have free space on your disk, you don’t have to touch your whole root filesystem. Just allocate some space, create a new filesystem with correct parameter, then mount it under /var/lib/docker and it’s done.

As regards to Discourse, this procedure won’t even hurt your Discourse data. Discourse puts all data under /var/discourse/share directory. When you get a new /var/lib/docker directory, only the container definition is gone. You just need to recreate the container with launcher script, then the site will just back to normal.

With that said, backup data before doing any filesystem or disk related operation is still a good practice!

Reference

My post regarding this issue on Discourse official forum.

Issue: Centos 7 fails to remove files or directories which are created on build of the image using overlay or overlay2.

Issue: overlayfs: Can’t delete file moved from base layer to newly created dir even on ext4

1 Comment