Discourse doesn't redirect to return_sso_url after user logs in on private site

I have a discourse instance which requires you to login, and doesn’t support anonymous browsing.

I also have a separate django app that uses python-social-auth to login to Discourse using its SSO protocol.

When a user logs in to the django app using the discourse SSO login, one of the two following sequences happen:

If the user is already logged in to discourse:

  1. They click the login button in the django app
  2. and are redirected to discourse’s SSO url
  3. and are immediately redirected back to the django app

However, if they’re not already logged in to discourse:

  1. They click the login button in the django app
  2. and are redirected to discourse’s SSO url
  3. which then redirects them to /login in the discourse app
  4. the user logs in to discourse
  5. they are redirected to the front discourse page
  6. and are never redirected back to the django app, meaning they need to remember to go back to the app after logging in to discourse and /start over from step 1, but now following other sequence of steps I wrote above/

My django app’s discourse SSO code can be found here:

I followed the steps here:

Am I missing something that isn’t documented? I see a lot of posts on discourse.org and a few merged pull requests in github that seem to allude to this having been fixed once before in 2015, but I can’t get it to work for some reason.

3 Likes

I’ve just tested this out with the WP Discourse plugin and using Discourse as the SSO Provider is working correctly for me on a private site. Users who are already logged into Discourse are automatically redirected back to the website. Users who are not logged into Discourse are redirect to the Discourse /login page. After clicking the Login button and entering their credentials, they are redirected back to the website.

You can see the WP Discourse implementation here: https://github.com/discourse/wp-discourse/tree/master/lib/sso-client. The important part is how the payload is created: https://github.com/discourse/wp-discourse/blob/master/lib/sso-client/query-redirect.php#L93.

In the Discourse code, the difference between how logged in and non-logged in users is handled starts here: https://github.com/discourse/discourse/blob/master/app/controllers/session_controller.rb#L56. A non-logged in user is redirected to /login with cookies[:sso_payload] set to the query string you sent from your django app. After being logged in, the sso_provider code should be being called again, with the payload set to the value of cookies[:sso_payload]. It seems that’s not happening for you.

3 Likes

Since you mentioned it, I decided to test the wp-discourse plugin as well. We currently use it for login to our wordpress site without issue, however having just now tested it inside of an incognito window I see that I’m getting the same exact behavior of no redirect back to wordpress after using the twitter login!

I’m really not sure what is different here. I used the chrome inspector to pick out the requests and here’s what I found:

  • Clicking on the django app’s ‘login with discourse’ button redirects me to /session/sso_provider?sig=bc16879aa51daa815318c1de6acdf8adb85f6e778d1e739334dd425a8b047b2d&sso=bm9uY2U9ODEwOTg1NzkmcmV0dXJuX3Nzb191cmw9aHR0cHM6Ly9vcmdhbml6aW5nLmVhc3RiYXlmb3JldmVyeW9uZS5vcmcvY29tcGxldGUvZGlzY291cnNlLw%3D%3D
  • Discourse responds to that request with a 302 redirect to /login, and sets the sso_payload cookie to sig%3Dbc16879aa51daa815318c1de6acdf8adb85f6e778d1e739334dd425a8b047b2d%26sso%3Dbm9uY2U9ODEwOTg1NzkmcmV0dXJuX3Nzb191cmw9aHR0cHM6Ly9vcmdhbml6aW5nLmVhc3RiYXlmb3JldmVyeW9uZS5vcmcvY29tcGxldGUvZGlzY291cnNlLw%253D%253D
  • Following the redirect, my browser sends sig%3Dbc16879aa51daa815318c1de6acdf8adb85f6e778d1e739334dd425a8b047b2d%26sso%3Dbm9uY2U9ODEwOTg1NzkmcmV0dXJuX3Nzb191cmw9aHR0cHM6Ly9vcmdhbml6aW5nLmVhc3RiYXlmb3JldmVyeW9uZS5vcmcvY29tcGxldGUvZGlzY291cnNlLw%253D%253D for the sso_payload cookie.
  • At this point, I’m looking at the “please login to discourse” screen. I click the login button, then the twitter button in the pop-up.
  • I sign in with my twitter account
  • The same song and dance happens, and my browser ends up requesting / from the discourse app, while sending the sso_payload cookie of sso_payload=sig%3Dbc16879aa51daa815318c1de6acdf8adb85f6e778d1e739334dd425a8b047b2d%26sso%3Dbm9uY2U9ODEwOTg1NzkmcmV0dXJuX3Nzb191cmw9aHR0cHM6Ly9vcmdhbml6aW5nLmVhc3RiYXlmb3JldmVyeW9uZS5vcmcvY29tcGxldGUvZGlzY291cnNlLw%253D%253D
  • I am never redirected to my django app.

In every step, the cookie seems intact and I can base64 decode it to generate the proper sso_payload. Here is one such payload: nonce=81098579&return_sso_url=http://localhost:8000/complete/discourse/

Should I be urlencoding the return_sso_url parameter as well? That isn’t mentioned in the documentation, so I’m currently not doing; modifying my django app to urlencode it also does not change this behavior and still gets me no redirects. That also wouldn’t explain why our wordpress plugin isn’t getting redirects either.

After re-reading your post though, I’m wondering if you’re testing using username+password logins instead of twitter logins. We have password logins turned off and the only way you can login to our discourse is through twitter. That might explain the differences.

3 Likes

Yes, that’s it! I can reproduce the problem with the wp-discourse plugin when I use Facebook login. I’ll look into what’s going on.

3 Likes

It’s fixed as per below commits. @tdfischer can you please check again.

https://github.com/discourse/discourse/commit/ca7424665118e527eddbcb3c8bb764dd942585d7

https://github.com/discourse/discourse/commit/be6404d6519d03cfb9194bc03e5c6b9593513c1d

6 Likes

This topic was automatically closed after 52 days. New replies are no longer allowed.