From 08c8ac8ffa4d214c548a1b2cb2a2528613dadcf2 Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Tue, 13 Aug 2019 13:20:03 -0400 Subject: [PATCH 1/8] allow for swagger oauth redirect --- flask_rest_api/spec/__init__.py | 10 +++ flask_rest_api/spec/templates/swagger_ui.html | 1 + .../spec/templates/swagger_ui_redirect.html | 67 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 flask_rest_api/spec/templates/swagger_ui_redirect.html diff --git a/flask_rest_api/spec/__init__.py b/flask_rest_api/spec/__init__.py index 8f4a5a9d..c93a4b50 100644 --- a/flask_rest_api/spec/__init__.py +++ b/flask_rest_api/spec/__init__.py @@ -123,6 +123,10 @@ def _register_swagger_ui_rule(self, blueprint): _add_leading_slash(swagger_ui_path), endpoint='openapi_swagger_ui', view_func=self._openapi_swagger_ui) + blueprint.add_url_rule( + _add_leading_slash('{}/oauth2-redirect'.format(swagger_ui_path)), + endpoint='openapi_swagger_ui_redirect', + view_func=self._openapi_swagger_ui_redirect) def _openapi_json(self): """Serve JSON spec file""" @@ -146,6 +150,12 @@ def _openapi_swagger_ui(self): self._swagger_ui_supported_submit_methods) ) + def _openapi_swagger_ui_redirect(self): + """Expose OpenAPI spec with Swagger UI""" + return flask.render_template( + 'swagger_ui_redirect.html' + ) + class APISpecMixin(DocBlueprintMixin): """Add APISpec related features to Api class""" diff --git a/flask_rest_api/spec/templates/swagger_ui.html b/flask_rest_api/spec/templates/swagger_ui.html index 06ed47a8..d6df6bab 100644 --- a/flask_rest_api/spec/templates/swagger_ui.html +++ b/flask_rest_api/spec/templates/swagger_ui.html @@ -15,6 +15,7 @@ \ No newline at end of file From 930fdb64e5b1a8a438d1fcbf0988027d0ac0a16e Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Tue, 13 Aug 2019 14:29:08 -0400 Subject: [PATCH 2/8] linting changes --- flask_rest_api/spec/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flask_rest_api/spec/__init__.py b/flask_rest_api/spec/__init__.py index c93a4b50..4646c12f 100644 --- a/flask_rest_api/spec/__init__.py +++ b/flask_rest_api/spec/__init__.py @@ -124,7 +124,9 @@ def _register_swagger_ui_rule(self, blueprint): endpoint='openapi_swagger_ui', view_func=self._openapi_swagger_ui) blueprint.add_url_rule( - _add_leading_slash('{}/oauth2-redirect'.format(swagger_ui_path)), + _add_leading_slash( + '{}/oauth2-redirect'.format(swagger_ui_path) + ), endpoint='openapi_swagger_ui_redirect', view_func=self._openapi_swagger_ui_redirect) From b368172476c9df1d2d77619336534b40e02eac82 Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Tue, 13 Aug 2019 16:38:07 -0400 Subject: [PATCH 3/8] updates to remotely pull template, add documentation --- docs/openapi.rst | 31 +++++++++ flask_rest_api/spec/__init__.py | 35 ++++++++-- .../spec/templates/swagger_ui_redirect.html | 67 ------------------- 3 files changed, 62 insertions(+), 71 deletions(-) delete mode 100644 flask_rest_api/spec/templates/swagger_ui_redirect.html diff --git a/docs/openapi.rst b/docs/openapi.rst index 9e32c5b4..30f9d2e3 100644 --- a/docs/openapi.rst +++ b/docs/openapi.rst @@ -149,6 +149,36 @@ Documentation components can be passed by accessing the internal apispec {'description': 'Item ID', 'format': 'int32', 'required': True} ) +Use Swagger OAuth2 Authentication +--------------------------------- + +Swagger can automatically redirect to OAuth2 URLs and retrieve a token for use as an Authentication Header. See the `Swagger OAuth2 Docs`_ for more information. Your redirect to supply to your OAuth provider will be ``{HOST}://{OPENAPI_URL_PREFIX}/{OPENAPI_SWAGGER_UI_PATH}/oauth2-redirect``. You can also specify the template URL for the redirect page directly with the ``SWAGGER_OAUTH_REDIRECT_TEMPLATE_URL`` config property. If not specified, it will default to ``https://raw.githubusercontent.com/swagger-api/swagger-ui/master/dist/oauth2-redirect.html``. The code below is an example of what should be supplied as config to app in order to activate this feature. + +.. code-block:: python + + app.config['API_SPEC_OPTIONS'] = {'components': + { + 'securitySchemes': { + }, + 'OAuth2': { + 'type': 'oauth2', + 'flows': { + 'implicit': { + 'authorizationUrl': self.AUTHORIZATION_URL, + 'scopes': { + 'openid': 'openid token' + } + } + } + } + } + }, + 'security': [{ + 'OAuth2': [] + }] + } + + Register Custom Fields ---------------------- @@ -276,3 +306,4 @@ number. .. _ReDoc: https://github.com/Rebilly/ReDoc .. _Swagger UI: https://swagger.io/tools/swagger-ui/ +.. _Swagger OAuth2 Docs: https://swagger.io/docs/specification/authentication/oauth2/ diff --git a/flask_rest_api/spec/__init__.py b/flask_rest_api/spec/__init__.py index 4646c12f..0c9ba3c2 100644 --- a/flask_rest_api/spec/__init__.py +++ b/flask_rest_api/spec/__init__.py @@ -10,6 +10,9 @@ from flask_rest_api.exceptions import OpenAPIVersionNotSpecified from .plugins import FlaskPlugin +from urllib.request import urlopen +from urllib.parse import urljoin + def _add_leading_slash(string): """Add leading slash to a string if there is None""" @@ -19,6 +22,24 @@ def _add_leading_slash(string): class DocBlueprintMixin: """Extend Api to serve the spec in a dedicated blueprint.""" + + def _get_swagger_ui_oauth_redirect_template(self): + swagger_ui_version = self._app.config.get( + 'OPENAPI_SWAGGER_UI_VERSION', 'master') + + url = self._app.config.get('SWAGGER_OAUTH_REDIRECT_TEMPLATE_URL', + 'https://raw.githubusercontent.com/swagger-api/swagger-ui/' + \ + '{version}/dist/oauth2-redirect.html'.format( + version=swagger_ui_version + ) + ) + try: + t = urlopen(url) + if t.getcode() is None or t.getcode() == 200: + return t.read().decode('utf-8') + except IOError: + pass + def _register_doc_blueprint(self): """Register a blueprint in the application to expose the spec @@ -44,6 +65,7 @@ def _register_doc_blueprint(self): self._register_redoc_rule(blueprint) self._register_swagger_ui_rule(blueprint) self._app.register_blueprint(blueprint) + self.template_body = self._get_swagger_ui_oauth_redirect_template() def _register_redoc_rule(self, blueprint): """Register ReDoc rule @@ -153,10 +175,15 @@ def _openapi_swagger_ui(self): ) def _openapi_swagger_ui_redirect(self): - """Expose OpenAPI spec with Swagger UI""" - return flask.render_template( - 'swagger_ui_redirect.html' - ) + """Expose OpenAPI redirect url with Swagger UI""" + template_response = "" + try: + template_response = flask.render_template_string( + self.template_body + ) + except Exception as e: + pass + return template_response class APISpecMixin(DocBlueprintMixin): diff --git a/flask_rest_api/spec/templates/swagger_ui_redirect.html b/flask_rest_api/spec/templates/swagger_ui_redirect.html deleted file mode 100644 index 4ced53b0..00000000 --- a/flask_rest_api/spec/templates/swagger_ui_redirect.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - \ No newline at end of file From 831ac3efea4225dc0fbcdd78a08397e151bc9b22 Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Tue, 13 Aug 2019 16:45:18 -0400 Subject: [PATCH 4/8] linting improvements --- flask_rest_api/spec/__init__.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/flask_rest_api/spec/__init__.py b/flask_rest_api/spec/__init__.py index 0c9ba3c2..677eadd3 100644 --- a/flask_rest_api/spec/__init__.py +++ b/flask_rest_api/spec/__init__.py @@ -11,7 +11,6 @@ from .plugins import FlaskPlugin from urllib.request import urlopen -from urllib.parse import urljoin def _add_leading_slash(string): @@ -22,17 +21,17 @@ def _add_leading_slash(string): class DocBlueprintMixin: """Extend Api to serve the spec in a dedicated blueprint.""" - def _get_swagger_ui_oauth_redirect_template(self): swagger_ui_version = self._app.config.get( 'OPENAPI_SWAGGER_UI_VERSION', 'master') url = self._app.config.get('SWAGGER_OAUTH_REDIRECT_TEMPLATE_URL', - 'https://raw.githubusercontent.com/swagger-api/swagger-ui/' + \ - '{version}/dist/oauth2-redirect.html'.format( - version=swagger_ui_version + 'https://raw.githubusercontent.com/' + # noqa: E128 + 'swagger-api/swagger-ui/' + # noqa: E128 + '{version}/dist/oauth2-redirect.html'.format( + version=swagger_ui_version + ) ) - ) try: t = urlopen(url) if t.getcode() is None or t.getcode() == 200: @@ -181,7 +180,7 @@ def _openapi_swagger_ui_redirect(self): template_response = flask.render_template_string( self.template_body ) - except Exception as e: + except Exception: pass return template_response From 6dbb590d5bafee1d10e072d1f90869e70259d663 Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Tue, 13 Aug 2019 16:49:43 -0400 Subject: [PATCH 5/8] additional documentation --- docs/openapi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/openapi.rst b/docs/openapi.rst index 30f9d2e3..711eefe7 100644 --- a/docs/openapi.rst +++ b/docs/openapi.rst @@ -152,7 +152,7 @@ Documentation components can be passed by accessing the internal apispec Use Swagger OAuth2 Authentication --------------------------------- -Swagger can automatically redirect to OAuth2 URLs and retrieve a token for use as an Authentication Header. See the `Swagger OAuth2 Docs`_ for more information. Your redirect to supply to your OAuth provider will be ``{HOST}://{OPENAPI_URL_PREFIX}/{OPENAPI_SWAGGER_UI_PATH}/oauth2-redirect``. You can also specify the template URL for the redirect page directly with the ``SWAGGER_OAUTH_REDIRECT_TEMPLATE_URL`` config property. If not specified, it will default to ``https://raw.githubusercontent.com/swagger-api/swagger-ui/master/dist/oauth2-redirect.html``. The code below is an example of what should be supplied as config to app in order to activate this feature. +Swagger can automatically redirect to OAuth2 URLs and retrieve a token for use as an Authentication Header. See the `Swagger OAuth2 Docs`_ for more information. Your redirect to supply to your OAuth provider will be ``{HOST}://{OPENAPI_URL_PREFIX}/{OPENAPI_SWAGGER_UI_PATH}/oauth2-redirect``. You can also specify the template URL for the redirect page directly with the ``SWAGGER_OAUTH_REDIRECT_TEMPLATE_URL`` config property. If not specified, it will default to ``https://raw.githubusercontent.com/swagger-api/swagger-ui/master/dist/oauth2-redirect.html``. An error in retrieving this will The code below is an example of what should be supplied as config to app in order to activate this feature. .. code-block:: python From 86e3b49bae29a1ea548feb4157c878e95f777497 Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Wed, 14 Aug 2019 12:15:26 -0400 Subject: [PATCH 6/8] latest changes based on feedback --- docs/openapi.rst | 3 +- flask_rest_api/spec/__init__.py | 35 ++-------- flask_rest_api/spec/templates/swagger_ui.html | 2 + .../spec/templates/swagger_ui_redirect.html | 67 +++++++++++++++++++ 4 files changed, 77 insertions(+), 30 deletions(-) create mode 100644 flask_rest_api/spec/templates/swagger_ui_redirect.html diff --git a/docs/openapi.rst b/docs/openapi.rst index 711eefe7..df350d69 100644 --- a/docs/openapi.rst +++ b/docs/openapi.rst @@ -152,7 +152,7 @@ Documentation components can be passed by accessing the internal apispec Use Swagger OAuth2 Authentication --------------------------------- -Swagger can automatically redirect to OAuth2 URLs and retrieve a token for use as an Authentication Header. See the `Swagger OAuth2 Docs`_ for more information. Your redirect to supply to your OAuth provider will be ``{HOST}://{OPENAPI_URL_PREFIX}/{OPENAPI_SWAGGER_UI_PATH}/oauth2-redirect``. You can also specify the template URL for the redirect page directly with the ``SWAGGER_OAUTH_REDIRECT_TEMPLATE_URL`` config property. If not specified, it will default to ``https://raw.githubusercontent.com/swagger-api/swagger-ui/master/dist/oauth2-redirect.html``. An error in retrieving this will The code below is an example of what should be supplied as config to app in order to activate this feature. +Swagger can automatically redirect to OAuth2 URLs and retrieve a token for use as an Authentication Header. See the `Swagger OAuth2 Docs`_ for more information. Your redirect to supply to your OAuth provider will be ``{HOST}://{OPENAPI_URL_PREFIX}/{OPENAPI_SWAGGER_UI_PATH}/oauth2-redirect``. The code below is an example of what should be supplied as config to app in order to activate this feature. .. code-block:: python @@ -177,6 +177,7 @@ Swagger can automatically redirect to OAuth2 URLs and retrieve a token for use a 'OAuth2': [] }] } + app.config['OPENAPI_SWAGGER_UI_ENABLE_OAUTH'] = True Register Custom Fields diff --git a/flask_rest_api/spec/__init__.py b/flask_rest_api/spec/__init__.py index 677eadd3..1b537ca0 100644 --- a/flask_rest_api/spec/__init__.py +++ b/flask_rest_api/spec/__init__.py @@ -10,8 +10,6 @@ from flask_rest_api.exceptions import OpenAPIVersionNotSpecified from .plugins import FlaskPlugin -from urllib.request import urlopen - def _add_leading_slash(string): """Add leading slash to a string if there is None""" @@ -21,24 +19,6 @@ def _add_leading_slash(string): class DocBlueprintMixin: """Extend Api to serve the spec in a dedicated blueprint.""" - def _get_swagger_ui_oauth_redirect_template(self): - swagger_ui_version = self._app.config.get( - 'OPENAPI_SWAGGER_UI_VERSION', 'master') - - url = self._app.config.get('SWAGGER_OAUTH_REDIRECT_TEMPLATE_URL', - 'https://raw.githubusercontent.com/' + # noqa: E128 - 'swagger-api/swagger-ui/' + # noqa: E128 - '{version}/dist/oauth2-redirect.html'.format( - version=swagger_ui_version - ) - ) - try: - t = urlopen(url) - if t.getcode() is None or t.getcode() == 200: - return t.read().decode('utf-8') - except IOError: - pass - def _register_doc_blueprint(self): """Register a blueprint in the application to expose the spec @@ -64,7 +44,6 @@ def _register_doc_blueprint(self): self._register_redoc_rule(blueprint) self._register_swagger_ui_rule(blueprint) self._app.register_blueprint(blueprint) - self.template_body = self._get_swagger_ui_oauth_redirect_template() def _register_redoc_rule(self, blueprint): """Register ReDoc rule @@ -169,20 +148,18 @@ def _openapi_swagger_ui(self): return flask.render_template( 'swagger_ui.html', title=self._app.name, swagger_ui_url=self._swagger_ui_url, + swagger_ui_enable_oauth=self._app.config.get( + 'OPENAPI_SWAGGER_UI_ENABLE_OAUTH', False), swagger_ui_supported_submit_methods=( self._swagger_ui_supported_submit_methods) ) def _openapi_swagger_ui_redirect(self): """Expose OpenAPI redirect url with Swagger UI""" - template_response = "" - try: - template_response = flask.render_template_string( - self.template_body - ) - except Exception: - pass - return template_response + return flask.render_template( + 'swagger_ui_redirect.html' + ) + class APISpecMixin(DocBlueprintMixin): diff --git a/flask_rest_api/spec/templates/swagger_ui.html b/flask_rest_api/spec/templates/swagger_ui.html index d6df6bab..cfec66fc 100644 --- a/flask_rest_api/spec/templates/swagger_ui.html +++ b/flask_rest_api/spec/templates/swagger_ui.html @@ -15,7 +15,9 @@ \ No newline at end of file From 551776545ac2ae9a08bd2204f025d060812c2b91 Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Wed, 14 Aug 2019 12:18:04 -0400 Subject: [PATCH 7/8] linting --- flask_rest_api/spec/__init__.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/flask_rest_api/spec/__init__.py b/flask_rest_api/spec/__init__.py index 1b537ca0..de2a2165 100644 --- a/flask_rest_api/spec/__init__.py +++ b/flask_rest_api/spec/__init__.py @@ -123,12 +123,16 @@ def _register_swagger_ui_rule(self, blueprint): _add_leading_slash(swagger_ui_path), endpoint='openapi_swagger_ui', view_func=self._openapi_swagger_ui) - blueprint.add_url_rule( - _add_leading_slash( - '{}/oauth2-redirect'.format(swagger_ui_path) - ), - endpoint='openapi_swagger_ui_redirect', - view_func=self._openapi_swagger_ui_redirect) + if (self._app.config.get( + 'OPENAPI_SWAGGER_UI_ENABLE_OAUTH', False)): + blueprint.add_url_rule( + _add_leading_slash( + '{}/oauth2-redirect'.format( + swagger_ui_path + ) + ), + endpoint='openapi_swagger_ui_redirect', + view_func=self._openapi_swagger_ui_redirect) def _openapi_json(self): """Serve JSON spec file""" @@ -161,7 +165,6 @@ def _openapi_swagger_ui_redirect(self): ) - class APISpecMixin(DocBlueprintMixin): """Add APISpec related features to Api class""" From faaf8723386db7dad7ef397b254228eb2a5bd407 Mon Sep 17 00:00:00 2001 From: Vince Montalbano Date: Wed, 14 Aug 2019 15:35:33 -0400 Subject: [PATCH 8/8] change evaluation of true statement --- flask_rest_api/spec/templates/swagger_ui.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flask_rest_api/spec/templates/swagger_ui.html b/flask_rest_api/spec/templates/swagger_ui.html index cfec66fc..e8f5ec62 100644 --- a/flask_rest_api/spec/templates/swagger_ui.html +++ b/flask_rest_api/spec/templates/swagger_ui.html @@ -15,7 +15,7 @@