noirbizarre / flask-restplus

Fully featured framework for fast, easy and documented API development with Flask
http://flask-restplus.readthedocs.org
Other
2.73k stars 506 forks source link

Support csrf-tokens for swagger-ui - optionally #411

Open warwing opened 6 years ago

warwing commented 6 years ago

Hello together,

I'm using flask-restplus together with flask-wtf and it's csrf-protection. Generally it works like a charm - but the swagger-ui doesn't support the csrf tokens.

I've seen the pull-request #213 and tried to apply it to the lastest release 0.10.1. If I patch the installed release inside of my virtual environment, everything works. But if I try to apply my patch to the source and build a release from it, I'm getting strange errors (.css and .js files will no longer be found).

I tried to follow the contribution guide, but after installing dev dependencies (pip install -e .[dev]), the tests are not running (inv test) - even with the unchanged sources checked out from tag 0.10.1!

When I try to install the release (inv dist), I'm facing the following errors:

` 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/css/typography.css HTTP/1.1" 404 -

127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/css/reset.css HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/css/screen.css HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/object-assign-pollyfill.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/jquery-1.8.0.min.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/jquery.slideto.min.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/jquery.wiggle.min.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/jquery.ba-bbq.min.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/handlebars-4.0.5.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/lodash.min.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/backbone-min.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/swagger-ui.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/highlight.9.1.0.pack.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/highlight.9.1.0.pack_extended.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:03] "GET /swaggerui/bower/swagger-ui/dist/lib/jsoneditor.min.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:04] "GET /swaggerui/bower/swagger-ui/dist/lib/marked.js HTTP/1.1" 404 - 127.0.0.1 - - [22/Mar/2018 21:11:04] "GET /swaggerui/bower/swagger-ui/dist/lib/swagger-oauth.js HTTP/1.1" 404 - `

Does somebody have an idea, what I could do wrong?

My dev-environment is a docker container with the following Dockerfile: ` FROM python:3.6-stretch

In this directory I'm mounting my local sources:

RUN mkdir /project_root VOLUME ["/project_root"] WORKDIR /project_root `

warwing commented 6 years ago

I tried to enhance the pull request to only depend optionally to flask-wtf:

diff --git a/flask_restplus/templates/swagger-ui.html b/flask_restplus/templates/swagger-ui.html
index 18a40ea..a980fc1 100644
--- a/flask_restplus/templates/swagger-ui.html
+++ b/flask_restplus/templates/swagger-ui.html
@@ -1,6 +1,9 @@
 <!DOCTYPE html>
 <html>
 <head>
+    {% if config.WTF_CSRF_ENABLED %}
+    <meta name="csrf-token" content="{{ csrf_token() }}">
+    {% endif %}
     <title>{{ title }}</title>
     {% include 'swagger-ui-css.html' %}
     {% include 'swagger-ui-libs.html' %}
@@ -23,6 +26,18 @@
                 validatorUrl: "{{ config.SWAGGER_VALIDATOR_URL }}" || null,
                 dom_id: "swagger-ui-container",
                 supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
+                {% if config.WTF_CSRF_ENABLED %}
+                authorizations: {
+                    csrfInterceptor: function() {
+                        // This function will get called /before/ each request
+                        // ... UNLESS you have a 'security' tag in the swagger.json file, 
+                        // ... in which case you must add 'csrfInterceptor' to the list of auths.
+                        var csrftoken = $('meta[name=csrf-token]').attr('content')
+                        this.headers['X-CSRFToken'] = csrftoken; 
+                        return true; 
+                    }
+                },
+                {% endif %}
                 onComplete: function(swaggerApi, swaggerUi){
                     if(typeof initOAuth == "function") {
                         {% if config.SWAGGER_UI_OAUTH_CLIENT_ID -%}

All changes