Filling in discourse_username when not using DiscourseConnect

This was a question on an old github issue, which is more easily tracked here on meta

From @mattdm:

We’re using OpenID for login, and it seems like that option is only available when using DiscourseConnect. Is there another way? Filling them in manually is pretty annoying.

We do allow users to edit their email address (distinct from the SSO) on the Discourse sites, but the user id is guaranteed to be the same.

My initial response (questions are still outstanding)

Hey @mattdm, could you clarify a few things:

  1. A user’s email may be different between their accounts on wordpress and discourse?
  2. What do you mean that “the user id is guaranteed to be the same.”? Which user id are we talking about?

Oh, sorry — I was sure I answered that before but I guess… I didn’t? Maybe I just thought about it! Anyway:

  1. The email is initially synced from the SSO for both WordPress and Discourse. However, due to popular demand, we allow people to change that email on Discourse. (It turns out to be frequent to want Discourse notifications going somewhere other than the email associated directly with the login.) It is also possible to change the email address on Wordpress, but I don’t know of anyone who does that, or even if outgoing email on that instance works.

  2. By “user id”, I meant “username”. The username is always[1] taken from the SSO for both Discourse and Wordpress and can’t be changed by the user in either case. For some reason unknown to me but which probably made sense at the time, this is nickname on our SSO side; this is mapped to oauth2 json username path.

  1. Actually it turns out that there are few accounts like my own which happen to have been set up before we had the SSO, and they’re wrong — I’m “Matthew Miller” instead of mattdm. But we could clean that up. ↩︎

hm ok, so effectively

  1. There would be a subset of your users with different emails on wordpress and discourse.
  2. Your username is gauranteed to be the same as its provided by your identity provider for both wordpress and discourse

If we were to decouple the WP Discourse user webhook from the DiscourseConnect functionality (possible), then user matching would occur on the basis of email, not username. Your situation is somewhat specific to your identity setup.

I think this case that’s better handled via custom code on your wordpress. What you want is something like this:

function update_discourse_username( $user_login, $user ) {
    update_user_meta( $user->ID, 'discourse_username', $user_login );
add_action( 'wp_login', 'update_discourse_username', 10, 2);

Basically, just assign the discourse_username meta field as the WP username after login, as they’re guaranteed to be the same. Note that “user_login” is what the “username” is sometimes called in wordpress code.