FastAPI + JWT + MySQL + DOcker end to end example
In this tutorial, we will explore how to implement a secure REST API using FastAPI with JSON Web Tokens (JWT) authentication, a MySQL database, and Docker for containerization.
What is JWT?
JWT (JSON Web Token) is like a secret message that can be sent between two computers to make sure that they trust each other. It's like having a secret code that only you and your friend know, and you use it to send messages to each other without anyone else being able to read them.
In the world of computers, when you log in to a website, you need to prove that you are who you say you are. One way to do this is to send your username and password to the website, but this is not very secure. So instead, the website can send you a JWT, which is like a secret message that only you and the website can read. This message proves that you have logged in successfully, and the website can use it to trust you and give you access to its features.
So, JWT is a way to keep information safe and secure between two computers, so they can trust each other and communicate without anyone else being able to see what they are saying.
Step 1:
Set up the MySQL Database
First, you will need to install MySQL and create a database to work with. For this tutorial, we will create a database called "fastapi_jwt" with the following table:
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
Next, insert a user record into the table:
INSERT INTO users (username, password) VALUES ('admin', 'password');
Step 2:
Install Dependencies
Next, install the necessary dependencies. You will need to install the following libraries:
pip install fastapi
pip install uvicorn
pip install PyJWT
pip install mysql-connector-python
Step 3:
Create a FastAPI app
Once you have installed the dependencies, create a new file called "main.py" and import the necessary libraries:
from fastapi import FastAPI, HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jwt import decode, encode, PyJWTError
from datetime import datetime, timedelta
from mysql.connector import connect, Error
from passlib.context import CryptContext
Next, create a FastAPI app instance:
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
Step 4:
Define the Database Connection
Now, define the function to connect to the MySQL database:
def get_db():
try:
conn = connect(
host="localhost",
user="root",
password="password",
database="fastapi_jwt"
)
if conn.is_connected():
return conn
except Error as e:
print(e)
Step 5:
Define the JWT Authentication
Next, define the JWT authentication functions:
SECRET_KEY = "mysecretkey"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def create_access_token(data: dict, expires_delta: int):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=expires_delta)
to_encode.update({"exp": expire})
encoded_jwt = encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
def verify_token(token: str):
try:
payload = decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")
except PyJWTError:
raise HTTPException(status_code=401, detail="Invalid authentication credentials")
Step 6:
Define the Login Endpoint
Next, define the login endpoint:
@app.post("/login")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
db = get_db()
cursor = db.cursor()
cursor.execute("SELECT id, username, password FROM users WHERE username=%s", (form_data.username,))
user = cursor.fetchone()
if not user:
raise HTTPException(status_code=401, detail="Invalid username or password")
if not pwd_context.verify(form_data.password, user[2]):
raise HTTPException(status_code=401, detail="Invalid username or password")
access_token = create_access_token(
data={"sub": user[1]}, expires_delta=ACCESS
Step 7:
Docker file
Here is an example Dockerfile that you can use for the FastAPI + JWT + MySQL implementation:
FROM python:3.8-slim-buster
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
Save this file as "Dockerfile" in the same directory as your FastAPI application files.
To build the Docker image, run the following command in the terminal:
docker build -t my-fastapi-app .
The .
at the end of the command specifies that the Docker build context is the current directory. The -t
flag specifies the name of the Docker image.
Once the build is complete, you can run the Docker container with the following command:
docker run -p 8000:80 my-fastapi-app
The -p
flag specifies the port mapping between the container's port 80 and the host's port 8000. You can access the FastAPI app at http://localhost:8000
in your web browser.
Note: In the above Dockerfile, we are using a slim version of the Python 3.8 image to minimize the size of the Docker image. If you need additional packages or libraries, you can install them using the RUN
command.
Conclusion:
In this article, we learned how to implement an end-to-end FastAPI application that uses MySQL as the database and JWT for authentication. We started by creating a MySQL database and setting up the required environment variables.
We then created a FastAPI application that can create, read, update, and delete users from the database. We added JWT authentication to our application, which required us to create a secret key and use it to generate and validate tokens.
Finally, we containerized our application using Docker and provided a Dockerfile to build the image.
By following this tutorial, you should now have a good understanding of how to create a secure and scalable FastAPI application that uses MySQL and JWT for authentication. You can use this as a starting point for your own projects and customize it as needed.
I hope this helps, you!!
More such articles:
https://www.youtube.com/channel/UCiTaHm1AYqMS4F4L9zyO7qA
\==========================**=========================
If this article adds any value to you then please clap and comment.
Let’s connect on Stackoverflow, LinkedIn, & Twitter.