mattermost-community/mattermost-plugin-skype4business

Include CSRF token in webapp’s API requests

Closed this issue · 7 comments

When a plugin’s webapp makes an API request to the Mattermost server, it needs to include the CSRF token supplied by the server in its request. This can be done using the getOptions function exported by the mattermost-redux library. Here is some example usage

https://github.com/mattermost/mattermost-plugin-jira/blob/ae5676ead0e9effca29d2948c6596f42cf6e35c1/webapp/src/client/index.js#L13-L18

The task here is to convert all API requests done by the plugin’s Client to use the token. The import statement import request from 'superagent' should be removed, and favor using fetch instead, as shown in the example usage linked above.

Plugin mattermost/mattermost-plugin-gitlab seems to have the same problem:

Processing by Gitlab::RequestForgeryProtection::Controller#index as JSON
  Parameters: {"channel_id"=>"<redacted>", "channel_name"=>"server-config", "command"=>"/gitlab-test", "response_url"=>"https://x.xxx.xxx/hooks/commands/<redacted>", "team_domain"=>"<redacted>", "team_id"=>"<redacted>", "text"=>"[FILTERED]", "token"=>"[FILTERED]", "trigger_id"=>"YjdmZG54bjEzZm5leGRuZ2RhNHNkNnV4Y2U6ZjdoenBqcm9xM25mdGVzdG5oZzN3cGppenk6MTU5MTQzNjE1NDI4MTpNRVVDSUJ2VFZpb1VUK2tDT3h4UE9janY3RHZVWFhpd0RWUldzaURkZ3RxdCtuWmpBaUVBaDY5cHBMdW9taVNSa04yY2R2ZzIwYTFnVlhPbllrWVc0bUdHMFV3NVdaQT0=", "user_id"=>"<redacted>", "user_name"=>"<redacted>"}
Can't verify CSRF token authenticity.
This CSRF token verification failure is handled internally by `GitLab::RequestForgeryProtection`
Unlike the logs may suggest, this does not result in an actual 422 response to the user
For API requests, the only effect is that `current_user` will be `nil` for the duration of the request
Completed 422 Unprocessable Entity in 0ms (ActiveRecord: 0.0ms | Elasticsearch: 0.0ms | Allocations: 233)

NameError (undefined local variable or method `footer' for #<Gitlab::SlashCommands::Presenters::Help:0x00007f90d1a812e0>):
  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/slash_commands/presenters/help.rb:24:in `help_message'
  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/slash_commands/presenters/help.rb:13:in `present'
  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/slash_commands/help.rb:24:in `execute'
  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/slash_commands/command.rb:30:in `execute'
  /opt/gitlab/embedded/service/gitlab-rails/app/models/project_services/slash_commands_service.rb:45:in `trigger'
  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/instrumentation.rb:161:in `block in trigger'
  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/method_call.rb:36:in `measure'
  /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/metrics/instrumentation.rb:161:in `trigger'
  /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3/lib/active_support/core_ext/object/try.rb:15:in `public_send'
  /opt/gitlab/embedded/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3/lib/active_support/core_ext/object/try.rb:15:in `try'
  /opt/gitlab/embedded/service/gitlab-rails/lib/api/services.rb:159:in `block (3 levels) in <class:Services>'

As a result, mattermost shows an error message, when running the slash command:
Command with a trigger of 'gitlab-test' returned response 500 Internal Server Error.

@fleXible Although the gitlab plugin does also need the update specified in this ticket, the error you provided is for a different kind of issue. It appears that it is for a CSRF token that gitlab is expecting, rather than the mattermost server.

Also the gitlab-test command does not have anything to do with the gitlab plugin. Are your creating your own slash command to hit gitlab's API?

@mickmister To me it looked the same, but you are right, I was trying to create a custom slash command, just to see what it is. But this part of the plugin seems to be broken.

@fleXible This looks an error that your rails server handling the slash command is throwing.

If your rails server is just going to be JSON based, then you can use ActionController::API as your ApplicationController. This will make it so no CSRF token checking will occur:

class ApplicationController < ActionController::API

Otherwise, you can skip the verify_authenticity_token action in your appropriate controllers:

skip_before_action :verify_authenticity_token

@mickmister Thanks for the quick reply, this is coming straight out of Gitlab 13.0.5.
I don't have a hand in that. But I think I see the problem. Gitlab uses a method called footer in the template, that doesn't exist. It's probably supposed to be help_footer
https://gitlab.com/gitlab-org/.../help.rb#L24

@fleXible Got it. Strange that they are expecting a CSRF token in a non-browser context. Does it mention the token anywhere in the slash command setup docs? Also, interesting that GitLab is written in Rails. Never would have thought of that.

@mickmister I think, the CSRF message is misleading, the actual error is the missing footer method used in the template. Just out of curiosity, I changed the it into help_footer in my docker instance, restarted and since then the help message is actually working :)

I just opened the issue #221052 in gitlab