Error using discourse-oauth2-basic plugin with NeonCRM

Anybody? @david or @Falco?

1 Like

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

https://github.com/discourse/discourse-oauth2-basic/blob/master/plugin.rb#L123-L126

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.

4 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.

1 Like

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:

3 Likes

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?

1 Like

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.

1 Like

Does that error have a backtrace attached to it?

1 Like

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

1 Like
/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'
1 Like

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

2 Likes

I think I’ll start by erasing our current Droplet and set it up from scratch again since this docker was set up a few years back. I’ll report back when I have done that and tested it.

2 Likes

Sounds like a good plan. For most communities we recommend sticking to the default tests-passed branch, because it gives you the latest and greatest Discourse features and bug fixes. There have been a lot of changes to authentication since the last stable release, so you might find things start working by themselves.

3 Likes

@david, I’ve taken the time to take another go at it today. I am now using a fresh Discourse install (latest on stable-passed, as you suggested).

I’ve set up Oauth2 using the plugin, just like before with the following settings:

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

If I use the manually formatted URL, I get this (which is new):

Authorization timed out, or you have switched browsers. Please try again.

And the usual error in the logs:

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

On the other hand, if I use the OAuth2 button in the Discourse login window, I get:

Oops

The software powering this discussion forum encountered an unexpected problem. We apologize for the inconvenience.

Detailed information about the error was logged, and an automatic notification generated. We'll take a look at it.
1 Like

I also get the following errors logged in /logs:

ArgumentError (Invalid URI: ) /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/excon-0.71.0/lib/excon.rb:126:in `new'

and

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

@david I tried your earlier suggestion regarding setting oauth2_user_json_url and disabling oauth2_fetch_user_details, and I got a bunch of (new) errors after trying it:

ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR: null value in column “provider_uid” violates not-null constraint
DETAIL: Failing row contains (1, oauth2_basic, null, null, 2019-12-19 01:00:49.076659, {}, {“token”: “9607”, “expires”: false}, {}, 2019-12-19 01:00:49.077107, 2019-12-19 01:00:49.077107).
)
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.1.4/lib/patches/db/pg.rb:69:in `async_exec_params’

Failed to handle exception in exception app middleware : PG::NotNullViolation: ERROR: null value in column “provider_uid” violates not-null constraint
DETAIL: Failing row contains (1, oauth2_basic, null, null, 2019-12-19 01:00:49.076659, {}, {“token”: “9607”, “expires”: false}, {}, 2019-12-19 01:00:49.077107, 2019-12-19 01:00:49.077107).

And of course the usual:

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

However I noticed in this last one (CSRF Detected) that in the env tab, it says:

hostname forum-app
process_id 762
application_version db7d00a8dce2cc1f7b9d86192cde1f55dd57408b
HTTP_HOST forum.efao.ca

Is it normal for the hostname to not match the HTTP_HOST name? Could that be why I get CSRF error?

1 Like

Hey Denis,

any luck?
I got the same error:
ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR: null value in column “provider_uid” violates not-null constraint

How did you fix it?

Thanks,
Beam

1 Like

Denis and I worked out that NeonCRM aren’t really sticking to the oauth2 spec… they are sending the user_id inside the access_token variable, and it cannot be used as an actual access token.

So, you need to disable oauth2_fetch_user_details, and set oauth2_callback_user_id_path to token (not access_token, because the oauth2 ruby library renames it for internal use)

With that, it should be functional, but there is no way to fetch the user email/name

Hey Denis,

I’m using mattermost so it’s behaving differently.
However, your info made me look more at the settings and I have it working, thanks!!

Here are my settings for mattermost as an oauth2 provider to discourse:

Settings in text for search engines:

oauth2 client id: <client id from mattermost oauth2 provider setup>
oauth2 client secret: <client secret from mattermost oauth2 provider setup>
oauth2 authorize url: https://chat.animalrebellion.org/oauth/authorize
oauth2 token url: https://chat.animalrebellion.org/oauth/access_token
oauth2 token url method: POST
oauth2 callback user id path:
oauth2 callback user info paths
oauth2 fetch user details: CHECKED
oauth2 user json url: https://chat.animalrebellion.org/api/v4/users/me
oauth2 user json url method: GET
oauth2 json user id path: id
oauth2 json username path: username
oauth2 json name path: username
oauth2 json email path: email
oauth2 json email verified path: email_verified
oauth2 json avatar path:
oauth2 email verified: CHECKED

On the mattermost side, the callback url is set as:
https://base.animalrebellion.org/auth/oauth2_basic/callback

Still would like to see how to join: first_name and last_name into the “jason name path” as full_name, but can live with just using the “username” or “first_name” property.

HTH

Cheers!
Beam

Links to resources:
Link to plugin: https://github.com/discourse/discourse-oauth2-basic
Link to how to install discourse plugin: Install Plugins in Discourse

1 Like

Happy you got it working @Beam!