Creating a RESTful API with FastAPI and JWT Authentication
In today's digital world, creating secure and efficient web applications is paramount. One of the most effective ways to build a robust backend is by developing a RESTful API. FastAPI, a modern Python web framework, simplifies this process while providing out-of-the-box support for JWT (JSON Web Tokens) authentication. In this article, we’ll explore how to create a RESTful API using FastAPI and implement JWT authentication, along with practical coding examples to guide you through each step.
What is FastAPI?
FastAPI is an asynchronous web framework for building APIs with Python 3.7+ based on standard Python type hints. It is designed to be fast (high performance), easy to use, and allows for automatic generation of OpenAPI documentation. FastAPI is particularly popular for its simplicity in creating RESTful APIs and its integration with data validation.
Key Features of FastAPI:
- Fast: High performance, on par with Node.js and Go.
- Easy: Simple and intuitive syntax.
- Automatic Docs: Interactive API documentation generated automatically.
- Type Checking: Utilizes Python type hints for validation and serialization.
Understanding JWT Authentication
JWT (JSON Web Tokens) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure.
Why Use JWT?
- Stateless: The server does not need to store session information.
- Cross-Domain: Can be used across different domains.
- Scalable: Suitable for microservices architecture.
Setting Up FastAPI
Before we begin coding, ensure you have Python 3.7+ installed. You can create a new FastAPI project by following these steps:
-
Install FastAPI and a web server (like Uvicorn):
bash pip install fastapi[all] uvicorn
-
Create a new Python file (e.g.,
main.py
).
Step-by-Step: Building a RESTful API
Step 1: Basic FastAPI Setup
Start by creating a simple FastAPI application.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
Step 2: Adding User Registration and JWT Generation
We will create endpoints for user registration and login, generating JWTs upon successful login.
User Model
First, define a user model using Pydantic.
from pydantic import BaseModel
class User(BaseModel):
username: str
password: str
User Registration Endpoint
Now, add a registration endpoint.
users_db = {}
@app.post("/register")
async def register(user: User):
if user.username in users_db:
return {"error": "User already exists."}
users_db[user.username] = user.password
return {"msg": "User registered successfully."}
Step 3: Implementing JWT Authentication
To implement JWT, you need to install the pyjwt
library:
pip install pyjwt
Create JWT Token
Add a function to create a JWT token.
import jwt
import datetime
from fastapi import HTTPException, Depends, status
SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
def create_jwt_token(username: str):
expiration = datetime.datetime.utcnow() + datetime.timedelta(hours=1)
token = jwt.encode({"exp": expiration, "sub": username}, SECRET_KEY, algorithm=ALGORITHM)
return token
Login Endpoint
Now, create a login endpoint to authenticate users and return a JWT token.
@app.post("/login")
async def login(user: User):
stored_password = users_db.get(user.username)
if not stored_password or stored_password != user.password:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials")
token = create_jwt_token(user.username)
return {"access_token": token, "token_type": "bearer"}
Step 4: Protecting Routes with JWT
To protect certain routes, create a dependency that verifies the token.
from fastapi import Security
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except jwt.PyJWTError:
raise credentials_exception
return username
Step 5: Creating a Protected Route
Now, let's create a protected route that requires authentication.
@app.get("/users/me")
async def read_users_me(current_user: str = Depends(get_current_user)):
return {"msg": f"Hello, {current_user}!"}
Running the FastAPI Application
Run the application using Uvicorn:
uvicorn main:app --reload
Visit http://127.0.0.1:8000/docs
to see the automatically generated documentation and test your API endpoints.
Conclusion
In this article, we’ve walked through the steps to create a RESTful API using FastAPI, with JWT authentication to secure your endpoints. FastAPI's ease of use, combined with the stateless nature of JWT, makes it a powerful choice for building modern web applications.
Key Takeaways:
- FastAPI is an efficient framework for developing APIs.
- JWT provides a secure way to handle user authentication.
- The combination of FastAPI and JWT simplifies the implementation of secure APIs.
Now that you have a foundational understanding, you can expand on this by adding features like user roles, password hashing, and more. Happy coding!