Problème CSRF en développement avec le plugin 'Discourse OpenID Connect'

I spent five or six weeks setting up Discourse’s SSO, and encountered some problems during this period. Now there is a problem that is blocking me. I will record this problem in as much detail as possible.

Development environment

  • ubuntu22 on vmware
  • discourse 3.2.0.beta2-dev
    • server runs on 127.0.0.1:3000
    • ember-cli runs on 127.0.0.1:4200
    • Install Discourse on Ubuntu or Debian for Development
    • disabled plugins
      • presence
      • chat
      • narrative bot
    • Use plug-in Discourse OpenID Connect to connect kecloak based on OIDC, keycloak as the identity provider of discourse
      • OIDC connection configuration on Discourse OpenID Connect
        • openid connect discovery document: http://127.0.0.1:8080/realms/mediawiki-realm/.well-known/openid-configuration
        • openid connect client id: mydiscourse
        • openid connect client secret: O9A8zQuOn1bfpsWD89U8ULwYf6ooDu73
  • sso provider keycloak 22.0.4
    • runs on 127.0.0.1:8080
    • OIDC connection configuration on keycloak
      • Valid redirect URIs: http://127.0.0.1:3000/auth/oidc/callback
      • Client secret: O9A8zQuOn1bfpsWD89U8ULwYf6ooDu73
  • chrome version 118.0.5993.70

Reproduction process

Log in with OIDC

image

Discourse redirects to keycloak, enter user information in keycloak

CSRF

Logs


//

//

//

// Application Trace

lib/middleware/omniauth_bypass_middleware.rb:53:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/gtm_script_nonce_injector.rb:10:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
lib/middleware/missing_avatars.rb:22:in `call'
lib/middleware/turbo_dev.rb:31:in `call'

// Framework Trace

omniauth (1.9.2) lib/omniauth/failure_endpoint.rb:25:in `raise_out!'
omniauth (1.9.2) lib/omniauth/failure_endpoint.rb:20:in `call'
omniauth (1.9.2) lib/omniauth/failure_endpoint.rb:12:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:491:in `fail!'
/home/hardway/Downloads/omniauth-oauth2/lib/omniauth/strategies/oauth2.rb:88:in `callback_phase'
plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb:142:in `callback_phase'
omniauth (1.9.2) lib/omniauth/strategy.rb:238:in `callback_call'
omniauth (1.9.2) lib/omniauth/strategy.rb:189:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/builder.rb:45:in `call'
rack (2.2.8) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.8) lib/rack/conditional_get.rb:27:in `call'
rack (2.2.8) lib/rack/head.rb:12:in `call'
actionpack (7.0.7) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
rack (2.2.8) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.8) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/cookies.rb:704:in `call'
activerecord (7.0.7) lib/active_record/migration.rb:603:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (7.0.7) lib/active_support/callbacks.rb:99:in `run_callbacks'
actionpack (7.0.7) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/debug_exceptions.rb:28:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/show_exceptions.rb:29:in `call'
logster (2.13.0) lib/logster/middleware/reporter.rb:40:in `call'
railties (7.0.7) lib/rails/rack/logger.rb:40:in `call_app'
railties (7.0.7) lib/rails/rack/logger.rb:27:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/remote_ip.rb:93:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/request_id.rb:26:in `call'
rack (2.2.8) lib/rack/method_override.rb:24:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/static.rb:23:in `call'
rack (2.2.8) lib/rack/sendfile.rb:110:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/host_authorization.rb:137:in `call'
rack-mini-profiler (3.1.1) lib/mini_profiler.rb:413:in `call'
message_bus (4.3.8) lib/message_bus/rack/middleware.rb:60:in `call'
railties (7.0.7) lib/rails/engine.rb:530:in `call'
railties (7.0.7) lib/rails/railtie.rb:226:in `public_send'
railties (7.0.7) lib/rails/railtie.rb:226:in `method_missing'
rack (2.2.8) lib/rack/urlmap.rb:74:in `block in call'
rack (2.2.8) lib/rack/urlmap.rb:58:in `each'
rack (2.2.8) lib/rack/urlmap.rb:58:in `call'
unicorn (6.1.0) lib/unicorn/http_server.rb:634:in `process_client'
unicorn (6.1.0) lib/unicorn/http_server.rb:739:in `worker_loop'
unicorn (6.1.0) lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
unicorn (6.1.0) lib/unicorn/http_server.rb:143:in `start'
unicorn (6.1.0) bin/unicorn:128:in `<top (required)>'
bin/unicorn:96:in `load'
bin/unicorn:96:in `block in <main>'
bin/unicorn:95:in `fork'
bin/unicorn:95:in `<main>'

// Full Trace

omniauth (1.9.2) lib/omniauth/failure_endpoint.rb:25:in `raise_out!'
omniauth (1.9.2) lib/omniauth/failure_endpoint.rb:20:in `call'
omniauth (1.9.2) lib/omniauth/failure_endpoint.rb:12:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:491:in `fail!'
/home/hardway/Downloads/omniauth-oauth2/lib/omniauth/strategies/oauth2.rb:88:in `callback_phase'
plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb:142:in `callback_phase'
omniauth (1.9.2) lib/omniauth/strategy.rb:238:in `callback_call'
omniauth (1.9.2) lib/omniauth/strategy.rb:189:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/strategy.rb:192:in `call!'
omniauth (1.9.2) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.2) lib/omniauth/builder.rb:45:in `call'
lib/middleware/omniauth_bypass_middleware.rb:53:in `call'
rack (2.2.8) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.8) lib/rack/conditional_get.rb:27:in `call'
rack (2.2.8) lib/rack/head.rb:12:in `call'
actionpack (7.0.7) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/gtm_script_nonce_injector.rb:10:in `call'
rack (2.2.8) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.8) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/cookies.rb:704:in `call'
activerecord (7.0.7) lib/active_record/migration.rb:603:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (7.0.7) lib/active_support/callbacks.rb:99:in `run_callbacks'
actionpack (7.0.7) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/debug_exceptions.rb:28:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/show_exceptions.rb:29:in `call'
logster (2.13.0) lib/logster/middleware/reporter.rb:40:in `call'
railties (7.0.7) lib/rails/rack/logger.rb:40:in `call_app'
railties (7.0.7) lib/rails/rack/logger.rb:27:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/remote_ip.rb:93:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/request_id.rb:26:in `call'
rack (2.2.8) lib/rack/method_override.rb:24:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/static.rb:23:in `call'
rack (2.2.8) lib/rack/sendfile.rb:110:in `call'
actionpack (7.0.7) lib/action_dispatch/middleware/host_authorization.rb:137:in `call'
lib/middleware/missing_avatars.rb:22:in `call'
lib/middleware/turbo_dev.rb:31:in `call'
rack-mini-profiler (3.1.1) lib/mini_profiler.rb:413:in `call'
message_bus (4.3.8) lib/message_bus/rack/middleware.rb:60:in `call'
railties (7.0.7) lib/rails/engine.rb:530:in `call'
railties (7.0.7) lib/rails/railtie.rb:226:in `public_send'
railties (7.0.7) lib/rails/railtie.rb:226:in `method_missing'
rack (2.2.8) lib/rack/urlmap.rb:74:in `block in call'
rack (2.2.8) lib/rack/urlmap.rb:58:in `each'
rack (2.2.8) lib/rack/urlmap.rb:58:in `call'
unicorn (6.1.0) lib/unicorn/http_server.rb:634:in `process_client'
unicorn (6.1.0) lib/unicorn/http_server.rb:739:in `worker_loop'
unicorn (6.1.0) lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
unicorn (6.1.0) lib/unicorn/http_server.rb:143:in `start'
unicorn (6.1.0) bin/unicorn:128:in `<top (required)>'
bin/unicorn:96:in `load'
bin/unicorn:96:in `block in <main>'
bin/unicorn:95:in `fork'
bin/unicorn:95:in `<main>'

Possible reason

The guidance or tips I want to get

  • How authentication in discourse works?
  • How discourse uses session?
  • Discourse messaging mechanism
  • It would be best if you could tell me the solution directly

Peut-être sans rapport, mais est-ce que la définition des URI de redirection valides à http://127.0.0.1:4200/auth/oidc/callback fait une différence ?

De plus, il y a actuellement quelque chose d’étrange qui se passe dans l’environnement de développement Ubuntu/Debian où le site est accessible soit à localhost:4200, soit à 127.0.0.1:4200. Chacun de ces domaines crée une session distincte. Probablement pas lié à votre problème, mais peut-être quelque chose qui pourrait causer des problèmes pour le développement local. J’utilise toujours le domaine localhost:4200. Cela semble être ce qui est attendu.

2 « J'aime »

Oui, ce serait ma première idée aussi. Il est important que le flux d’authentification commence et se termine sur le même port, sinon la session peut être différente.

Si vous démarrez Rails et Ember-CLI ensemble via bin/ember-cli -u, tout sera automatiquement configuré pour vous. Mais si vous les démarrez séparément, assurez-vous de définir l’environnement DISCOURSE_PORT=4200 sur le serveur Rails afin que tout s’aligne correctement.

2 « J'aime »

J’ai essayé, mais « Paramètre non valide : redirect_uri » apparaît dans Keycloak.

Démarrez Rails et Ember-CLI ensemble via bin/ember-cli -u

Définissez les URI de redirection valides sur http://127.0.0.1:4200/auth/oidc/callback.

Il semble que la cause soit un écart entre les URI de redirection valides dans Keycloak et les URI représentés dans l’illustration suivante.

L’URI représenté dans l’image est

http://127.0.0.1:8080/realms/mediawiki-realm/protocol/openid-connect/auth?client_id=mydiscourse&nonce=dce3dd8bccb09b25f88d1645d26b9d20b58e3d2ff3804f83ed79098c793a5ae2&redirect_uri=http%3A%2F%2F127.0.0.1%3A3000%2Fauth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email&state=7fd712dd2b28c8264eac170721b898b26ae8fb2edb9a2e9f

Après décodage du ‘redirect_uri’, son équivalence avec

http://127.0.0.1:3000/auth/oidc/callback

Quel devrait être, en effet, le bon redirect_uri ?

Auriez-vous l’obligeance de divulguer la plateforme utilisée pour la vérification d’identité lors de la création de ce plugin ?

Merci, ça fonctionne. :blush:
Ma solution de contournement a été d’ouvrir discourse en utilisant 127.0.0.1:4200 au lieu de localhost:4200.

2 « J'aime »

Je ne le recommande pas, mais pour le développement local, j’ai adopté l’approche quelque peu brutale consistant à modifier la méthode callback_url du plugin : discourse-openid-connect/lib/omniauth_open_id_connect.rb at main · discourse/discourse-openid-connect · GitHub.

     def callback_url
        full_host = 'http://localhost:4200'
        full_host + script_name + callback_path
      end

De cette façon, il renvoie toujours http://localhost:4200/auth/oidc/callback

Sans cette modification, je n’ai trouvé aucun moyen de faire en sorte que la partie hôte de l’URL soit autre chose que http://127.0.0.1:3000.

1 « J'aime »

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.