SSO and e-mail addresses having a plus sign

AI-generated summary

A discussion about SSO and e-mail addresses having a plus sign. thabbs reported an issue where Discourse interprets the plus sign as a space, resulting in an error. sam suggested a possible fix, but it was not the cause of the problem. david later clarified that the payload should indeed be url-encoded before base64 encoding, contrary to thabbs’s initial understanding. The documentation has been updated to reflect this.

I’m not sure if this is an implementation error on my side or if this is a bug in the SSO implementation of Discourse.
Users having a plus-extension in the local part of their e-mail address got an error since Discourse interpretes the plus sign as space.

Following Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso) I must not urlencode the payload before encoding it to base64.

Here my basic implementation, written in php:

$email = 'user+extension@example.com';
$payload = base64_encode($nonce. "&email={$email}&external_id={$external_id}&username={$realname}&name={$realname}");
$return_sig = hash_hmac('sha256', $payload, $token);
header("Location: $referer/session/sso_login?sso=". rawurlencode($payload) ."&sig=". $return_sig);

Discourse throws the error: “Nonce has already expired” and writes down the e-mail address as “user extension@example.com” with a space instead of a plus sign.

You need "nonce=" . $nonce. there…

This is already there and was not the reason for my request.

(
    $nonce = base64_decode($sso);
    # starts with nonce=...
)

A little late, I know. But in case anyone else runs into this problem.

In fact we should urlencode the payload before base64 encoding. Our wordpress plugin and our ruby implementation both use library functions to build the payload, which automatically takes care of the encoding.

I updated the docs to make it more explicit: