Error using discourse-oauth2-basic plugin with NeonCRM

I’m trying to set up the discourse-oauth2-basic plugin so that our users can sign into our Discourse forum using their account credentials created and stored through NeonCRM.

A NeonCRM support tech explained to me that I can create the authorization URL manually using this format:

https://{{Org ID}}.z2systems.com/np/oauth/auth?response_type=code&client_id={{Client ID}}&redirect_uri={{Redirect URL}}

In Discourse, I set the following parameters for the plugin:

oauth2 client id: MY-CLIENT-ID
oauth2 client secret: MY-CLIENT-SECRET
oauth2 authorize url: https://MY-NEON-ID.z2systems.com/np/oauth/auth
oauth2 token url: https://www.z2systems.com/np/oauth/token

So I manually created this URL (which I censored):

https://MY-NEON-ID.z2systems.com/np/oauth/auth?response_type=code&client_id=MY-CLIENT-ID&redirect_uri=https://MY-FORUM.COM/auth/oauth2_basic/callback

And when I enter this URL in a browser, I get a Discourse page with the following message:

And my logs say:

(oauth2_basic) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

Why?

So if I use this URL instead:

https://MY-NEON-ID.z2systems.com/np/oauth/auth?response_type=code&client_id=MY-CLIENT-ID&redirect_uri=https://MY-FORUM.COM/

(I removed the callback part at the end of my redirect_uri)

I actually make it to the NeonCRM login page, after which I enter my test user credentials and log in. I am then redirected to MY-FORUM.COM. But once I’m there I am not logged in at all. If I click on the “Login” button at the top of the page and click on the grey "login with OAtuh2: button, a new window opens with the following message:

And two errors show up in my logs:

ArgumentError (Invalid URI: )

/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/excon-0.64.0/lib/excon.rb:126:in `new’

and

Failed to handle exception in exception app middleware : Invalid URI:

This redirect_uri is wrong. You need to set it correctly for the flow to work.

In the plugin documentation it’s the first thing in the basic setup.

NeonCRM also documents how to set it on their docs

1 Like

Thanks @Falco!

I did try to set the redirect_uri to:

https://MY-FORUM.COM/auth/oauth2_basic/callback

But that did not work, see my original post (which I just edited so it was less confusing, sorry if you missed it).

Is your forum running in HTTPS ?

Yes, it is @Falco.

Did you enable the force_https setting

@Falco, I found instructions to enable force_https, and I have set it to true.

Still get the same error though.

I’ve integrated the widget that NeonCRM suggests I use at the top of the forum (so you can try it yourself if you’d like) at

When I use the widget I get the same result as in my original post.

(oauth2_basic) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

Anybody? @david or @Falco?

The only place we use Excon in the oauth2 plugin is here:

What do you have set for the oauth2_user_json_url? I suspect it is blank. If so, you should also disable oauth2_fetch_user_details, so that Discourse does not try and contact a blank URL.

3 Likes

@david, it is indeed blank.

I don’t know what to set as oauth2_user_json_url. Unfortunately, I’ve run out of luck trying to get NeonCRM to help me figure this out through their tech support.

If I try to disable it, I get a message telling me I need to set oauth2 callback user id path, but as I said above, I don’t know what this value should be.

I don’t have a NeonCRM install to test it with, but I think setting it to access_token should work. Can you try that?

From the docs Falco linked above:

1 Like

Same error:

(oauth2_basic) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

Backtrace:

 /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/logger.rb:110:in `report_to_store'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/logger.rb:101:in `add_with_opts'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/logger.rb:52:in `add'
/usr/local/lib/ruby/2.6.0/logger.rb:543:in `error'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:163:in `log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:486:in `fail!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-oauth2-1.6.0/lib/omniauth/strategies/oauth2.rb:71:in `callback_phase'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:238:in `callback_call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:189:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/builder.rb:64:in `call'
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:30:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/tempfile_reaper.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/conditional_get.rb:25:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/head.rb:12:in `call'
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
/var/www/discourse/lib/middleware/anonymous_cache.rb:218:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:232:in `context'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:226:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/cookies.rb:670:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:98:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/middleware/reporter.rb:43:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:38:in `call_app'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:28:in `call'
/var/www/discourse/config/initializers/100-quiet_logger.rb:18:in `call'
/var/www/discourse/config/initializers/100-silence_logger.rb:31:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/request_id.rb:27:in `call'
/var/www/discourse/lib/middleware/enforce_hostname.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/method_override.rb:22:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:14:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/sendfile.rb:111:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.1.0/lib/mini_profiler/profiler.rb:184:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/message_bus-2.2.0/lib/message_bus/rack/middleware.rb:57:in `call'
/var/www/discourse/lib/middleware/request_tracker.rb:163:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/engine.rb:524:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `method_missing'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:68:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:605:in `process_client'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:700:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:548:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:144:in `start'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `<main>'

Interesting… the backtrace suggests that error is coming from this part of the OAuth2 library. That means that the state parameter is not being matched up correctly.

To confirm, this error is from your production site?. I tried logging in to that, and from my end it looks like the state is being passed around correctly.

That suggests some issue on the server-side. How is your site hosted? Did you follow our standard procedure?

Also @david, and I don’t know if this is related, but I also have this separate entry in our logs:

Job exception: SSL_connect returned=1 errno=0 state=error: certificate verify failed (self signed certificate)

We use Let’sEncrypt for our SSL certificate.

Does that error have a backtrace attached to it?

Yes forum.efao.ca is our production site. We are hosted on Digital Ocean and it was installed using the standard procedure.

/usr/local/lib/ruby/2.6.0/net/protocol.rb:44:in `connect_nonblock'
/usr/local/lib/ruby/2.6.0/net/protocol.rb:44:in `ssl_socket_connect'
/usr/local/lib/ruby/2.6.0/net/pop.rb:553:in `do_start'
/usr/local/lib/ruby/2.6.0/net/pop.rb:531:in `start'
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:43:in `poll_pop3'
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:18:in `execute'
/var/www/discourse/app/jobs/base.rb:232:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.0.7/lib/rails_multisite/connection_management.rb:63:in `with_connection'
/var/www/discourse/app/jobs/base.rb:221:in `block in perform'
/var/www/discourse/app/jobs/base.rb:217:in `each'
/var/www/discourse/app/jobs/base.rb:217:in `perform'
/var/www/discourse/app/jobs/base.rb:279:in `perform'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_scheduler-0.11.0/lib/mini_scheduler/manager.rb:83:in `process_queue'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_scheduler-0.11.0/lib/mini_scheduler/manager.rb:34:in `block in initialize'

I’m afraid there’s not a huge amount more I can do to diagnose this without access to the server. We have a lot of people using the oauth2 plugin without issue, so I think this must be a configuration issue somewhere. The only other thing that might help is to upgrade to the latest version of Discourse, rather than using the stable branch.

Maybe someone else in the community will jump in, but if not you may have some success asking for help in the #marketplace