|
| 1 | +# Keycloak OAuth Configuration for Nextcloud MCP Server |
| 2 | +# |
| 3 | +# This configuration uses Keycloak as the OAuth/OIDC identity provider |
| 4 | +# while still accessing Nextcloud APIs. Nextcloud's user_oidc app validates |
| 5 | +# Keycloak bearer tokens and provisions users automatically. |
| 6 | +# |
| 7 | +# Architecture: Client → Keycloak (OAuth) → MCP Server → Nextcloud (user_oidc validates) → APIs |
| 8 | +# |
| 9 | +# This enables ADR-002 authentication patterns without admin credentials! |
| 10 | + |
| 11 | +# ============================================================================== |
| 12 | +# OAUTH PROVIDER SELECTION |
| 13 | +# ============================================================================== |
| 14 | + |
| 15 | +# OAuth provider: "keycloak" or "nextcloud" (default) |
| 16 | +OAUTH_PROVIDER=keycloak |
| 17 | + |
| 18 | +# ============================================================================== |
| 19 | +# KEYCLOAK CONFIGURATION |
| 20 | +# ============================================================================== |
| 21 | + |
| 22 | +# Keycloak base URL (accessible from MCP server container) |
| 23 | +KEYCLOAK_URL=http://keycloak:8080 |
| 24 | + |
| 25 | +# Keycloak realm name |
| 26 | +KEYCLOAK_REALM=nextcloud-mcp |
| 27 | + |
| 28 | +# OAuth client credentials (from Keycloak realm export or manual configuration) |
| 29 | +KEYCLOAK_CLIENT_ID=nextcloud-mcp-server |
| 30 | +KEYCLOAK_CLIENT_SECRET=mcp-secret-change-in-production |
| 31 | + |
| 32 | +# OIDC discovery URL (auto-constructed from URL + realm, or specify explicitly) |
| 33 | +KEYCLOAK_DISCOVERY_URL=http://keycloak:8080/realms/nextcloud-mcp/.well-known/openid-configuration |
| 34 | + |
| 35 | +# ============================================================================== |
| 36 | +# NEXTCLOUD CONFIGURATION |
| 37 | +# ============================================================================== |
| 38 | + |
| 39 | +# Nextcloud URL (accessible from MCP server container) |
| 40 | +# Used for API access - Keycloak tokens are validated by user_oidc app |
| 41 | +NEXTCLOUD_HOST=http://app:80 |
| 42 | + |
| 43 | +# MCP server URL (for OAuth redirect URIs) |
| 44 | +# This is the publicly accessible URL that OAuth clients connect to |
| 45 | +NEXTCLOUD_MCP_SERVER_URL=http://localhost:8002 |
| 46 | + |
| 47 | +# Public Keycloak issuer URL (accessible from OAuth clients) |
| 48 | +# If clients access Keycloak via a different URL than the internal one, |
| 49 | +# set this to the public URL for OAuth flows |
| 50 | +NEXTCLOUD_PUBLIC_ISSUER_URL=http://localhost:8888 |
| 51 | + |
| 52 | +# ============================================================================== |
| 53 | +# REFRESH TOKEN STORAGE (ADR-002 Tier 1: Offline Access) |
| 54 | +# ============================================================================== |
| 55 | + |
| 56 | +# Enable offline_access scope to get refresh tokens |
| 57 | +ENABLE_OFFLINE_ACCESS=true |
| 58 | + |
| 59 | +# Encryption key for storing refresh tokens (generate with instructions below) |
| 60 | +# IMPORTANT: Keep this secret! Tokens are encrypted at rest using this key. |
| 61 | +# |
| 62 | +# Generate a key: |
| 63 | +# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" |
| 64 | +# |
| 65 | +# Example (DO NOT use this in production!): |
| 66 | +# TOKEN_ENCRYPTION_KEY=your-base64-encoded-fernet-key-here |
| 67 | + |
| 68 | +# Path to SQLite database for token storage |
| 69 | +TOKEN_STORAGE_DB=/app/data/tokens.db |
| 70 | + |
| 71 | +# ============================================================================== |
| 72 | +# DOCKER COMPOSE NOTES |
| 73 | +# ============================================================================== |
| 74 | + |
| 75 | +# When running via docker-compose, the mcp-keycloak service is pre-configured |
| 76 | +# with these environment variables. See docker-compose.yml for the full config. |
| 77 | +# |
| 78 | +# Start services: |
| 79 | +# docker-compose up -d keycloak app mcp-keycloak |
| 80 | +# |
| 81 | +# View logs: |
| 82 | +# docker-compose logs -f mcp-keycloak |
| 83 | +# |
| 84 | +# Check Keycloak realm: |
| 85 | +# curl http://localhost:8888/realms/nextcloud-mcp/.well-known/openid-configuration |
| 86 | +# |
| 87 | +# Check user_oidc provider: |
| 88 | +# docker compose exec app php occ user_oidc:provider keycloak |
| 89 | + |
| 90 | +# ============================================================================== |
| 91 | +# KEYCLOAK SETUP VERIFICATION |
| 92 | +# ============================================================================== |
| 93 | + |
| 94 | +# 1. Verify Keycloak is running and realm is imported: |
| 95 | +# curl http://localhost:8888/realms/nextcloud-mcp/.well-known/openid-configuration |
| 96 | +# |
| 97 | +# 2. Verify Nextcloud user_oidc provider is configured: |
| 98 | +# docker compose exec app php occ user_oidc:provider keycloak |
| 99 | +# |
| 100 | +# 3. Test OAuth flow manually: |
| 101 | +# - Get token from Keycloak: |
| 102 | +# curl -X POST "http://localhost:8888/realms/nextcloud-mcp/protocol/openid-connect/token" \ |
| 103 | +# -d "grant_type=password" \ |
| 104 | +# -d "client_id=nextcloud-mcp-server" \ |
| 105 | +# -d "client_secret=mcp-secret-change-in-production" \ |
| 106 | +# -d "username=admin" \ |
| 107 | +# -d "password=admin" \ |
| 108 | +# -d "scope=openid profile email offline_access" |
| 109 | +# |
| 110 | +# - Use token with Nextcloud API: |
| 111 | +# curl -H "Authorization: Bearer <access_token>" \ |
| 112 | +# http://localhost:8080/ocs/v2.php/cloud/capabilities |
| 113 | +# |
| 114 | +# 4. Connect MCP client to server: |
| 115 | +# - Point your MCP client to http://localhost:8002 |
| 116 | +# - Complete OAuth flow via Keycloak (credentials: admin/admin) |
| 117 | +# - Client should receive access token and be able to call MCP tools |
| 118 | + |
| 119 | +# ============================================================================== |
| 120 | +# TROUBLESHOOTING |
| 121 | +# ============================================================================== |
| 122 | + |
| 123 | +# If OAuth flow fails: |
| 124 | +# - Check that Keycloak is accessible: curl http://localhost:8888 |
| 125 | +# - Check that user_oidc provider is configured: docker compose exec app php occ user_oidc:provider keycloak |
| 126 | +# - Check MCP server logs: docker-compose logs mcp-keycloak |
| 127 | +# - Verify redirect URIs match in Keycloak client configuration |
| 128 | +# |
| 129 | +# If token validation fails: |
| 130 | +# - Verify user_oidc has bearer validation enabled (--check-bearer=1) |
| 131 | +# - Check Nextcloud logs: docker compose exec app tail -f /var/www/html/data/nextcloud.log |
| 132 | +# - Verify Keycloak discovery URL is accessible from Nextcloud container: |
| 133 | +# docker compose exec app curl http://keycloak:8080/realms/nextcloud-mcp/.well-known/openid-configuration |
| 134 | +# |
| 135 | +# If offline_access/refresh tokens not working: |
| 136 | +# - Verify TOKEN_ENCRYPTION_KEY is set and valid |
| 137 | +# - Check token storage database: ls -lah /app/data/tokens.db (inside container) |
| 138 | +# - Check that offline_access scope is requested in realm configuration |
0 commit comments