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 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.