Problem redirecting to forum after login when using MemberMouse


(Leah Kramer) #1

Hello. So in searching some other threads here, it seems like the expected behavior is this:

  1. Someone is reading a thread in Discourse and decided to login so they click the Login button
  2. They pop over to WordPress where they login
  3. They are redirected back to the Discourse thread that they were reading

That sounds great! In our case, this isn’t working I think because we use the MemberMouse plugin which forces people to a certain “welcome” URL after logging in. BUT, I can bypass that with a filter MemberMouse provides.

The only problem, is that the URL of the Discourse topic the person was reading doesn’t seem to be passed to WordPress.

E.g. Let’s say I’m in this topic in Discourse:
https://forums.gemsociety.org/t/any-brazil-company-which-sold-rough-faceting-amethyst-citerine-and-amertine/1246

And I click the Login button in Discourse

I get sent to this URL:
https://www.gemsociety.org/login/?redirect_to=%2Flogin%3Fsso%3Dbm9uY2U9Y2IwZGE0NmRlMGM0YTlhOGM1OTc4OGU0NGRjOGU3MDkmcmV0dXJu%250BX3Nzb191cmw9aHR0cCUzQSUyRiUyRmZvcnVtcy5nZW1zb2NpZXR5Lm9yZyUy%250BRnNlc3Npb24lMkZzc29fbG9naW4%253D%250B%26sig%3D419ba4dfda93d068c81470cf32e4aec633217047728a9bca514bbae3891cffde

Nowhere in that big string do I find the URL the person was reading in Discourse (/any-brazil-company…/).

So, I’m a little confused here. Any thoughts? Thanks!


(Simon Cossar) #2

The sso return path is saved on Discourse as the value of the nonce key. If you can find a way to get your WordPress site to redirect back to Discourse (/session/sso_login?) with the sso params users should get redirected to the page they clicked the login link on.


(Leah Kramer) #3

Thanks Simon for the reply. So, should I redirect the user to this?

https://forums.gemsociety.org/session/sso_login?sso=bm9uY2U9ZTU3NWU3YzI2ODM2MjEzYjNmZTNmZWE5ZTc4NjNiNTQmcmV0dXJu%250BX3Nzb191cmw9aHR0cCUzQSUyRiUyRmZvcnVtcy5nZW1zb2NpZXR5Lm9yZyUy%250BRnNlc3Npb24lMkZzc29fbG9naW4%253D%250B%26sig%3D9c9ee72cd56218de3fb5ba46b985084369874fc5f434afdb1d9b5d14d170c0a

When I do this, I get a blank screen in Discourse.


(Simon Cossar) #4

Right, that’s not going to work. If you look here: wp-discourse/discourse-sso.php at master · discourse/wp-discourse · GitHub you can see what needs to happen. If the sso and sig parameters are in the query_vars and a user is not logged in, they are redirected to the WordPress login URL with the SSO request from Discourse set as the redirect parameter. It seems like the MemberMouse plugin is overriding that redirect.

Somehow, you need to preserve the redirect (the parameter from this line: $login = wp_login_url( esc_url_raw( $redirect ) ); and redirect to it after MemberMouse has done its work. The request should then be processed by the part of the sso_parse_request function that begins here:


(Leah Kramer) #5

I got it working! Thanks very much @Simon_Cossar.

Now when someone comes into the forum; clicks the blue Login button; logs into wordpress by typing in their username/pw; they are redirected back to thread they were at in Discourse.

I think this is going to be a huge win for people who come in via the Discourse emails e.g. and want to participate in the thread. Previously, they’d lose track of where they were since they didn’t get redirected back to the thread.


(Leah Kramer) #6

P.S.

For anyone else looking into this – This “redirecting back to where you were” behavior works (thx to the WP-Discourse plugin) in the scenario #1 where you are already logged into WordPress.

But it’s scenario #2 where you need to login to WordPress that you are not automatically redirected back to the forum thread where you were. This is what I added in myself thanks to @Simon_Cossar 's help.

I thought it was due to my membership plugin but I actually just think the scenario #2 redirect functionality doesn’t exist in the WP-Discourse plugin. I could be wrong about this, feel free to correct me!


(Simon Cossar) #7

Yes, WordPress plugin has that functionality, but other plugins that do login redirects can break it.


(Richard - DiscourseHosting.com) #8

Could you please share what you exactly have done to fix this?


(Simon Cossar) #9

When SSO is enabled, clicking the login link on Discourse should automatically redirect users back to the Discourse page that they clicked the login link on. If this isn’t working for you, can you give some details about where you are seeing the problem?


(Leah Kramer) #10

Hi Richard. It’s been a while since I worked on this and things seem to be changing from time to time in the discourse plugin (new and better functions keep cropping up) but this is what I did way back them and it still works for us.

We use the wordpress plugin membermouse. And membermouse is written in such a way that after you login, you get redirected to a specific wordpress “welcome member!” page. So this functionality was overriding discourse’s attempt to redirect you back to where you were in discourse.

membermouse has a filter called mm_login_redirect where you can change membermouse’s behavior of redirecting the user to that “welcome member!” page. Below is the php code I wrote for that filter.

// If the person came from the discourse forum, push them back after logging in
function my_mm_login_redirect( $infoObj ) {

	$current_user = $infoObj->user;
	if ( is_wp_error($current_user) ) return('');
	
	$user_id = $current_user->ID;

	if ( @$_COOKIE['detected_forum_referal'] != '' ) {

		// Payload and signature.
		$payload = @$_COOKIE['mm_cookie_sso'];
		$sig     = @$_COOKIE['mm_cookie_sig'];
		
		// Change %0B back to %0A.
		$payload = rawurldecode( str_replace( '%0B', '%0A', rawurlencode( $payload ) ) );
		
		// Validate signature.
		$sso_secret = '###################';
		$sso        = new \WPDiscourse\SSO\SSO( $sso_secret );
		if ( ! ( $sso->validate( $payload, $sig ) ) ) {
			return '';
		}
		
		$nonce  = $sso->get_nonce( $payload );
		$params = array(
			'nonce'               => $nonce,
			'username'            => $current_user->user_login,
			'email'               => $current_user->user_email,
			'external_id'         => $user_id,
		);
		
		$params = apply_filters( 'wpdc_sso_params', $params, $current_user );
		$q = $sso->build_login_string( $params );

		do_action( 'wpdc_sso_provider_before_sso_redirect', $user_id, $current_user );
		
		// Redirect back to Discourse.
		return('https://YOURFORMURLHERE' . '/session/sso_login?' . $q);
	}
	return('');
}
add_filter( 'mm_login_redirect', 'my_mm_login_redirect', 10, 1 );

(Richard - DiscourseHosting.com) #11

Thank you so much!!
We’ve been struggling with this MemberMouse behavior all day and this seems to be the perfect solution! :slight_smile:


(Joshua Rosenfeld) #12

Hey @lkramer, you included a $sso_secret in the code above. We’ve removed it, but if that is a valid $sso_secret you should change it.


(Leah Kramer) #13

(Oops. Thx all sorted out.)

Btw, I should reiterate that there may be a better way to accomplish than my code above. It’s just what worked at the time that I needed to solve this issue.


(Simon Cossar) #14

Thanks for doing this! I installed the Membermouse plugin in my development environment today. Getting the redirect back to Discourse is harder than I expected. I don’t think there’s any reason to change the way you are doing it, but here’s an alternate approach. It at least shows how the plugin expects things to work. Generally, it should be possible to do this by hooking into the WordPress login_redirect filter and getting the Discourse redirect_to parameter from that filter’s $request parameter. This can’t be done with Membermouse though.

This function depends on being able to get the HTTP_REFERER with wp_get_referer. The referer may not always be available. If it isn’t, the user will be redirected to the default Membermouse redirect. I have only tested this in my development environment.

add_filter( 'mm_login_redirect', 'wpdc_login_redirect_override' );
function wpdc_login_redirect_override() {
    $referer = wp_get_referer();
    if ( $referer ) {
	    $query_params = [];
	    parse_str( parse_url( $referer, PHP_URL_QUERY ), $query_params );
	    if ( isset( $query_params['redirect_to'] ) ) {

		    return home_url( $query_params['redirect_to'] );
	    }
    }

	return '';
}

WP / MemberMouse / Discourse Integration Guide
(Leah Kramer) #15

@Simon_Cossar, I did a test and that function you provided definitely works. So much more compact and efficient. Thanks! (@RGJ you should definitely give that function a try.)


(Richard - DiscourseHosting.com) #16

Works like a charm indeed! Thank you @Simon_Cossar