A security-focused REST API built with FastAPI, designed around practical application security, authentication, authorization, auditability, security monitoring, and DevSecOps automation.
The project demonstrates how a modern security-aware API can integrate preventive controls, detection capabilities, security logging, incident management, automated testing, containerized deployment, and CI security gates into a single application.
This project implements a secure REST API with:
- JWT-based authentication (access + refresh token architecture)
- Refresh token rotation and server-side revocation
- Role-Based Access Control (RBAC)
- Secure password hashing with Argon2 (
pwdlib) - SQLAlchemy database integration with Alembic migrations
- Security audit logging (database-backed)
- Request ID / correlation tracking
- Structured JSON security logging
- Login rate limiting
- HTTP security headers (CSP, HSTS, X-Frame-Options, etc.)
- Incident management with object-level authorization
- SIEM-style security event monitoring
- Automated security alert generation
- Machine-readable security reports
- SOC-style monitoring dashboard (Streamlit)
- Containerized deployment (Docker + Docker Compose)
- Automated security testing
- Static security analysis (Bandit)
- Dependency vulnerability auditing (pip-audit)
- Secret scanning (Gitleaks)
- GitHub Actions security CI pipeline
Client
|
v
+---------------------+
| FastAPI API |
+---------------------+
|
+------------+------------+
| |
v v
Request ID Middleware Security Headers
| |
+------------+------------+
|
v
+---------------------+
| Authentication |
| JWT / RBAC |
+---------------------+
|
+------------+------------+
| |
v v
API Resources Incident Management
| |
+------------+------------+
|
v
+---------------------+
| Audit Logging |
| Structured JSON Logs |
+---------------------+
|
v
+---------------------+
| Security Monitoring |
+---------------------+
|
+------------+------------+
| |
v v
Alert Engine Security Report
| |
+------------+------------+
|
v
+---------------------+
| SOC Dashboard |
| Streamlit |
+---------------------+
The API uses JWT-based authentication with separate, explicitly-typed access and refresh tokens.
Security features include:
- Signed JWT access tokens (
type: access) - Signed JWT refresh tokens (
type: refresh) - Token expiration (
exp) - Token type validation (an access token cannot be used where a refresh token is required, and vice versa)
- JWT ID (
jti) for refresh-token tracking - Issuer (
iss) validation - Audience (
aud) validation - Issued-at (
iat) claims - Refresh token rotation (each use issues a new pair and invalidates the old one)
- Refresh token revocation (server-side, database-backed — supports logout)
Role-Based Access Control is implemented for protected resources.
Supported roles include:
analystadmin
Administrative endpoints require the appropriate role. Incident resources additionally enforce object-level authorization: a user can only retrieve or list incidents they own, identified by their database user ID (not their username), which is carried in the JWT user_id claim.
Passwords are never stored in plaintext. The project uses:
pwdlibwith Argon2 password hashing- Password verification before authentication
- Secure password storage practices
Authentication endpoints use request rate limiting through SlowAPI.
POST /auth/login
5 requests per minute
This reduces automated authentication attacks such as repeated password guessing.
The application applies security-related HTTP headers through custom middleware:
X-Frame-OptionsX-Content-Type-OptionsReferrer-PolicyPermissions-PolicyContent-Security-Policy(relaxed for/docsand/redocso Swagger UI can load its assets; strictdefault-src 'self'everywhere else)Strict-Transport-Security
Every API request receives a unique request ID, returned as X-Request-ID. Clients can also supply their own. The same identifier is correlated across:
API Request
|
+--> Structured Security Log
|
+--> Audit Record
|
+--> Security Monitoring
|
+--> SOC Alert
This provides an investigation-friendly trail for security events.
GET /health Liveness check — is the process running?
GET /readiness Readiness check — is the database reachable?
/health is intentionally public (no authentication required) so container orchestrators such as Docker or Kubernetes can probe it without credentials. /readiness additionally verifies database connectivity and returns 503 if the database is unreachable.
The API includes security incident management capabilities.
Authenticated users can create and retrieve incidents. Object-level authorization prevents users from accessing incidents belonging to other users — ownership is checked against the requesting user's database ID, not just their role, which protects against insecure direct object reference (IDOR) / broken object-level authorization (BOLA) attacks.
POST /api/v1/incidents
GET /api/v1/incidents
GET /api/v1/incidents/{incident_id}
Security principles demonstrated:
- Authentication before access
- User ownership validation by database ID
- Object-level authorization
- Controlled incident retrieval
- Security-focused API design
Current limitation: all incident routes filter by the requesting user's own ownership, including for the
adminrole — administrators cannot yet view other users' incidents. Broader admin visibility, andPATCH/DELETEincident endpoints, are planned next steps (see Roadmap below).
The project includes a lightweight security monitoring pipeline that processes structured application security logs.
security.log
|
v
Log Parser
|
v
Security Events
|
v
Alert Engine
|
+---- Authentication Failure Burst
|
+---- Targeted Account Failure
|
v
Security Alerts
|
v
JSON Security Report
|
v
SOC Dashboard
Authentication Failure Burst — repeated failed authentication attempts from the same IP address.
Default threshold: 5 failed attempts
Alert: AUTHENTICATION_FAILURE_BURST (Severity: HIGH)
Targeted Account Failure — repeated authentication failures against the same username.
Default threshold: 3 failed attempts
Alert: TARGETED_ACCOUNT_FAILURE (Severity: MEDIUM)
Alerts include SOC-oriented metadata: alert ID, alert type, detection rule, severity, detection timestamp, source IP, target account, event count, correlated request IDs, and a description.
A Streamlit-based SOC monitoring dashboard provides visibility into:
- Total security events and alerts (by severity)
- Security alert details
- Detection rules triggered
- Target accounts and source IPs
- Correlated request IDs
- The latest monitoring report
Application Logs → Security Monitoring → Detection Rules → Security Report → SOC Dashboard
Run it with:
streamlit run .\src\dashboard\app.pyAvailable locally at http://localhost:8501.
A user attempting to access another user's incident receives a 404, not the incident's data:
The monitoring engine generates a machine-readable JSON report at reports/security_report.json:
{
"generated_at": "2026-09-19T11:24:08+00:00",
"summary": {
"total_events": 355,
"total_alerts": 1,
"alerts_by_severity": {
"MEDIUM": 1
}
},
"alerts": [
{
"alert_id": "ALT-XXXXXXXXXXXX",
"alert_type": "TARGETED_ACCOUNT_FAILURE",
"rule": "targeted_account_failure",
"severity": "MEDIUM",
"event_count": 3
}
]
}reports/ and logs/ are generated at runtime and are excluded from version control (see .gitignore) — they are not checked into the repository.
The project includes a Docker setup for local container-based development.
docker compose up --buildThis starts:
- FastAPI on
http://localhost:8000 - PostgreSQL on the internal Docker network, with a health check gating API startup
The API container runs as a non-root user and includes a built-in container health check against /health.
Before using this beyond local development: replace the default
POSTGRES_PASSWORDandJWT_SECRET_KEYvalues indocker-compose.ymlwith real secrets supplied via environment variables, and disable or scopeStrict-Transport-Securityappropriately if not served over HTTPS.
Security checks are integrated into GitHub Actions (.github/workflows/security.yml):
Code
|
+--> Ruff (lint)
|
+--> Bandit (SAST)
|
+--> Pytest
|
+--> Coverage (>= 85%)
|
+--> pip-audit (dependency scan)
|
+--> Gitleaks (secret scanning)
|
v
Security CI
- Automated unit/integration testing
- Minimum 85% test coverage enforced
- Ruff code quality checks
- Bandit security analysis
- Dependency vulnerability auditing with pip-audit
- Secret detection with Gitleaks
Current project validation:
Tests: 34 passed
Coverage: 88.74%
CI Status: Passing
The Streamlit dashboard is intentionally excluded from the backend coverage calculation, as it is a UI layer rather than API/security logic.
The project uses pytest for automated testing. The suite covers:
- Public endpoint behavior (
/,/health) - Authentication (valid, invalid, and missing tokens)
- Access-token and refresh-token validation
- Refresh-token rotation and reuse rejection
- Logout and token revocation
- RBAC (analyst vs. admin access)
- Security headers
- Audit logging
- Incident creation and retrieval
- Incident ownership and cross-user access denial (BOLA/IDOR protection)
- Request ID correlation
- Failed-login and targeted-account detection rules
- Security log parsing
- Security report generation
python -m pytest -v
python -m pytest -v --cov=src --cov-report=term-missing --cov-fail-under=85Current result:
34 passed
88.74% coverage
| Technology | Purpose |
|---|---|
| Python 3.12 | Application language |
| FastAPI | REST API framework |
| Uvicorn | ASGI server |
| PyJWT | JWT authentication |
| pwdlib | Password hashing |
| Argon2 | Password hashing algorithm |
| SQLAlchemy | Database ORM |
| Alembic | Database migrations |
| SlowAPI | API rate limiting |
| Streamlit | SOC dashboard |
| Docker | Containerized deployment |
| Pytest | Automated testing |
| Ruff | Code quality / linting |
| Bandit | Python security analysis (SAST) |
| pip-audit | Dependency vulnerability scanning |
| Gitleaks | Secret detection |
| GitHub Actions | CI/CD security automation |
Secure-REST-API-DevSecOps/
│
├── .github/
│ └── workflows/
│ └── security.yml
│
├── src/
│ ├── dashboard/
│ │ ├── __init__.py
│ │ └── app.py
│ │
│ ├── security/
│ │ ├── __init__.py
│ │ ├── audit.py
│ │ ├── auth.py
│ │ ├── incidents.py
│ │ ├── jwt_config.py
│ │ ├── middleware.py
│ │ ├── request_id.py
│ │ ├── schemas.py
│ │ └── users.py
│ │
│ ├── security_monitoring/
│ │ ├── __init__.py
│ │ ├── alert_engine.py
│ │ ├── log_parser.py
│ │ ├── monitor.py
│ │ └── report_generator.py
│ │
│ ├── database.py
│ ├── dependencies.py
│ ├── logging_config.py
│ ├── main.py
│ └── models.py
│
├── tests/
│ ├── conftest.py
│ ├── test_security.py
│ └── test_security_monitoring.py
│
├── migrations/
│ └── versions/
│
├── scripts/
│ └── seed_admin.py
│
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
│
├── .coveragerc
├── .gitignore
├── pyproject.toml
├── pytest.ini
├── requirements.txt
├── requirements-dev.txt
└── README.md
reports/andlogs/are created automatically at runtime and are not part of the committed repository structure.
git clone https://github.com/Shumii98/Secure-REST-API-DevSecOps.git
cd Secure-REST-API-DevSecOps
python -m venv .venv
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
python -m pip install -r requirements-dev.txtCreate a local .env file with the required configuration (see .env.example if present), and never commit it — it's excluded via .gitignore.
uvicorn src.main:app --reload- API:
http://127.0.0.1:8000 - Interactive docs (Swagger UI):
http://127.0.0.1:8000/docs
python -m src.security_monitoring.monitorSecurity log → Log parser → Alert engine → Security report
Output: reports/security_report.json
After generating the monitoring report:
streamlit run .\src\dashboard\app.pyOpen http://localhost:8501.
A failed authentication event can be traced end-to-end through the monitoring pipeline:
1. Authentication failure
|
v
2. Structured JSON security log written
|
v
3. Request ID assigned and correlated
|
v
4. Audit record created in the database
|
v
5. Monitoring engine analyzes the event
|
v
6. Detection threshold reached
|
v
7. SOC alert generated
|
v
8. Alert displayed in the dashboard
This demonstrates the relationship between prevention, logging, detection, and investigation in an application security context.
Known gaps, tracked honestly for transparency:
- Admin visibility into all incidents (currently every role, including admin, only sees its own)
-
PATCH/DELETEincident endpoints with authorization tests - Move Docker Compose secrets (
POSTGRES_PASSWORD,JWT_SECRET_KEY) to environment variables with a.env.example - Make
Strict-Transport-Securityconditional on HTTPS deployment - Validate/sanitize client-supplied
X-Request-IDvalues (length, character set) - Add Trivy container image scanning and SBOM generation to CI
- Add a PostgreSQL integration-test job in CI (currently SQLite-only in tests)
- Secure API development
- Authentication and authorization (RBAC + object-level)
- JWT security and token lifecycle management
- Password security
- Rate limiting
- Security headers
- Audit logging and structured logging
- Correlation IDs
- Incident management
- Security monitoring and detection engineering
- Alert generation and SOC workflows
- Containerized deployment
- DevSecOps and CI security gates
- Dependency and secret vulnerability scanning
- Automated security testing
This project was designed to demonstrate security engineering and SOC-oriented capabilities beyond a basic CRUD API:
Secure Development + Application Security + Detection Engineering
+ Security Monitoring + Incident Management + DevSecOps Automation
The result is a practical, security-focused application demonstrating both preventive security controls and security operations capabilities — while transparently tracking what's still in progress.
Shumaila M.S. Information Security Cybersecurity | SOC | Application Security | DevSecOps
GitHub: https://github.com/Shumii98






