Safeguard
Developer Tools•

How do you require auth on every FastAPI route?

Pass an auth dependency to FastAPI(dependencies=[...]) or to an APIRouter so every route inherits it. Why that beats adding it per route, and what to test.

Safeguard Security Team
3 min read

Pass your authentication dependency to FastAPI(dependencies=[Depends(...)]) so it applies to every path operation in the app, or to an APIRouter to cover one group. Per route dependencies are easy to forget. A global or router level dependency makes protection the default and gives a scan fewer anonymous routes to find.

What the documentation says

FastAPI's tutorial on global dependencies shows that dependencies passed when you create the app "will be applied to all the path operations in the application." The same ideas as adding dependencies to a path operation decorator apply, just app wide. The tutorial also points to bigger application patterns where a single dependencies parameter covers a group of operations on a router.

Levels of protection

Where you declare itCovers
FastAPI(dependencies=[...])Every path operation in the app
APIRouter(dependencies=[...])Every operation on that router
Decorator dependenciesOne path operation
Function parameter with DependsOne path operation, and gives you the value

The router and decorator forms follow general FastAPI usage and the tutorial's pointers rather than the single page we fetched, so confirm them against your FastAPI version.

A caution about OAuth2PasswordBearer

OAuth2PasswordBearer only looks at the Authorization header. It expects a value of the form Bearer and a token, and returns 401 if the header is missing. By itself it does not validate the token, the tutorial says, so you must add validation in your own dependency. Also, tokenUrl does not create an endpoint. It only declares where clients should get a token, and that information goes into the OpenAPI description and interactive docs.

Public routes with a global dependency

A global dependency covers routes you want open too, such as login and health checks. Two common answers: keep those on a separate app or router that does not get the dependency, or have the dependency itself skip a short allowlist of paths. The first is easier to review, because the open surface is a separate file.

public = APIRouter()           # login, health
private = APIRouter(dependencies=[Depends(require_user)])

app = FastAPI()
app.include_router(public)
app.include_router(private)

Steps

  1. Write one dependency that validates the token and returns the user.
  2. Attach it to the private router, or to the app if almost everything is protected.
  3. Move deliberately public routes to their own router.
  4. Write a test that iterates app.routes and checks that every route not on the public router returns 401 without a token.
  5. Run an authenticated and an unauthenticated scan against staging and compare coverage.
  6. Remember that authentication is not authorization. A valid user can still request another user's record, so check ownership in the handler.

See also FastAPI response_model stops password and field leaks for the output side.

Try it yourself

Click through it at your own pace, or open it full screen. Compare what the scan sees with and without credentials.

Safeguard's SBOM and dependency scanning covers FastAPI, Starlette and Pydantic, and a free scan is available.

Quick check

Does a global dependency protect docs routes?

Check your version and test it. If the docs must be private, also disable them in production.

Does Depends(oauth2_scheme) verify the token?

No. It extracts the bearer token and returns 401 when it is absent. Validation is your job.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.