All posts

Implementing Basic Authentication With Python FastAPI

The inspiration for this project came from an initiative I started a few years ago called PyDex. It was essentially a repository of “borrowed” copies of various textbooks that I obtained either for college or by scour…

I want to continue the theme of security-based articles with a quick tutorial on implementing BasicAuth as an Authentication method if you’re using the FastAPI framework for Python.

The inspiration for this project came from an initiative I started a few years ago called PyDex. It was essentially a repository of “borrowed” copies of various textbooks that I obtained either for college or by scouring the internet. I have always believed in providing knowledge for free, and this was one way of doing so.

The website itself was quite simple. It had a front-end that would send query data to the backend. I used SQL to store the titles, names, images, and any other metadata associated with these books. However, there was never any sort of authentication, which would have been essential if, for instance, I wanted people to add their books to the collection. While BasicAuth is becoming deprecated in many modern systems, it is still a good and simple authentication technique to learn.

Implementation

The FastAPI framework provides a way to implement BasicAuth relatively quickly. First, assuming you already have FastAPI installed, we need to import FastAPI and a few of its classes and modules. Specifically, we need the FastAPI, Depends, HTTPException, Status classes, and the fastapi.security module with the HTTPBasic and BasicCredentials classes, as shown below:

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

Next, we can take the code from the FastAPI documentation and instantiate both the FastAPI app and HTTPBasic. However, we’ll need to specify that we want global BasicAuth protection, meaning that the user must be authenticated for access to all the routes that we create. To achieve this, we’ll add a dependency to the app that points to the instantiated HTTPBasic authentication. The code would look something like this:

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

security = HTTPBasic()
app = FastAPI(dependencies=[Depends(security)])

From here, we can create a dictionary of users to perform authentication. In this case, I’ll create a dictionary with an admin user that includes a password and other metadata that we may want to use in our application. Note that in a real application, this data should not be hardcoded and in plaintext. However, for the purpose of this example, it is acceptable.

users = {
    "admin": {
        "password": "Password123",
        "token": "",
        "priviliged": True
    }
}

Next, we want to create an authentication method that will search the dictionary and verify the username and password.

def verification(creds: HTTPBasicCredentials = Depends(security)):
    username = creds.username
    password = creds.password
    if username in users and password == users[username]["password"]:
        print("User Validated")
        return True
    else:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect email or password",
            headers={"WWW-Authenticate": "Basic"},
        )

Now, we can create our path operation function and check for proper authentication using the following code:

@app.get("/name/{name}")
async def search(name: str, Verifcation = Depends(verification)):
    #If The Verification Function Successfuylly Authenticates The User Then It Will Run The Below SQLite3 Code
    if Verifcation:
        #Insert Code Here
        Print(f"Hello {name}!")

In all, the code should look something like this:

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

# Instatiated Variables
security = HTTPBasic()
app = FastAPI(dependencies=[Depends(security)])

users = {
    "admin": {
        "password": "Password123",
        "token": "",
        "priviliged": True
    }
}

# User Verification Function
def verification(creds: HTTPBasicCredentials = Depends(security)):
    username = creds.username
    password = creds.password
    if username in users and password == users[username]["password"]:
        print("User Validated")
        return True
    else:
        # From FastAPI 
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect email or password",
            headers={"WWW-Authenticate": "Basic"},
        )

# Path Operation Function
@app.get("/name/{name}")
async def search(name: str, Verifcation = Depends(verification)):
    #If The Verification Function Successfuylly Authenticates The User Then It Will Run The Below Code
    if Verifcation:
        #Insert Code Here
        return {"Hello":name}

Results

Prompt for credentials
Prompt for credentials
Results from successful authentication

In my next article, I’ll build upon the code we have here and integrate SQLite3. I’ll also discuss how we can sanitize user input for use with SQL queries.

Note: This article was reviewed by ChatGPT for grammatical errors, testing to see how it works out?

Discussion

No comments yet