244 lines
6.9 KiB
Markdown
244 lines
6.9 KiB
Markdown
# FastAPI Keycloak Integration with React Frontend
|
|
|
|
## Table of Contents
|
|
|
|
- [Introduction](#introduction)
|
|
- [Features](#features)
|
|
- [Project Structure](#project-structure)
|
|
- [Prerequisites](#prerequisites)
|
|
- [Installation](#installation)
|
|
- [Configuration](#configuration)
|
|
- [Usage](#usage)
|
|
- [Authentication Flow](#authentication-flow)
|
|
- [Development](#development)
|
|
- [Contributing](#contributing)
|
|
- [License](#license)
|
|
|
|
## Introduction
|
|
|
|
This project provides a full-stack authentication solution using FastAPI as the backend, React (with TypeScript and Tailwind CSS) as the frontend, and Keycloak as the identity provider. Authentication is handled securely using HTTP-only cookies to protect tokens from XSS attacks.
|
|
|
|
## Features
|
|
|
|
- **FastAPI Backend**: A modern, fast web framework for building APIs with Python 3.12+
|
|
- **React Frontend**: TypeScript-based React application with Tailwind CSS for styling
|
|
- **Keycloak Integration**: Enterprise-grade identity management with OAuth2/OpenID Connect
|
|
- **Secure Cookie-Based Auth**: HTTP-only cookies protect access tokens from XSS attacks
|
|
- **Dockerized Setup**: Full Docker Compose setup including Keycloak, backend, and frontend
|
|
- **Poetry for Python Dependencies**: Simplified Python dependency management
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
.
|
|
├── .env.example # Environment variables template
|
|
├── docker-compose.yaml # Production Docker Compose
|
|
├── docker-compose.dev.yaml # Development Docker Compose
|
|
├── README.md
|
|
├── backend/
|
|
│ ├── Dockerfile
|
|
│ ├── pyproject.toml
|
|
│ ├── poetry.lock
|
|
│ └── src/
|
|
│ ├── __init__.py
|
|
│ ├── config.py # Keycloak & cookie settings
|
|
│ ├── controller.py # Request handlers
|
|
│ ├── main.py # FastAPI app with CORS
|
|
│ ├── models.py # Pydantic models
|
|
│ └── service.py # Keycloak auth service
|
|
└── frontend/
|
|
├── Dockerfile
|
|
├── nginx.conf # Production nginx config
|
|
├── package.json
|
|
├── tsconfig.json
|
|
├── tailwind.config.js
|
|
├── vite.config.ts
|
|
└── src/
|
|
├── App.tsx
|
|
├── main.tsx
|
|
├── index.css
|
|
├── components/ # Reusable UI components
|
|
├── context/ # React Context (AuthContext)
|
|
├── hooks/ # Custom hooks (useAuth)
|
|
├── pages/ # Page components
|
|
├── services/ # API service layer
|
|
└── types/ # TypeScript types
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
- [Docker](https://www.docker.com/get-started) and [Docker Compose](https://docs.docker.com/compose/install/)
|
|
- [Node.js 20+](https://nodejs.org/) (for local frontend development)
|
|
- [Python 3.12+](https://www.python.org/downloads/) (for local backend development)
|
|
- [Git](https://git-scm.com/)
|
|
|
|
## Installation
|
|
|
|
1. **Clone the Repository**
|
|
|
|
```bash
|
|
git clone https://github.com/your-repo/fastapi-keycloak.git
|
|
cd fastapi-keycloak
|
|
```
|
|
|
|
2. **Copy Environment Variables File**
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
3. **Configure Environment Variables**
|
|
|
|
Open the `.env` file and update the following variables:
|
|
|
|
```env
|
|
# Keycloak Configuration
|
|
KEYCLOAK_SERVER_URL=http://localhost:8081/
|
|
KEYCLOAK_REALM=your-realm
|
|
KEYCLOAK_CLIENT_ID=your-client-id
|
|
KEYCLOAK_CLIENT_SECRET=your-client-secret
|
|
|
|
# Frontend URL (for CORS and redirects)
|
|
FRONTEND_URL=http://localhost:3000
|
|
|
|
# Cookie Configuration
|
|
COOKIE_SECURE=false # Set to true in production with HTTPS
|
|
COOKIE_SAMESITE=lax
|
|
COOKIE_MAX_AGE=3600
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Setting Up Keycloak
|
|
|
|
1. **Start the Services**
|
|
|
|
```bash
|
|
docker-compose up keycloak -d
|
|
```
|
|
|
|
2. **Access the Keycloak Admin Console**
|
|
|
|
Open `http://localhost:8081/` and login with:
|
|
- Username: `admin`
|
|
- Password: `admin`
|
|
|
|
3. **Create a New Realm**
|
|
|
|
- Click "Create Realm"
|
|
- Name it (e.g., `my-app`)
|
|
- Click "Create"
|
|
|
|
4. **Create a New Client**
|
|
|
|
- Go to Clients → Create client
|
|
- Client ID: e.g., `my-app-client`
|
|
- Client Protocol: `openid-connect`
|
|
- Click Next
|
|
- Enable "Client authentication" (confidential)
|
|
- Enable "Standard flow" and "Direct access grants"
|
|
- Click Next
|
|
- Valid redirect URIs: `http://localhost:8080/*`
|
|
- Web origins: `http://localhost:3000`
|
|
- Click Save
|
|
|
|
5. **Get Client Secret**
|
|
|
|
- Go to Credentials tab
|
|
- Copy the "Client secret"
|
|
- Update your `.env` file
|
|
|
|
6. **Create a Test User**
|
|
|
|
- Go to Users → Add user
|
|
- Username: `testuser`
|
|
- Email: `test@example.com`
|
|
- Click Create
|
|
- Go to Credentials tab → Set password
|
|
- Disable "Temporary"
|
|
|
|
## Usage
|
|
|
|
### Running with Docker (Production)
|
|
|
|
```bash
|
|
# Start all services
|
|
docker-compose up --build
|
|
|
|
# Services will be available at:
|
|
# - Frontend: http://localhost:3000
|
|
# - Backend API: http://localhost:8080
|
|
# - Keycloak: http://localhost:8081
|
|
```
|
|
|
|
### Running with Docker (Development)
|
|
|
|
For development with hot-reload on the backend:
|
|
|
|
```bash
|
|
# Start Keycloak and Backend only
|
|
docker-compose -f docker-compose.dev.yaml up --build
|
|
|
|
# In another terminal, start the frontend dev server
|
|
cd frontend
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
## Authentication Flow
|
|
|
|
1. **User clicks "Login"** → Frontend redirects to `/api/login`
|
|
2. **Backend redirects to Keycloak** → User authenticates with Keycloak
|
|
3. **Keycloak redirects back** → Backend receives authorization code at `/api/callback`
|
|
4. **Backend exchanges code for token** → Sets HTTP-only cookie with access token
|
|
5. **Backend redirects to frontend** → User lands on `/dashboard`
|
|
6. **Frontend calls `/api/auth/me`** → Backend validates cookie and returns user info
|
|
|
|
### API Endpoints
|
|
|
|
| Endpoint | Method | Auth | Description |
|
|
|----------|--------|------|-------------|
|
|
| `/api` | GET | No | Welcome message and docs link |
|
|
| `/api/login` | GET | No | Initiates OAuth2 login flow |
|
|
| `/api/callback` | GET | No | OAuth2 callback (sets cookie) |
|
|
| `/api/auth/me` | GET | Cookie | Get current user info |
|
|
| `/api/auth/logout` | POST | Cookie | Clear auth cookie |
|
|
| `/api/protected` | GET | Bearer | Protected endpoint (token in header) |
|
|
| `/docs` | GET | No | Swagger API documentation |
|
|
|
|
## Development
|
|
|
|
### Backend Development
|
|
|
|
```bash
|
|
cd backend
|
|
poetry install
|
|
poetry run uvicorn src.main:app --reload --port 8080
|
|
```
|
|
|
|
### Frontend Development
|
|
|
|
```bash
|
|
cd frontend
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
The frontend dev server runs on `http://localhost:3000` and proxies `/api` requests to the backend.
|
|
|
|
### Environment Variables
|
|
|
|
See `.env.example` for all available configuration options:
|
|
|
|
- **Keycloak settings**: Server URL, realm, client ID/secret
|
|
- **Frontend URL**: For CORS and OAuth redirects
|
|
- **Cookie settings**: Security options for the auth cookie
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please feel free to submit a pull request or open an issue.
|
|
|
|
## License
|
|
|
|
This project is licensed under the MIT License.
|