Supporting Basic Auth and JWT Auth Access Endpoint in FastAPI
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. In this article, we will discuss how to support Basic Auth and JWT Auth access endpoints in FastAPI.
Basic Auth in FastAPI
Basic Authentication is a simple authentication scheme built into the HTTP protocol. The client sends HTTP requests with the Authorization header that contains the word Basic followed by a space and a base64-encoded string "username:password".
To support Basic Auth in FastAPI, we can use the FastAPI library's built-in Depends() function along with the HTTPBasic() class from the fastapi.security module.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
app = FastAPI()
security = HTTPBasic()
@app.get("/protected-route")
async def protected_route(credentials: HTTPBasicCredentials = Depends(security)):
correct_username = "username"
correct_password = "password"
if credentials.username != correct_username or credentials.password != correct_password:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Basic"},
)
return {"message": "Protected route accessed successfully"}
JWT Auth in FastAPI
JSON Web Tokens (JWT) are a compact, URL-safe means of representing claims to be transferred between two parties. JWTs are signed and consist of three parts: a header, a payload, and a signature. JWTs are typically used to authenticate clients and authorize access to protected resources.
To support JWT Auth in FastAPI, we can use the PyJWT library to create and verify JWTs and the FastAPI library's built-in Depends() function to inject the JWT token into our protected routes.
from fastapi import Depends, FastAPI, HTTPException, status
import jwt
from jose import jwt as jose_jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
app = FastAPI()
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password):
return pwd_context.hash(password)
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jose_jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async 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
token_data = TokenData(username=username)
except jwt.JWTError:
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
raise credentials_exception
return user
@app.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
user = get_user(fake_users_db, form_data.username)
if not user:
raise HTTPException(status_code=400, detail="Incorrect username or password")
if not verify_password(form_data.password, user.hashed_password):
raise HTTPException(status_code=400, detail="Incorrect username or password")
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
@app.get("/jwt-protected")
async def jwt_protected_route(current_user: User = Depends(get_current_user)):
return {"message": f"Hello, {current_user.username}!"}
Significance and Applications
Supporting Basic Auth and JWT Auth access endpoints in FastAPI is essential for building secure and scalable APIs. By implementing authentication and authorization, we can ensure that only authorized users can access protected resources, preventing unauthorized access and data breaches.
References: