flasgger / flasgger

Easy OpenAPI specs and Swagger UI for your Flask API
http://flasgger.pythonanywhere.com/
MIT License
3.63k stars 524 forks source link

Is there away to protect the "/apidocs" page? #381

Closed informatica92 closed 4 years ago

informatica92 commented 4 years ago

Hi all, currently I am developing an API application that will be deployed on Google Cloud App Engine. For this reason it would be a bood idea to "protect" behind authentication or just a password, the documentation page so that only the authorized users can access and read it.

Is there a way to do this at the moment?

joeystevens00 commented 4 years ago

The swagger_ui boolean setting in config will allow you to disable the apidocs view. Providing a config setting currently overrides the default though so you need to provide a full config object like so:

swagger = Swagger(app,  config={
    "headers": [
    ],
    "specs": [
        {
            "endpoint": 'apispec_1',
            "route": '/apispec_1.json',
            "rule_filter": lambda rule: True,  # all in
            "model_filter": lambda tag: True,  # all in
        }
    ],
    "static_url_path": "/flasgger_static",
    "swagger_ui": False,
})
informatica92 commented 4 years ago

But in this way the ui becomes inaccessible at all. My idea is only to limit the access to that endpoint, not disable it completely

mirecl commented 4 years ago

Hi, you can use auth decorator for route apidocs

informatica92 commented 4 years ago

Thank you @mirecl for your suggestion. I had a look to this possibility and I found that flasgger supports decorators. so I simply did this:

  1. I changed swagger init from Swagger(app, template=app.config['SWAGGER']) to Swagger(app, decorators=[basic_auth_decorator], template=app.config['SWAGGER']) (I added the decorators parameter)
  2. I created the basic_auth_decorator to handle the authentication

The basic_auth_decorator is:

from flask import current_app as app, request
from functools import wraps

def basic_auth_decorator(f):
    """Decorator to require HTTP Basic Auth for your endpoint."""

    def check_auth(username, password):
        return username == app.config['ADMIN_USERNAME'] and password == app.config['ADMIN_PASSWORD']

    def authenticate():
        return Response("Authentication required.", 401, {"WWW-Authenticate": "Basic realm='Login Required'"})

    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            return authenticate()
        return f(*args, **kwargs)

    return decorated

please have a look to the basic_auth.py example in the examples directory for more details

informatica92 commented 4 years ago

It would be nice anyway (since most of the code would be the same for all the applications) to add this feature inside flasgger by default. In this case I'd only pass username and password to the Swagger constructor in order to activate authentication for the flasgger endpoints