Erro ao usar o plugin discourse-oauth2-basic com NeonCRM

Estou tentando configurar o plugin discourse-oauth2-basic para que nossos usuários possam fazer login em nosso fórum Discourse usando as credenciais de conta criadas e armazenadas no NeonCRM.

Um técnico de suporte do NeonCRM me explicou que posso criar a URL de autorização manualmente usando este formato:

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

No Discourse, configurei os seguintes parâmetros para o 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

Então, criei manualmente esta URL (que eu censurei):

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

Ao inserir essa URL no navegador, recebo uma página do Discourse com a seguinte mensagem:

E meus logs dizem:

(oauth2_basic) Falha na autenticação! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detectado

Por quê?

Então, se eu usar esta URL no lugar:

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

(Removi a parte do callback no final do meu redirect_uri)

Eu realmente consigo acessar a página de login do NeonCRM. Após isso, insiro minhas credenciais de usuário de teste e faço o login. Sou então redirecionado para MY-FORUM.COM. Mas, ao chegar lá, não estou logado de forma alguma. Se clicar no botão “Login” no topo da página e depois no botão cinza “login with OAuth2”, uma nova janela se abre com a seguinte mensagem:

E dois erros aparecem nos meus logs:

ArgumentError (Invalid URI: )

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

e

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

Esse redirect_uri está incorreto. Você precisa configurá-lo corretamente para que o fluxo funcione.

Na documentação do plugin, é a primeira coisa em configuração básica.

A NeonCRM também documenta como configurá-la em sua documentação.

Obrigado, @Falco!

Eu tentei definir o redirect_uri para:

https://MEU-FÓRUM.COM/auth/oauth2_basic/callback

Mas isso não funcionou. Veja minha postagem original (que acabei de editar para ficar menos confusa, desculpe se você não viu).

Seu fórum está rodando em HTTPS?

Sim, é @Falco.

https://forum.efao.ca/

Você ativou a configuração force_https?

@Falco, encontrei instruções para habilitar o force_https e o configurei como true.

Ainda assim, continuo recebendo o mesmo erro.

Integrei o widget que a NeonCRM sugere usar no topo do fórum (para que você possa testá-lo se quiser) em

https://forum.efao.ca/

Quando uso o widget, obtenho o mesmo resultado que no meu post original.

(oauth2_basic) Falha de autenticação! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detectado

Alguém? @david ou @Falco?

A única vez que usamos o Excon no plugin oauth2 é aqui:

O que você configurou para oauth2_user_json_url? Suspeito que esteja em branco. Se for o caso, você também deve desabilitar oauth2_fetch_user_details, para que o Discourse não tente contatar uma URL vazia.

@david, está realmente em branco.

Não sei o que definir como oauth2_user_json_url. Infelizmente, esgotei minha sorte tentando obter ajuda da NeonCRM para resolver isso por meio de seu suporte técnico.

Se eu tentar desativá-lo, recebo uma mensagem dizendo que preciso definir oauth2 callback user id path, mas, como mencionei acima, não sei qual deve ser esse valor.

Não tenho uma instalação do NeonCRM para testar, mas acho que configurá-lo como access_token deve funcionar. Você pode tentar isso?

Dos documentos que o Falco linkou acima:

Mesmo erro:

(oauth2_basic) Falha de autenticação! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detectado

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

Interessante… o rastreamento de erro sugere que o problema está vindo desta parte da biblioteca OAuth2. Isso significa que o parâmetro state não está sendo correspondido corretamente.

Para confirmar, esse erro é do seu site de produção? Tentei fazer login nele e, do meu lado, parece que o state está sendo passado corretamente.

Isso sugere algum problema no lado do servidor. Como seu site está hospedado? Você seguiu nosso procedimento padrão?

Também, @david, e não sei se isso está relacionado, mas tenho também esta entrada separada em nossos logs:

Exceção de Job: SSL_connect returned=1 errno=0 state=error: falha na verificação do certificado (certificado autoassinado)

Usamos o Let’s Encrypt para nosso certificado SSL.

Esse erro tem um backtrace anexado?

Sim, forum.efao.ca é nosso site de produção. Estamos hospedados na Digital Ocean e foi instalado usando o procedimento padrão.

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

Receio que não haja muito mais que eu possa fazer para diagnosticar isso sem acesso ao servidor. Temos muitas pessoas usando o plugin oauth2 sem problemas, então acho que isso deve ser um problema de configuração em algum lugar. A única outra coisa que pode ajudar é atualizar para a versão mais recente do Discourse, em vez de usar a branch estável.

Talvez alguém mais da comunidade se manifeste, mas se não, você pode ter sucesso pedindo ajuda no Marketplace.