question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[QUESTION] Protect API docs behind authentication?

See original GitHub issue

Basic Question

Does FastAPI provide a method for implementing authentication middleware or similar on the docs themselves (e.g. to protect access to /docs and /redoc)?

Additional context

My company is currently relying on a needlessly-complex Django backend, whose main purpose is serving an API via the Django REST framework. However, it feels like half the bugs the frontend app folks are running into are caused by a disconnect between what the Django app is doing and the API documentation wiki (which is maintained by hand; it’s a monster).

FastAPI thus looks like a perfect alternative. However, it’s a requirement for us that the API documentation only be accessible to specific authenticated users. It looks like I could easily disable the docs when run in a production environment (as opposed to a local testing environment), but if it’s possible to serve the docs on production but explicitly protect them that would be ideal (the API in part facilitates interaction between frontend apps and IOT devices, so the interactive portions of the docs would be a lot easier to use and maintain on specific hosted servers; setting up working local environments is complicated).

In my ideal world, I’d love to also auto-populate the initial authentication credentials for the interactive queries with the current user’s authentication token (to allow no-configuration usage of them immediately upon access). I wasn’t able to find anything in the FastAPI docs about meddling with the way the documentation is handled, but if I missed it I’d love a link!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:13 (3 by maintainers)

github_iconTop GitHub Comments

63reactions
EasonC13commented, Mar 3, 2021

Hi there, I just find an easy solution to this question.

You can simply disable default /docs and create docs behind authentication

Example code:

from fastapi import FastAPI

from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.openapi.utils import get_openapi

import secrets

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials

app = FastAPI(docs_url=None, redoc_url=None, openapi_url = None)

security = HTTPBasic()


def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
    correct_username = secrets.compare_digest(credentials.username, "user")
    correct_password = secrets.compare_digest(credentials.password, "password")
    if not (correct_username and correct_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect email or password",
            headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username


@app.get("/docs")
async def get_documentation(username: str = Depends(get_current_username)):
    return get_swagger_ui_html(openapi_url="/openapi.json", title="docs")


@app.get("/openapi.json")
async def openapi(username: str = Depends(get_current_username)):
    return get_openapi(title = "FastAPI", version="0.1.0", routes=app.routes)

34reactions
kennylajaracommented, Aug 2, 2021

Pro tips

Using ReDoc If you prefer ReDoc, you can use it just replacing get_swagger_ui_html by get_redoc_html… Or you can use both…

Hiding those endpoints You are adding 2 new endpoints to your API and, almost for sure, it won’t be very useful to show them in your documentation. You can hide them by including the parameter include_in_schema=False to the @app.get( ... ) decorators.

A small improvement for code mantainance It might be a bit better to define the title and version in the inside of app = FastAPI( ... ) and use:

return get_openapi(title=app.title, version=app.version, routes=app.routes)

instead of

return get_openapi(title = "FastAPI", version="0.1.0", routes=app.routes)

This way, every-time you change the version (or if you need to change the title in the future), you can do it where you would normally do it and you won’t have to remember where is that defined. Save time for the future you.

Final code After does changes, this would be the final code:

from fastapi import FastAPI

from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
from fastapi.openapi.utils import get_openapi

import secrets

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials

app = FastAPI(
    title="FastAPI",
    version="0.1.0",
    docs_url=None,
    redoc_url=None,
    openapi_url = None,
)

security = HTTPBasic()


def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
    correct_username = secrets.compare_digest(credentials.username, "user")
    correct_password = secrets.compare_digest(credentials.password, "password")
    if not (correct_username and correct_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect email or password",
            headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username


@app.get("/docs", include_in_schema=False)
async def get_swagger_documentation(username: str = Depends(get_current_username)):
    return get_swagger_ui_html(openapi_url="/openapi.json", title="docs")


@app.get("/redoc", include_in_schema=False)
async def get_redoc_documentation(username: str = Depends(get_current_username)):
    return get_redoc_html(openapi_url="/openapi.json", title="docs")


@app.get("/openapi.json", include_in_schema=False)
async def openapi(username: str = Depends(get_current_username)):
    return get_openapi(title=app.title, version=app.version, routes=app.routes

Final words: Just remember this is an example and you still need to connect this small authentication code to your real login system or, at least, use environment variables. If you are protecting your API documentation, just don’t hard code your credentials…

Read more comments on GitHub >

github_iconTop Results From Across the Web

Best practices for REST API security: Authentication and ...
If you have a REST API accessible on the internet, you're going to need to secure it. Here's the best practices on how...
Read more >
Put the Web Api Documentation behind a login page so that ...
We want to authenticate the help pages (which are implemented in MVC). The question here is my web api uses basic authentication and...
Read more >
API authentication and authorization - Idratherbewriting.com
What to document with authentication ... In API documentation, you don't need to explain how your authentication works in detail to outside users....
Read more >
Security - First Steps - FastAPI
The password flow¶ · But it needs authentication for that specific endpoint. · So, to authenticate with our API, it sends a header...
Read more >
API Keys: API Authentication Methods & Examples
“How am I going to keep this secure?” is a crucial question when building any piece of software. This question is especially critical...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found