Discourse-saml: There was an error authorizing your account

Hi All,

So, following on from my post yesterday I have installed the discourse-saml plugin. Our iDP has setup everything on their end, but whenever we attempt to login the following message appears:

Sorry, there was an error authorizing your account. Perhaps you did not approve authorization?

Searching around meta I have found others with this same issues, but it usually relates to social login (e.g. Facebook, Twitter, etc.) rather than using a SSO plugin like discourse-saml.

Looking in the logs, here is the error message:

(saml) Authentication failure! invalid_ticket: OneLogin::RubySaml::ValidationError, The response was received at https://example.com/auth/saml/callback instead of http://example.com/auth/saml/callback

So it looks like the response is going to the https site, whereas it wants to go to the http site. Not sure why it wants the response on the http site - does anyone have an idea about how to tell the plugin to expect the response on the https site?

Thanks in advance!

Digging a little bit deeper into the source code of the discourse-saml plugin:

omniauth.provider :saml,
                      ...
                      :issuer => Discourse.base_url,
                      ...
                      :assertion_consumer_service_url => Discourse.base_url + "/auth/saml/callback",

I think the issue is related to these lines. I am guessing that the Discourse.base_url has the URL of the Discourse instance defined as http which is then being picked up by the assertion_consumer_service_url so that’s http as well.

So, is it possible to change the Discourse.base_url so that it’s https?

Thanks!

So, after doing a fair bit of experimenting I have gotten SAML 2.0 authentication fully working with our Discourse instance. I thought it would be worthwhile posting here in case others would like to do the same thing.

We are running Discourse over HTTPS with a Let’s Encrypt certificate (although the exact issuer is irrelevant, the fact that it’s running over HTTPS is important). As per the first message in this thread, the callback from the iDP was being sent to the HTTP version of our site, not HTTPS.

EDIT: Sorry, there’s a mistake above. It should read the callback from the iDP was being sent to the HTTPS version of our site, but Discourse was expecting it to be sent to the HTTP version.

Despite changing all the settings I could find in Discourse to force HTTPS it still didn’t want to cooperate, and I couldn’t find an easy way change the Discourse.base_url to be HTTPS, rather than HTTP.

So, I did a bit of a hacky solution. I forked the discourse-saml repo on GitHub and replaced the four references to Discourse.base_url with the hardcoded HTTPS URL to our Discourse instance (e.g. https://forum.example.com). I then referenced that repo as the plugin in the app.yml file (so that it used my version instead) and all worked.

Additionally, thanks to @sam on this thread I also made another modification which means that if SAML is the only authentication method being used (which it is for our instance, we have disabled local user accounts) it won’t pop-up for authentication but will instead follow through in the main web browser window. Makes the flow a bit nicer, without additionally windows popping up everywhere.

This is almost certainly incorrect.

Just corrected the typo.

Either you do not have force https set in your site settings, or you are proxying from nginx without the proper headers to pass https.

The force https setting is definitely enabled in the site settings. In terms of the proxying from nginx, I followed the instructions to automatically setup https using Let’s Encrypt from the instructions found in the howto here - I haven’t made any config changes beyond what was described there.

Perhaps @eviltrout can advise because no such hack was needed for the customers we have using SAML.

You should be able to just set the force_https setting to true and base_url will return https

2 Likes

I tried that but it didn’t work - that said, I never checked what the base_url was actually returning (I am fairly unfamiliar with Ruby). However, when I did the hardcoding hack in the plugin everything started working, so I can only assume that when force_https was enabled in the settings it wasn’t setting the base_url to https…at least as far as the discourse-saml plugin was concerned.

Did you restart your server after you changed the setting? The saml plugin is initialized to that URL only when the app starts.

4 Likes

Yep, that was the problem. Thanks for the advice :slight_smile: All fixed following a restart, and back to using the base_url variable rather than the hardcoded URL.