Skip to content

About

Secure FastAPI Employee CRUD API demonstrating API key authentication, JWT, rate limiting, CORS, security headers, input validation, SQL injection prevention, XSS protection, and HTTPS-ready configuration.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

ย 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ” API Security Audit

A production-inspired FastAPI Employee CRUD API hardened with layered security controls including API key authentication, JWT authentication, rate limiting, CORS, secure headers, input validation, SQL injection prevention, XSS input protection, environment-based configuration, and HTTPS-ready deployment support.

Python FastAPI SQLAlchemy JWT Security


๐Ÿ“Œ Table of Contents


๐Ÿ”Ž Overview

The API Security Audit project starts with a small Employee CRUD REST API and progressively hardens it against common API security risks.

The project demonstrates an important engineering workflow:

flowchart LR
    A[Basic FastAPI CRUD] --> B[Security Audit]
    B --> C[Authentication]
    B --> D[Input Protection]
    B --> E[HTTP Security]
    B --> F[Abuse Protection]
    C --> G[Hardened API]
    D --> G
    E --> G
    F --> G
Loading

The goal is not simply to add security libraries. Each security control is implemented and tested against a concrete requirement.


๐ŸŽฏ Objective

Core Requirements

  • API Key Authentication
  • JWT Authentication
  • HTTPS-ready configuration
  • Rate Limiting
  • CORS
  • Secure HTTP Headers
  • Input Validation
  • SQL Injection Prevention
  • XSS Prevention
  • Environment Variables
  • Secret Management

Bonus

  • Redis-backed Rate Limiting

Demonstration

The security audit includes before-and-after attack demonstrations showing how requests behave before and after the corresponding security controls are applied.


๐Ÿ—๏ธ Architecture

flowchart TD
    Client[Client / Browser / Postman]
    Proxy[Nginx / HTTPS Reverse Proxy]
    Rate[Rate Limiting Middleware]
    CORS[CORS Middleware]
    Headers[Security Headers]
    Router[FastAPI Router]
    APIKey[API Key Validation]
    JWT[JWT Validation]
    Schema[Pydantic Validation]
    ORM[SQLAlchemy ORM]
    DB[(SQLite Database)]

    Client --> Proxy
    Proxy --> Rate
    Rate --> CORS
    CORS --> Headers
    Headers --> Router
    Router --> APIKey
    APIKey --> JWT
    JWT --> Schema
    Schema --> ORM
    ORM --> DB
Loading

Request Security Flow

Client Request
      โ”‚
      โ–ผ
Rate Limiting
      โ”‚
      โ–ผ
CORS / HTTP Security
      โ”‚
      โ–ผ
API Key Authentication
      โ”‚
      โ–ผ
JWT Authentication
      โ”‚
      โ–ผ
Pydantic Input Validation
      โ”‚
      โ–ผ
SQLAlchemy ORM
      โ”‚
      โ–ผ
Database

๐Ÿ” Security Architecture

Two-Layer Authentication

Protected employee endpoints currently require both:

X-API-Key
      +
Authorization: Bearer <JWT>
      โ†“
Protected Endpoint

The API key identifies an approved client/application.

The JWT represents an authenticated user session.

This project intentionally demonstrates both mechanisms so their roles can be understood separately.


๐Ÿ› ๏ธ Technology Stack

Layer Technology Purpose
API Framework FastAPI REST API and request handling
Language Python 3.13+ Application logic
ORM SQLAlchemy Database access using parameterized queries
Database SQLite Local employee persistence
Validation Pydantic Request and response validation
Authentication API Key + JWT Client and user authentication
JWT Library python-jose JWT creation and verification
Configuration python-dotenv Environment-based configuration
Middleware Starlette/FastAPI CORS, headers, rate limiting, HTTPS
Development Server Uvicorn ASGI server

๐Ÿ“ Project Structure

api-security-audit/
โ”‚
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ main.py                  # FastAPI application and middleware
โ”‚   โ”œโ”€โ”€ database.py              # SQLAlchemy engine/session
โ”‚   โ”œโ”€โ”€ models.py                # Database models
โ”‚   โ”œโ”€โ”€ schemas.py               # Pydantic request/response schemas
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ routers/
โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”œโ”€โ”€ employees.py         # Employee CRUD endpoints
โ”‚   โ”‚   โ””โ”€โ”€ auth.py              # Login endpoint
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ security/
โ”‚   โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”‚   โ”œโ”€โ”€ api_key.py           # API key verification
โ”‚   โ”‚   โ”œโ”€โ”€ jwt.py               # JWT creation/verification
โ”‚   โ”‚   โ”œโ”€โ”€ jwt_auth.py          # JWT authentication dependency
โ”‚   โ”‚   โ””โ”€โ”€ headers.py            # Security response headers
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ middleware/
โ”‚       โ”œโ”€โ”€ __init__.py
โ”‚       โ””โ”€โ”€ rate_limit.py        # IP-based rate limiting
โ”‚
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ __init__.py
โ”‚
โ”œโ”€โ”€ .env.example                 # Safe configuration template
โ”œโ”€โ”€ .gitignore                   # Git ignore rules
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ requirements.txt

.env is intentionally excluded from source control.


โœจ Security Features

๐Ÿ”‘ 1. API Key Authentication

Protected employee endpoints require an X-API-Key header.

X-API-Key: <your-api-key>

Missing or incorrect keys return:

401 Unauthorized

The implementation uses secrets.compare_digest() for the key comparison.


๐ŸŽซ 2. JWT Authentication

Users authenticate through:

POST /auth/login

A successful login returns a bearer token.

Protected requests use:

Authorization: Bearer <JWT>

JWT expiration is configured through an environment variable.


๐Ÿšฆ 3. Rate Limiting

The application allows:

10 requests / 60 seconds / client IP

Exceeding the limit returns:

429 Too Many Requests

Swagger and OpenAPI documentation paths are excluded from the rate limiter so documentation browsing does not consume the API quota.

The current implementation is in-memory and intended for the project/demo environment. Redis-backed rate limiting is a future/bonus improvement for distributed deployments.


๐ŸŒ 4. CORS

Allowed browser origins are configured through:

ALLOWED_ORIGINS=http://localhost:3000

Unauthorized browser origins receive a CORS rejection.


๐Ÿ›ก๏ธ 5. Secure HTTP Headers

The API adds:

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Content-Security-Policy: default-src 'none'

CSP is skipped for Swagger/OpenAPI documentation paths because Swagger requires browser-loaded assets to render correctly.


โœ… 6. Input Validation

Pydantic validates:

  • Name length
  • Email format
  • Department length
  • Non-negative salary
  • Positive pagination values
  • Required response identifiers

Invalid requests return 422 Unprocessable Entity.


๐Ÿ’‰ 7. SQL Injection Prevention

Database operations use SQLAlchemy ORM queries instead of dynamically concatenating SQL strings.

User input is therefore treated as data rather than being inserted directly into SQL statements.


๐Ÿงน 8. XSS Input Protection

Employee name and department fields reject HTML-like tags.

Example:

<script>alert("XSS")</script>

is rejected by request validation.

XSS protection is context-dependent. If a future frontend renders user-controlled data as HTML, that frontend must also safely escape or sanitize output.


๐Ÿ” 9. Secret Management

Sensitive values are stored in .env rather than committed to Git.

Examples include:

  • API key
  • JWT secret
  • Authentication password
  • Database URL

.env.example contains only placeholder values.


๐Ÿ”’ 10. HTTPS-Ready Configuration

Uvicorn is configured to understand forwarded proxy headers:

uvicorn app.main:app --reload --proxy-headers

Production deployments can place FastAPI behind an HTTPS reverse proxy such as Nginx.

HTTPS enforcement is environment-controlled:

FORCE_HTTPS=false

Set it to true when HTTPS termination is configured in the deployment environment.


โš™๏ธ Setup & Installation

1. Clone the repository

git clone <YOUR_GITHUB_REPOSITORY_URL>
cd api-security-audit

2. Create a virtual environment

python3.13 -m venv venv
source venv/bin/activate

3. Install dependencies

pip install --upgrade pip
pip install -r requirements.txt

4. Create environment configuration

cp .env.example .env

Edit .env and provide your own local secrets.

Never copy real secrets into .env.example.


๐Ÿ”‘ Environment Variables

Example configuration:

# Database
DATABASE_URL=sqlite:///./employee_db.sqlite

# API Authentication
API_KEY=your-secure-api-key

# JWT
JWT_SECRET_KEY=your-long-random-secret
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=30

# Login
AUTH_USERNAME=admin
AUTH_PASSWORD=your-local-password

# CORS
ALLOWED_ORIGINS=http://localhost:3000

# HTTPS
FORCE_HTTPS=false

Generate strong random secrets with:

python -c "import secrets; print(secrets.token_hex(32))"

Git Security Check

Verify that .env is ignored:

git check-ignore -v .env

Expected output should reference .gitignore.


๐Ÿš€ Running the Application

Start the API with proxy-header support:

uvicorn app.main:app --reload --proxy-headers

Interactive API Documentation

http://127.0.0.1:8000/docs

ReDoc

http://127.0.0.1:8000/redoc

๐Ÿ”Œ API Endpoints

Authentication

Method Endpoint Purpose Auth
POST /auth/login Generate JWT None

Employees

Method Endpoint Purpose
POST /employees/ Create employee
GET /employees/ List employees
GET /employees/{id} Get employee
PUT /employees/{id} Update employee
PATCH /employees/{id} Partial update
DELETE /employees/{id} Delete employee

Employee endpoints require:

X-API-Key: <API_KEY>
Authorization: Bearer <JWT>

๐Ÿงช Security Testing

The project demonstrates security behavior using requests before and after controls are implemented.

1. Missing API Key

Expected:

401 Unauthorized

2. Invalid API Key

Expected:

401 Unauthorized

3. Missing/Invalid JWT

Expected:

401 Unauthorized

4. Invalid Input

Example:

{
  "name": "",
  "email": "not-an-email",
  "salary": -100
}

Expected:

422 Unprocessable Entity

5. XSS Attempt

Example:

{
  "name": "<script>alert('XSS')</script>",
  "email": "[email protected]"
}

Expected:

422 Unprocessable Entity

6. SQL Injection-Style Input

Example:

' OR '1'='1

The SQLAlchemy ORM treats the value as data rather than dynamically executing it as SQL.

7. Rate Limit

After the configured request limit is exceeded:

429 Too Many Requests

๐Ÿšฆ Rate Limiting Demo

Restart the application first so the in-memory counter starts fresh.

Then send 11 authenticated requests:

for i in {1..11}; do
  curl -s -o /dev/null -w "Request $i: %{http_code}\n"     "http://127.0.0.1:8000/employees/?page=1&size=20"     -H "X-API-Key: YOUR_API_KEY"     -H "Authorization: Bearer YOUR_JWT"
done

Expected:

Request 1: 200
Request 2: 200
...
Request 10: 200
Request 11: 429

๐ŸŒ CORS Demo

Allowed Origin

curl -i -X OPTIONS http://127.0.0.1:8000/employees/   -H "Origin: http://localhost:3000"   -H "Access-Control-Request-Method: GET"

Expected response includes:

access-control-allow-origin: http://localhost:3000

Disallowed Origin

curl -i -X OPTIONS http://127.0.0.1:8000/employees/   -H "Origin: http://evil-example.com"   -H "Access-Control-Request-Method: GET"

The request should be rejected by the CORS configuration.


๐Ÿ›ก๏ธ Security Headers

Check the API response headers:

curl -i http://127.0.0.1:8000/

Expected security headers include:

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Content-Security-Policy: default-src 'none'

Swagger/OpenAPI documentation paths intentionally have different CSP handling so the interactive documentation can load correctly.


๐Ÿ”’ HTTPS-Ready Configuration

The application supports deployment behind an HTTPS reverse proxy.

flowchart LR
    Browser[Browser]
    HTTPS[HTTPS / TLS]
    Nginx[Nginx Reverse Proxy]
    Uvicorn[Uvicorn]
    FastAPI[FastAPI]

    Browser --> HTTPS
    HTTPS --> Nginx
    Nginx --> Uvicorn
    Uvicorn --> FastAPI
Loading

Run the application with:

uvicorn app.main:app --reload --proxy-headers

For an HTTPS-enabled deployment:

FORCE_HTTPS=true

Local development should normally remain:

FORCE_HTTPS=false

because the local development server does not provide a TLS certificate.


๐ŸŽฅ YouTube Demonstration

Recommended demonstration sequence:

1. Show the unsecured/baseline behavior

Demonstrate representative attacks or missing controls against the original CRUD API:

  • Unauthenticated employee access
  • Invalid input
  • XSS-style input
  • SQL injection-style input
  • Repeated requests

2. Explain the security architecture

Show:

API Key
   โ†“
JWT
   โ†“
Validation
   โ†“
SQLAlchemy ORM
   โ†“
Database

And the middleware layer:

Rate Limiting
CORS
Security Headers
HTTPS-ready proxy handling

3. Demonstrate the hardened API

Show:

  • Missing API key โ†’ 401
  • Invalid JWT โ†’ 401
  • Invalid input โ†’ 422
  • XSS payload โ†’ rejected
  • CORS violation โ†’ rejected
  • Rate limit exceeded โ†’ 429
  • Security headers โ†’ present
  • Valid authenticated CRUD โ†’ successful

๐Ÿงฉ Troubleshooting

โŒ API Key Missing

Protected employee endpoints require:

X-API-Key: YOUR_API_KEY

โŒ Invalid JWT

Login again using:

POST /auth/login

Then send:

Authorization: Bearer YOUR_JWT

Check that the token has not expired.

โŒ Swagger Becomes Unavailable

Check that restrictive CSP is not applied to:

/docs
/redoc
/openapi.json

These documentation routes need browser assets to render correctly.

โŒ Rate Limit Reached During Testing

The current implementation uses in-memory counters. Restarting the development server resets the counters.

Swagger/OpenAPI documentation routes are excluded from the rate limiter.

โŒ .env Appears in Git Status

Check:

git check-ignore -v .env

Make sure .env is listed in .gitignore.

If it was accidentally staged:

git restore --staged .env

Never publish an actual secret.


๐Ÿ“Œ Assignment Coverage

Requirement Implementation Status
API Key Authentication app/security/api_key.py โœ…
JWT app/security/jwt.py + jwt_auth.py โœ…
HTTPS Ready Proxy headers + configurable redirect โœ…
Rate Limiting app/middleware/rate_limit.py โœ…
CORS CORSMiddleware โœ…
Secure Headers app/security/headers.py โœ…
Input Validation app/schemas.py โœ…
SQL Injection Prevention SQLAlchemy ORM โœ…
XSS Prevention HTML-like input rejection โœ…
Environment Variables .env + python-dotenv โœ…
Secret Management .gitignore + .env.example โœ…
Redis Rate Limiting Not yet implemented โณ

๐Ÿง  Key Engineering Lessons

  1. Authentication is layered.
  2. Validation belongs close to the API boundary.
  3. ORM parameterization helps prevent SQL injection.
  4. Security headers protect browser-facing behavior.
  5. CORS controls browser origins, not general API access.
  6. Rate limiting protects APIs from excessive requests.
  7. Secrets should live outside source code.
  8. HTTPS should be part of the deployment architecture.
  9. Security controls should be tested, not only configured.
  10. Local development and production configuration should be separated.

๐Ÿ”ฎ Future Improvements

  • Redis-backed distributed rate limiting
  • PostgreSQL for production database
  • Automated security test suite
  • Password hashing with a dedicated password-hashing algorithm
  • Refresh-token flow
  • Role-based access control
  • Structured logging and audit trails
  • Nginx HTTPS deployment with real TLS certificates
  • Secret manager integration
  • CI/CD security checks
  • Dependency vulnerability scanning

๐Ÿ‘จโ€๐Ÿ’ป Author

Vijay Rangvani

Backend & AI Engineering Learner | Healthcare IT

Focus Areas

Python ยท FastAPI ยท REST APIs ยท SQLAlchemy ยท JWT ยท API Security ยท Docker ยท Cloud Systems


Built as a practical API security audit project demonstrating secure backend engineering patterns through implementation and attack testing.

About

Secure FastAPI Employee CRUD API demonstrating API key authentication, JWT, rate limiting, CORS, security headers, input validation, SQL injection prevention, XSS protection, and HTTPS-ready configuration.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages