update configuration docker setup for data platform
This commit is contained in:
325
03-apiservice/KEYCLOAK-SETUP.md
Normal file
325
03-apiservice/KEYCLOAK-SETUP.md
Normal file
@@ -0,0 +1,325 @@
|
||||
# Keycloak Setup Guide for API Service Authentication
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Keycloak must be running at `http://localhost:8085`
|
||||
2. PostgreSQL database must have `keycloak` database created
|
||||
3. API Service must have Keycloak configuration in `.env`
|
||||
|
||||
## Step 1: Restart Infrastructure to Create Keycloak Database
|
||||
|
||||
```bash
|
||||
cd 01-infra
|
||||
docker compose down
|
||||
docker compose --env-file ../.env.global up -d
|
||||
```
|
||||
|
||||
Wait for Keycloak to initialize (check logs):
|
||||
```bash
|
||||
docker logs keycloak -f
|
||||
```
|
||||
|
||||
Look for: `Keycloak ... started`
|
||||
|
||||
## Step 2: Access Keycloak Admin Console
|
||||
|
||||
1. Open browser: `http://localhost:8085/admin`
|
||||
2. Login credentials:
|
||||
- **Username**: `admin`
|
||||
- **Password**: `admin_secret_pass_2026`
|
||||
|
||||
## Step 3: Create Client for API Service
|
||||
|
||||
### 3.1 Navigate to Clients
|
||||
1. In left sidebar, click **Clients**
|
||||
2. Click **Create client** button
|
||||
|
||||
### 3.2 General Settings
|
||||
- **Client type**: `OpenID Connect`
|
||||
- **Client ID**: `apiservice`
|
||||
- Click **Next**
|
||||
|
||||
### 3.3 Capability Config
|
||||
- **Client authentication**: `ON` (toggle to enable)
|
||||
- **Authorization**: `OFF`
|
||||
- **Authentication flow**:
|
||||
- ✅ Standard flow
|
||||
- ✅ Direct access grants
|
||||
- ❌ Implicit flow (uncheck)
|
||||
- ❌ Service accounts roles (uncheck)
|
||||
- Click **Next**
|
||||
|
||||
### 3.4 Login Settings
|
||||
Fill in the following URLs:
|
||||
|
||||
**Root URL**:
|
||||
```
|
||||
http://localhost:8040
|
||||
```
|
||||
|
||||
**Home URL**:
|
||||
```
|
||||
http://localhost:8040/apiservice/
|
||||
```
|
||||
|
||||
**Valid redirect URIs** (add both):
|
||||
```
|
||||
http://localhost:8040/apiservice/auth/callback
|
||||
https://ai.sriphat.com/apiservice/auth/callback
|
||||
```
|
||||
|
||||
**Valid post logout redirect URIs** (add both):
|
||||
```
|
||||
http://localhost:8040/apiservice/
|
||||
https://ai.sriphat.com/apiservice/
|
||||
```
|
||||
|
||||
**Web origins** (add both):
|
||||
```
|
||||
http://localhost:8040
|
||||
https://ai.sriphat.com
|
||||
```
|
||||
|
||||
Click **Save**
|
||||
|
||||
### 3.5 Get Client Secret
|
||||
1. Go to **Credentials** tab
|
||||
2. Copy the **Client secret** value
|
||||
3. Save it - you'll need it for the `.env` file
|
||||
|
||||
## Step 4: Configure API Service
|
||||
|
||||
### 4.1 Create/Update `.env` file in `03-apiservice`
|
||||
|
||||
```bash
|
||||
cd ../03-apiservice
|
||||
```
|
||||
|
||||
Create `.env` file with:
|
||||
|
||||
```bash
|
||||
# Application
|
||||
APP_NAME=APIsService
|
||||
ROOT_PATH=/apiservice
|
||||
|
||||
# Timezone
|
||||
TIMEZONE=Asia/Bangkok
|
||||
|
||||
# PostgreSQL Database
|
||||
DB_HOST=postgres
|
||||
DB_PORT=5432
|
||||
DB_USER=postgres
|
||||
DB_PASSWORD=Secure_Hospital_Pass_2026
|
||||
DB_NAME=postgres
|
||||
DB_SSLMODE=prefer
|
||||
|
||||
# Supabase (if not using, keep dummy values)
|
||||
SUPABASE_DB_HOST=localhost
|
||||
SUPABASE_DB_PORT=5432
|
||||
SUPABASE_DB_USER=postgres
|
||||
SUPABASE_DB_PASSWORD=dummy
|
||||
SUPABASE_DB_NAME=postgres
|
||||
SUPABASE_DB_SSLMODE=disable
|
||||
SUPABASE_API_URL=http://localhost:8000
|
||||
SUPABASE_API_KEY=dummy
|
||||
|
||||
# Admin Authentication
|
||||
ADMIN_SECRET_KEY=apiservice_admin_secret_2026
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=change_me_2026
|
||||
|
||||
# API Key Encryption
|
||||
API_KEY_ENC_SECRET=dev_encryption_secret_2026
|
||||
|
||||
# Keycloak Authentication
|
||||
KEYCLOAK_SERVER_URL=http://keycloak:8080
|
||||
KEYCLOAK_REALM=master
|
||||
KEYCLOAK_CLIENT_ID=apiservice
|
||||
KEYCLOAK_CLIENT_SECRET=<PASTE_YOUR_CLIENT_SECRET_HERE>
|
||||
KEYCLOAK_REDIRECT_URI=http://localhost:8040/apiservice/auth/callback
|
||||
```
|
||||
|
||||
**Important**: Replace `<PASTE_YOUR_CLIENT_SECRET_HERE>` with the actual secret from Step 3.5
|
||||
|
||||
## Step 5: Create Test User in Keycloak
|
||||
|
||||
### 5.1 Create User
|
||||
1. In Keycloak Admin, go to **Users**
|
||||
2. Click **Add user**
|
||||
3. Fill in:
|
||||
- **Username**: `testuser`
|
||||
- **Email**: `test@sriphat.local`
|
||||
- **First name**: `Test`
|
||||
- **Last name**: `User`
|
||||
- **Email verified**: `ON` (toggle)
|
||||
4. Click **Create**
|
||||
|
||||
### 5.2 Set Password
|
||||
1. Go to **Credentials** tab
|
||||
2. Click **Set password**
|
||||
3. Fill in:
|
||||
- **Password**: `password`
|
||||
- **Password confirmation**: `password`
|
||||
- **Temporary**: `OFF` (toggle off)
|
||||
4. Click **Save**
|
||||
5. Confirm by clicking **Save password**
|
||||
|
||||
## Step 6: Rebuild and Restart API Service
|
||||
|
||||
```bash
|
||||
cd 03-apiservice
|
||||
docker compose down
|
||||
docker compose --env-file ../.env up --build -d
|
||||
```
|
||||
|
||||
Check logs:
|
||||
```bash
|
||||
docker logs apiservice -f
|
||||
```
|
||||
|
||||
Look for successful startup without errors.
|
||||
|
||||
## Step 7: Test Authentication Flow
|
||||
|
||||
### 7.1 Access Landing Page
|
||||
1. Open browser: `http://localhost:8040/apiservice/`
|
||||
2. You should be redirected to Keycloak login page
|
||||
|
||||
### 7.2 Login
|
||||
1. Enter credentials:
|
||||
- **Username**: `testuser`
|
||||
- **Password**: `password`
|
||||
2. Click **Sign In**
|
||||
|
||||
### 7.3 Verify Success
|
||||
1. You should be redirected back to the landing page
|
||||
2. You should see your name in the top-right corner: "👤 Test User"
|
||||
3. You should see a **Logout** button
|
||||
|
||||
### 7.4 Test Protected Pages
|
||||
Try accessing:
|
||||
- `/apiservice/` - Landing page (requires auth)
|
||||
- `/apiservice/docs` - API docs (requires auth)
|
||||
- `/apiservice/data-management/finance` - Finance page (requires auth)
|
||||
|
||||
All should work without redirecting to login again.
|
||||
|
||||
### 7.5 Test API Endpoints (Should NOT require Keycloak auth)
|
||||
```bash
|
||||
# API endpoints use API Key authentication, not Keycloak
|
||||
curl -X GET http://localhost:8040/apiservice/api/v1/health
|
||||
```
|
||||
|
||||
This should work without Keycloak authentication.
|
||||
|
||||
### 7.6 Test Logout
|
||||
1. Click **Logout** button
|
||||
2. You should be logged out from Keycloak
|
||||
3. Accessing any protected page should redirect to login again
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "access_denied" in Keycloak logs
|
||||
**Cause**: Client not configured correctly or client secret mismatch
|
||||
|
||||
**Solution**:
|
||||
1. Verify client ID is exactly `apiservice`
|
||||
2. Verify client secret in `.env` matches Keycloak
|
||||
3. Verify redirect URIs are correct
|
||||
4. Restart API service after changing `.env`
|
||||
|
||||
### Error: "SessionMiddleware must be installed"
|
||||
**Cause**: Middleware order is incorrect
|
||||
|
||||
**Solution**: Already fixed in `app/main.py` - SessionMiddleware is added after WebAuthenticationMiddleware
|
||||
|
||||
### Error: "Invalid redirect_uri"
|
||||
**Cause**: Redirect URI not in Keycloak's allowed list
|
||||
|
||||
**Solution**:
|
||||
1. Go to Keycloak → Clients → apiservice → Settings
|
||||
2. Add the exact redirect URI to "Valid redirect URIs"
|
||||
3. Make sure it matches `KEYCLOAK_REDIRECT_URI` in `.env`
|
||||
|
||||
### Error: Connection refused to Keycloak
|
||||
**Cause**: Keycloak not running or wrong URL
|
||||
|
||||
**Solution**:
|
||||
1. Check Keycloak is running: `docker ps | grep keycloak`
|
||||
2. Verify `KEYCLOAK_SERVER_URL=http://keycloak:8080` (use container name, not localhost)
|
||||
3. Verify both services are on same Docker network
|
||||
|
||||
## Production Deployment
|
||||
|
||||
For production deployment:
|
||||
|
||||
1. **Use HTTPS**:
|
||||
```bash
|
||||
KEYCLOAK_REDIRECT_URI=https://ai.sriphat.com/apiservice/auth/callback
|
||||
```
|
||||
|
||||
2. **Update Keycloak Client**:
|
||||
- Add production redirect URIs
|
||||
- Remove localhost URIs
|
||||
|
||||
3. **Secure Cookies**:
|
||||
- SessionMiddleware should use `secure=True, httponly=True, samesite='lax'`
|
||||
|
||||
4. **Use Nginx Proxy Manager**:
|
||||
- Configure SSL certificates
|
||||
- Set up proper reverse proxy rules
|
||||
|
||||
5. **Environment Variables**:
|
||||
- Use Docker secrets or external secret management
|
||||
- Never commit `.env` with real secrets to git
|
||||
|
||||
## Security Notes
|
||||
|
||||
1. **Client Secret**: Keep this secret! Never commit to git
|
||||
2. **Session Secret**: Use strong random value for `ADMIN_SECRET_KEY`
|
||||
3. **HTTPS**: Always use HTTPS in production
|
||||
4. **Token Expiration**: Configure appropriate token lifetimes in Keycloak
|
||||
5. **CORS**: Restrict `allow_origins` to known domains only
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
User Browser
|
||||
↓
|
||||
↓ (1) Access protected page
|
||||
↓
|
||||
API Service (FastAPI)
|
||||
↓
|
||||
↓ (2) Check session - not authenticated
|
||||
↓
|
||||
↓ (3) Redirect to Keycloak login
|
||||
↓
|
||||
Keycloak (OAuth2/OIDC)
|
||||
↓
|
||||
↓ (4) User enters credentials
|
||||
↓
|
||||
↓ (5) Redirect back with auth code
|
||||
↓
|
||||
API Service
|
||||
↓
|
||||
↓ (6) Exchange code for tokens
|
||||
↓
|
||||
↓ (7) Store user info in session
|
||||
↓
|
||||
↓ (8) Redirect to original page
|
||||
↓
|
||||
User sees protected page with user info
|
||||
```
|
||||
|
||||
## API vs Web Authentication
|
||||
|
||||
| Type | Authentication Method | Protected Routes |
|
||||
|------|----------------------|------------------|
|
||||
| **Web Pages** | Keycloak (OAuth2/OIDC) | `/`, `/docs`, `/data-management/*` |
|
||||
| **API Endpoints** | API Key (Bearer Token) | `/api/v1/*` |
|
||||
| **Admin Panel** | SQLAdmin (Basic Auth) | `/admin/*` |
|
||||
|
||||
This separation allows:
|
||||
- Human users to login via Keycloak for web UI
|
||||
- Applications/services to use API Keys for programmatic access
|
||||
- Admins to manage API keys via separate admin panel
|
||||
Reference in New Issue
Block a user