FastAPI API Key Authentication Python Code

title: Contents 
style: nestedList # TOC style (nestedList|inlineFirstLevel)
minLevel: 1 # Include headings from the specified level
maxLevel: 4 # Include headings up to the specified level
includeLinks: true # Make headings clickable
debugInConsole: false # Print debug info in Obsidian console

Overview

Sources:

  • **

Code

In src/api/auth/security.py

from dotenv import dotenv_values  
from fastapi.security import APIKeyHeader  
from fastapi import HTTPException, Security, status
 
# Constants  
API_KEY_HEADER = APIKeyHeader(name="X-API-Key")  
API_KEY = dotenv_values(".env")["SERVICE_API_KEY"]  
 
def validate_authentication(api_key: str = Security(API_KEY_HEADER)):  
	""" Validate API key authentication.  
	:param api_key: Authentication credentials.  
	:raise HTTPException(401): When an incorrect API key is supplied.  
	"""
	if api_key != API_KEY:  
	raise HTTPException(  
		status_code=status.HTTP_401_UNAUTHORIZED,  
		detail="Invalid or missing API Key",  
		headers={"WWW-Authenticate": "X-API-Key"}  
	)

This validate_authentication procedure handles API-key authentication for process endpoints that needs it. FastAPI are using a dependency injection pattern in the endpoint decorator and the procedure is designed to be used there. The input api_key parameter is supplied automatically by FastAPI.

Then in src/api/__main__.py:

import asyncio
from uuid import uuid4
 
from pydantic import BaseModel, UUID4
from fastapi import FastAPI, Depends, HTTPException
 
from auth.security import validate_authentication
 
app = FastAPI(
	redoc_url=None,
	title='API'
)
 
 
class ProcessModel(BaseModel):
	status: str
 
 
class ProcessResponseModel(ProcessModel):  
	id: UUID4
 
 
async def _fake_processing(payload: ProcessModel) -> bool:
    await asyncio.sleep(0.5)
    return payload.status == 'SUCCESS'
 
 
@app.post(  
	'/process',
	response_model=ProcessResponseModel,  
	dependencies=[
		Depends(validate_authentication)
	]  
)
async def process(payload: ProcessModel) -> ProcessResponseModel:
	if await _fake_processing(payload):
		return ProcessResponseModel(status='SUCCESS', id=f'{uuid4()}')
 
	raise HTTPException(status_code=500, detail="Task processing failed")

After the imports the FastAPI class is instantiated. It is followed by two Pydantic models used by the endpoint to validate input and output data.

A good coding practice that I want to show you is the FastAPI built-in dependency injection pattern (se Depends in the decorator_)_. By using it this way you are making sure that users of the process endpoint are properly authenticated (by specifying the correct API key in the calling request header).

Finally, the run.py:

import uvicorn
 
if __name__ == "__main__":
    uv_config = {'reload': True, 'app': 'src/api/__main__:app'}
    uvicorn.run(**uv_config)

This is the program that starts Uvicorn (who creates the API server). To access the API web page, use the following URL in your browser: http://127.0.0.1:8000/docs.

Details

About

This note is about …

See Also


Appendix

Note created on 2024-04-15 and last modified on 2024-04-15.

LIST FROM [[Python - FastAPI API Key Authentication]] AND -"CHANGELOG" AND -"04-RESOURCES/Code/Python/Python - FastAPI API Key Authentication"

(c) No Clocks, LLC | 2024