This repository contains a full-stack proof-of-concept demonstrating how to secure a modern React frontend and a FastAPI backend using Keycloak Identity and Access Management.
The entire stack is containerized using Docker and is served securely behind an Nginx HTTPS reverse proxy to mirror a production environment and avoid CORS complexity.
graph TD
%% Define Styles
classDef proxy fill:#4bc87fd9,stroke:#3bb16f,stroke-width:2px,color:white;
classDef frontend fill:#61dafb,stroke:#4faecc,stroke-width:2px,color:white;
classDef backend fill:#306998,stroke:#26557a,stroke-width:2px,color:white;
classDef auth fill:#e95420,stroke:#d04b1c,stroke-width:2px,color:white;
classDef db fill:#336791,stroke:#2a5375,stroke-width:2px,color:white;
classDef nosql fill:#4db33d,stroke:#3b912c,stroke-width:2px,color:white;
%% Nodes
User(("🧑💻 User Browser"))
subgraph "Docker Compose Stack"
Nginx["Nginx<br/>(Reverse Proxy)"]:::proxy
React["React<br/>(Frontend)"]:::frontend
FastAPI["FastAPI<br/>(Backend API)"]:::backend
Keycloak["Keycloak<br/>(Identity Provider)"]:::auth
subgraph "Data Layer"
PostgreSQL[("PostgreSQL<br/>(Auth DB)")]:::db
MongoDB[("MongoDB<br/>(App DB)")]:::nosql
end
end
%% Routing Flow
User -- "HTTPS" --> Nginx
Nginx -- "/ (Port 3000)" --> React
Nginx -- "/api/ (Port 8000)" --> FastAPI
Nginx -- "/auth/ (Port 8080)" --> Keycloak
%% Application Logic Flow
React -. "Login Redirect" .-> Keycloak
React == "API Request + JWT" ==> FastAPI
%% Database Flow
Keycloak --> PostgreSQL
FastAPI --> MongoDB
FastAPI -. "Fetch JWKS" .-> Keycloak
- Reverse Proxy (Nginx): Terminates SSL (
https://localhost) and routes traffic to the appropriate internal services. - Identity Provider (Keycloak): Handles user registration, login, and token issuance. Backed by PostgreSQL.
- Frontend (React/Vite): Client application that uses the
keycloak-jsadapter to manage user sessions and interact with the API. - Backend API (FastAPI): Python server that cryptographically verifies Keycloak JWTs before granting access to MongoDB records.
- Docker & Docker Compose installed.
Run the following command in the root of the repository to build and start all containers in detached mode:
docker compose up -dNote: The Nginx container will automatically generate self-signed SSL certificates upon building.
Once the containers are healthy (this may take a few seconds for PostgreSQL and Keycloak to fully initialize), navigate to:
Because we are using self-signed development certificates, your browser will display a "Not Secure" warning.
- In Chrome: Click
Advanced->Proceed to localhost (unsafe). - In Firefox: Click
Advanced->Accept the Risk and Continue.
The Keycloak realm (myrealm) is automatically imported on startup. It comes pre-configured with a test user:
- Username:
testuser - Password:
password
You can also use the signup form to create a brand new user account.
Two database management UIs are spun up alongside the stack:
- pgAdmin (PostgreSQL): http://localhost:5050 (Login:
admin@admin.com/password) - Mongo Express (MongoDB): http://localhost:8081 (No login required)
Detailed documentation regarding the authentication flow, OAuth grant types, Keycloak configurations, and the Nginx proxy setup is available via MkDocs.
To view the documentation locally:
- Spin up the docs container:
docker compose -f docker-compose.docs.yml up -d
- Navigate to http://localhost:8005
- When finished reading, stop the docs container:
docker compose -f docker-compose.docs.yml down
To stop and remove all running containers, networks, and recreate your local environment state, run:
docker compose downIf you want to completely wipe the persistent database volumes (destroying all created users and To-Do items) so you can start from a completely clean slate next time, append the -v flag:
docker compose down -v