A secure Flask REST API demonstrating modern API security techniques.
- Overview
- Project Structure
- Requirements
- Obtain the Project
- Install Dependencies
- Run the API
- Swagger Documentation
- Authentication Methods
- API Endpoints
- Testing via PowerShell
- Validation Tests
- Stopping the Server
- Notes
This project implements a secure REST API using the Flask framework.
It demonstrates several modern API security mechanisms including API Key authentication, GitHub OAuth2 authentication, HTTPS encryption, and interactive API documentation using Swagger.
Features:
- CRUD API for managing items
- HTTPS using a self-signed SSL certificate
- API Key authentication
- GitHub OAuth2 login
- Interactive Swagger documentation
- Input validation and proper error handling
- In-memory storage (no external database) This project demonstrates multiple authentication methods and secure API practices.
secureAPI/
│
├── app.py
├── jwt_app.py
├── key_manager.py
├── swagger.yaml
├── requirements.txt
│
├── cert/
│ ├── cert.pem
│ └── key.pem
│
└── README.md
- Windows
- Python 3.12+
- PowerShell
You can either download the project archive or clone the repository from GitHub.
- Download the project
.zipfile. - Extract the archive.
- Open the extracted folder in your terminal.
git clone https://github.com/QuantumDevPro/secure-flask-api-CYB350
cd secure-flask-api-CYB350Before installing the project dependencies, create and activate a Python virtual environment.
From the project root directory:
python -m venv venvOn Windows PowerShell:
.\venv\Scripts\ActivateAfter activation, your terminal prompt should show (venv).
With the virtual environment activated, install the required packages:
pip install -r requirements.txtThis installs the required libraries:
- Flask
- Flasgger
- Authlib
- Flask-Limiter
- requests
Start the server:
python app.pyExpected output:
Running on https://127.0.0.1:5000
Because the API uses a self-signed SSL certificate, your browser will show a warning.
Click:
Advanced → Proceed
This is normal for local development.
Open the interactive documentation:
https://127.0.0.1:5000/docs
Before testing endpoints:
- Click the Authorize button in Swagger.
- Enter the API key:
secret_key
This authorizes your browser to access protected endpoints.
Swagger allows you to:
- Explore endpoints
- Send test requests
- View request/response models
- Debug the API interactively
OpenAPI specification:
https://127.0.0.1:5000/swagger.json
This API demonstrates three authentication methods.
Protected endpoints require an API key.
Required header:
X-API-Key: secret_key
Routes excluded from API key validation:
/
/docs
/swagger.json
/login
/authorize
To enable GitHub OAuth authentication, you must create a GitHub OAuth application and obtain a Client ID and Client Secret.
If you do not already have one, create a GitHub account:
https://github.com/signup
- Open GitHub Developer Settings:
https://github.com/settings/developers
-
Select OAuth Apps.
-
Click New OAuth App.
Fill in the application details:
| Field | Value |
|---|---|
| Application name | SecureAPI Lab |
| Homepage URL | https://127.0.0.1:5000 |
| Authorization callback URL | https://127.0.0.1:5000/authorize |
After creating the application, GitHub will provide:
Client ID
Client Secret
Open app.py and replace the placeholder values with your credentials:
oauth.register(
name='github',
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
access_token_url='https://github.com/login/oauth/access_token',
authorize_url='https://github.com/login/oauth/authorize',
api_base_url='https://api.github.com/',
client_kwargs={
'scope': 'user:email'
}
)Save the file after updating the credentials.
Open the login endpoint in your browser:
https://127.0.0.1:5000/login
You will be redirected to GitHub to authorize the application.
After approving access, GitHub will redirect back to the API and return a success response.
Example response:
{
"github_user": "QuantumDevPro",
"message": "OAuth2 Authentication Successful"
}The API also supports JSON Web Token (JWT) authentication for accessing protected endpoints.
JWT authentication works by issuing a signed token after a successful login.
The client must include this token in the Authorization header when accessing protected routes.
Send a login request with valid credentials.
$r = Invoke-RestMethod -Uri "http://127.0.0.1:5000/login" `
-Method POST `
-ContentType "application/json" `
-Body '{"username":"admin","password":"1234"}'Extract the token:
$token = $r.access_tokenUse the token in the Authorization header.
Invoke-RestMethod -Uri "http://127.0.0.1:5000/protected" `
-Headers @{Authorization="Bearer $token"}Expected response:
{
"message": "Hello admin, you are authorized!"
}If the token is missing, invalid, or expired, the API will deny access to the endpoint.
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Health check |
| GET | /items |
Get all items |
| GET | /items/<id> |
Get item by ID |
| POST | /items |
Create item |
| PUT | /items/<id> |
Update item |
| DELETE | /items/<id> |
Delete item |
| GET | /login |
GitHub OAuth login |
| GET | /authorize |
OAuth callback |
Because the API uses HTTPS with a self-signed certificate, PowerShell must bypass certificate validation.
Run once per session:
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint,
X509Certificate certificate,
WebRequest request,
int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicyInvoke-RestMethod https://127.0.0.1:5000/Expected:
{
"message": "Secure API is running!",
"status": "ok"
}Invoke-RestMethod -Uri https://127.0.0.1:5000/items `
-Method POST `
-Headers @{ "X-API-Key"="secret_key" } `
-ContentType "application/json" `
-Body '{"name":"sword","quantity":5}'Invoke-RestMethod https://127.0.0.1:5000/items `
-Headers @{ "X-API-Key"="secret_key" }Invoke-RestMethod -Uri https://127.0.0.1:5000/items/1 `
-Method PUT `
-Headers @{ "X-API-Key"="secret_key" } `
-ContentType "application/json" `
-Body '{"quantity":99}'Invoke-RestMethod -Uri https://127.0.0.1:5000/items/1 `
-Method DELETE `
-Headers @{ "X-API-Key"="secret_key_key" }Using Swagger /docs, try these invalid requests.
{
"name": "bow"
}{
"name": "arrows",
"quantity": -5
}A secure API must fail gracefully and predictably.
Press:
Ctrl + C
in the terminal running the API.
Ensure the SSL certificate folder exists:
cert/cert.pem
cert/key.pem
These certificates enable HTTPS for local development.
Important security note
The OAuth client_secret should never be committed in production environments.
It is included here only for educational purposes, and it was deleted from the account already.