Custom authentication for FastAPI

29k views Asked by At

How can I create custom authentication for fastapi?

Example: I would like to make request with headers {'password': 'best password'} and if password key in header is "best password" allow to visible "auth only" content without changing it in all views (and compatible with generic documentation).

1

There are 1 answers

2
lsabi On

If you do not care about having a fancy integration with the swagger front end, you can simply create a dependency for verifying the token.

    from fastapi import FastAPI, HTTPException, Depends, Request

    def verify_token(req: Request):
        token = req.headers["Authorization"]
        # Here your code for verifying the token or whatever you use
        if token is not valid:
            raise HTTPException(
                status_code=401,
                detail="Unauthorized"
            )
        return True
    
    @app.post("/auth")
    async def login(password: str):
        if password == "my_password":
            return {"token": password} # Generate your own token
    
    @app.get("/")
    async def home(authorized: bool = Depends(verify_token)):
         if authorized:
            return {"detail": "Welcome home"}

I did not test the code, but it should be enough to give you an idea of how it should work.

If you care about having everything nicely integrated with the swagger UI, let me know. Since it's quite long and time consuming to prepare it, I won't prepare it if not necessary. Also, you'll have to follow the implementation of swagger, which, as far as I can understand from your question, not exactly what you asked for.

EDIT

Since the requests in the comments, I'll try to explain below how to achieve the integration with swagger.

The idea is to directly access the request during the login and perform some checks in order to decide whether the request is coming from swagger/openapi or from a personalized request. Then, once the parameters are obtained, perform the authentication as usual.

The code for logging in is the following. Note that it has to be adjusted based on the exact location and name of your parameters (since other people asked, I've shared a more general approach).

@app.post("/token")
async def login(req: Request, form_data: OAuth2PasswordRequestForm = Depends()):

    # Get header's data from the raw request
    # or from the swagger login form
    user = form_data.username
    print(user)
    print(req.headers["password"])

    return {"access_token": user, "token_type": "bearer"}