From 2ca6725fc6f85ef4ec7737b1dee802be473f14cd Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Sun, 2 Nov 2025 19:06:59 +0100 Subject: [PATCH] docs: Replace .nextcloud_oauth_client.json references with SQLite storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all references to the JSON file-based OAuth client storage with SQLite database storage in documentation. OAuth client credentials are now stored in the SQLite database instead of .nextcloud_oauth_client.json. Changes: - Update oauth-architecture.md to reference SQLite database - Update jwt-oauth-reference.md credential storage sections - Update oauth-setup.md Docker volume mounts and security best practices - Update oauth-troubleshooting.md file permission → database permission errors - Update configuration.md to remove JSON file chmod instructions - Update troubleshooting.md database permission troubleshooting The code already uses SQLite (RefreshTokenStorage class), so only documentation needed updating. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/configuration.md | 13 ++---------- docs/jwt-oauth-reference.md | 21 +++++++++---------- docs/oauth-architecture.md | 9 ++++---- docs/oauth-setup.md | 14 +++++-------- docs/oauth-troubleshooting.md | 39 +++++++++++++++++------------------ docs/troubleshooting.md | 23 ++++++++++++--------- 6 files changed, 53 insertions(+), 66 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index ab2bd30..72100e8 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -45,8 +45,7 @@ NEXTCLOUD_HOST=https://your.nextcloud.instance.com NEXTCLOUD_OIDC_CLIENT_ID=your-client-id NEXTCLOUD_OIDC_CLIENT_SECRET=your-client-secret -# OAuth Storage and Callback Settings (optional) -NEXTCLOUD_OIDC_CLIENT_STORAGE=.nextcloud_oauth_client.json +# OAuth Callback Settings (optional) NEXTCLOUD_MCP_SERVER_URL=http://localhost:8000 # Leave these EMPTY for OAuth mode @@ -61,7 +60,6 @@ NEXTCLOUD_PASSWORD= | `NEXTCLOUD_HOST` | ✅ Yes | - | Full URL of your Nextcloud instance (e.g., `https://cloud.example.com`) | | `NEXTCLOUD_OIDC_CLIENT_ID` | ⚠️ Optional | - | OAuth client ID (auto-registers if empty) | | `NEXTCLOUD_OIDC_CLIENT_SECRET` | ⚠️ Optional | - | OAuth client secret (auto-registers if empty) | -| `NEXTCLOUD_OIDC_CLIENT_STORAGE` | ⚠️ Optional | `.nextcloud_oauth_client.json` | Path to store auto-registered client credentials | | `NEXTCLOUD_MCP_SERVER_URL` | ⚠️ Optional | `http://localhost:8000` | MCP server URL for OAuth callbacks | | `NEXTCLOUD_USERNAME` | ❌ Must be empty | - | Leave empty to enable OAuth mode | | `NEXTCLOUD_PASSWORD` | ❌ Must be empty | - | Leave empty to enable OAuth mode | @@ -160,10 +158,6 @@ Options: NEXTCLOUD_OIDC_CLIENT_ID env var) --oauth-client-secret TEXT OAuth client secret (can also use NEXTCLOUD_OIDC_CLIENT_SECRET env var) - --oauth-storage-path TEXT Path to store OAuth client credentials - (can also use - NEXTCLOUD_OIDC_CLIENT_STORAGE env var) - [default: .nextcloud_oauth_client.json] --mcp-server-url TEXT MCP server URL for OAuth callbacks (can also use NEXTCLOUD_MCP_SERVER_URL env var) [default: http://localhost:8000] @@ -225,10 +219,7 @@ uv run nextcloud-mcp-server --no-oauth \ - Store OAuth client credentials securely - Use environment variables from your deployment platform (Docker secrets, Kubernetes ConfigMaps, etc.) - Never commit credentials to version control -- Set appropriate file permissions on credential storage: - ```bash - chmod 600 .nextcloud_oauth_client.json - ``` +- SQLite database permissions are handled automatically by the server ### For Docker diff --git a/docs/jwt-oauth-reference.md b/docs/jwt-oauth-reference.md index 7a366a9..4941af2 100644 --- a/docs/jwt-oauth-reference.md +++ b/docs/jwt-oauth-reference.md @@ -272,7 +272,7 @@ mcp-oauth: **Key Points:** - **No credentials needed** - DCR automatically registers the client on first start -- **Credentials persist** - Saved to `.nextcloud_oauth_client.json` and reused +- **Credentials persist** - Saved to SQLite database and reused - **JWT tokens** - Use `--oauth-token-type jwt` for better performance - **Token verifier supports both** - Can handle JWT and opaque tokens - **Pre-configured credentials** - Providing `CLIENT_ID`/`CLIENT_SECRET` skips DCR @@ -286,7 +286,6 @@ mcp-oauth: | `NEXTCLOUD_PUBLIC_ISSUER_URL` | Public issuer URL for JWT validation | (uses `NEXTCLOUD_HOST`) | | `NEXTCLOUD_OIDC_CLIENT_ID` | Pre-configured OAuth client ID | (optional - uses DCR if unset) | | `NEXTCLOUD_OIDC_CLIENT_SECRET` | Pre-configured OAuth client secret | (optional - uses DCR if unset) | -| `NEXTCLOUD_OIDC_CLIENT_STORAGE` | Path to persist DCR-registered credentials | `.nextcloud_oauth_client.json` | | `NEXTCLOUD_OIDC_SCOPES` | Space-separated scopes to request | `"openid profile email mcp:notes:read mcp:notes:write"` | | `NEXTCLOUD_OIDC_TOKEN_TYPE` | Token format: `"jwt"` or `"Bearer"` | `"Bearer"` | @@ -303,8 +302,8 @@ When the MCP server starts in OAuth mode, it follows this **three-tier credentia ├─ NEXTCLOUD_OIDC_CLIENT_ID └─ NEXTCLOUD_OIDC_CLIENT_SECRET -2. Storage File (Second Priority) - └─ NEXTCLOUD_OIDC_CLIENT_STORAGE (.nextcloud_oauth_client.json) +2. SQLite Database (Second Priority) + └─ OAuth client credentials table 3. Dynamic Client Registration (Automatic Fallback) ├─ Discovers registration endpoint from /.well-known/openid-configuration @@ -327,10 +326,10 @@ export NEXTCLOUD_OIDC_TOKEN_TYPE=jwt # or "Bearer" for opaque tokens **Credential Storage:** -- Registered credentials are saved to `NEXTCLOUD_OIDC_CLIENT_STORAGE` (default: `.nextcloud_oauth_client.json`) -- File has restrictive permissions (0600 - owner read/write only) +- Registered credentials are saved to SQLite database +- Database is encrypted and protected by file system permissions - Credentials are reused on subsequent starts (no re-registration needed) -- Storage file is checked for expiration (auto-regenerates if expired) +- Stored credentials are checked for expiration (auto-regenerates if expired) **Format:** ```json @@ -386,9 +385,9 @@ export NEXTCLOUD_OIDC_CLIENT_ID="" export NEXTCLOUD_OIDC_CLIENT_SECRET="" export NEXTCLOUD_OIDC_TOKEN_TYPE="jwt" -# Option 2: Storage file (second priority) -# Save the JSON response to .nextcloud_oauth_client.json -# Server will automatically load it on startup +# Option 2: SQLite database (second priority) +# Credentials are automatically saved to the database after DCR +# Server will automatically load them on startup ``` When credentials are provided via environment variables or storage file, **DCR is skipped**. @@ -724,7 +723,7 @@ docker compose exec db mariadb -u nextcloud -ppassword nextcloud \ 1. Ensure `NEXTCLOUD_OIDC_SCOPES` environment variable is set correctly 2. Check MCP server startup logs for the scopes being requested 3. Verify DCR is enabled in Nextcloud OIDC app settings -4. Delete `.nextcloud_oauth_client.json` and restart to force re-registration +4. Clear the SQLite database OAuth client entry and restart to force re-registration ### Issue: Token Type Case Sensitivity diff --git a/docs/oauth-architecture.md b/docs/oauth-architecture.md index 7a9b786..e833617 100644 --- a/docs/oauth-architecture.md +++ b/docs/oauth-architecture.md @@ -39,7 +39,7 @@ Phase 0: MCP Server Startup & Client Registration (DCR - RFC 7591) │ 0d. Client credentials │ │<────────────────────────────────────┤ │ {client_id, client_secret} │ - │ → Saved to .nextcloud_oauth_*.json │ + │ → Saved to SQLite database │ │ │ │ ✓ Server ready for connections │ @@ -211,7 +211,7 @@ Insufficient Scope Example (Step-Up Authorization) - **PKCE Validation**: Verifies server advertises S256 code challenge method - **Dynamic Client Registration (DCR)**: Automatically registers OAuth client via `/apps/oidc/register` (RFC 7591) - Or loads pre-configured client credentials - - Saves credentials to `.nextcloud_oauth_client.json` + - Saves credentials to SQLite database - **Tool Registration**: Loads all MCP tools with their `@require_scopes` decorators #### Client Connection Phase @@ -324,7 +324,7 @@ The OAuth flow consists of four distinct phases (see diagram above for visual re - MCP server registers itself as OAuth client (RFC 7591) - Provides: client name, redirect URIs, requested scopes, token type - Receives: `client_id`, `client_secret` - - Saves credentials to `.nextcloud_oauth_client.json` + - Saves credentials to SQLite database 3. **Tool Registration** - All MCP tools loaded with their `@require_scopes` decorators @@ -515,7 +515,7 @@ NEXTCLOUD_HOST=https://nextcloud.example.com **How it works**: 1. Server checks `/.well-known/openid-configuration` for `registration_endpoint` 2. Calls `/apps/oidc/register` to register a client on first startup -3. Saves credentials to `.nextcloud_oauth_client.json` +3. Saves credentials to SQLite database 4. Reuses these credentials on subsequent startups 5. Re-registers only if credentials are missing or expired @@ -718,7 +718,6 @@ See [Configuration Guide](configuration.md) for all OAuth environment variables: | `NEXTCLOUD_OIDC_CLIENT_ID` | Pre-configured client ID (optional) | | `NEXTCLOUD_OIDC_CLIENT_SECRET` | Pre-configured client secret (optional) | | `NEXTCLOUD_MCP_SERVER_URL` | MCP server URL for OAuth callbacks | -| `NEXTCLOUD_OIDC_CLIENT_STORAGE` | Path for auto-registered credentials | ## Testing diff --git a/docs/oauth-setup.md b/docs/oauth-setup.md index 7b90136..8a0191e 100644 --- a/docs/oauth-setup.md +++ b/docs/oauth-setup.md @@ -170,7 +170,7 @@ You have two options for managing OAuth clients: **How it works**: - MCP server automatically registers an OAuth client on first startup - Uses Nextcloud's dynamic client registration endpoint -- Saves credentials to `.nextcloud_oauth_client.json` +- Saves credentials to SQLite database - Reuses stored credentials on subsequent restarts - Re-registers automatically if credentials expire @@ -253,9 +253,6 @@ NEXTCLOUD_PASSWORD= # Optional: MCP server URL (for OAuth callbacks) NEXTCLOUD_MCP_SERVER_URL=http://localhost:8000 - -# Optional: Client storage path -NEXTCLOUD_OIDC_CLIENT_STORAGE=.nextcloud_oauth_client.json EOF ``` @@ -291,7 +288,6 @@ EOF | `NEXTCLOUD_OIDC_CLIENT_ID` | ⚠️ Mode B only | - | OAuth client ID | | `NEXTCLOUD_OIDC_CLIENT_SECRET` | ⚠️ Mode B only | - | OAuth client secret | | `NEXTCLOUD_MCP_SERVER_URL` | ⚠️ Optional | `http://localhost:8000` | MCP server URL for callbacks | -| `NEXTCLOUD_OIDC_CLIENT_STORAGE` | ⚠️ Optional | `.nextcloud_oauth_client.json` | Client credentials storage path | | `NEXTCLOUD_USERNAME` | ❌ Must be empty | - | Leave empty for OAuth | | `NEXTCLOUD_PASSWORD` | ❌ Must be empty | - | Leave empty for OAuth | @@ -334,7 +330,7 @@ INFO OIDC discovery successful INFO Attempting dynamic client registration... INFO Dynamic client registration successful INFO OAuth client ready: ... -INFO Saved OAuth client credentials to .nextcloud_oauth_client.json +INFO Saved OAuth client credentials to SQLite database INFO OAuth initialization complete INFO MCP server ready at http://127.0.0.1:8000 ``` @@ -427,9 +423,9 @@ uv run nextcloud-mcp-server --oauth --log-level debug 2. **Secure Credential Storage** ```bash - # Set restrictive permissions - chmod 600 .nextcloud_oauth_client.json + # Set restrictive permissions on environment file chmod 600 .env + # Database permissions are handled automatically ``` 3. **Use HTTPS for MCP Server** @@ -474,7 +470,7 @@ services: NEXTCLOUD_OIDC_CLIENT_SECRET: ${NEXTCLOUD_OIDC_CLIENT_SECRET} NEXTCLOUD_MCP_SERVER_URL: http://your-server:8000 volumes: - - ./oauth_client.json:/app/.nextcloud_oauth_client.json + - ./data:/app/data # For SQLite database persistence command: ["--oauth", "--transport", "streamable-http"] restart: unless-stopped ``` diff --git a/docs/oauth-troubleshooting.md b/docs/oauth-troubleshooting.md index 4bb0438..0fa9b63 100644 --- a/docs/oauth-troubleshooting.md +++ b/docs/oauth-troubleshooting.md @@ -17,7 +17,7 @@ Start here to identify your issue: | Only seeing Notes tools (7 instead of 90+) | Limited OAuth scopes granted | [Limited Scopes](#limited-scopes---only-seeing-notes-tools) | | HTTP 401 for Notes API | Bearer token patch missing | [Bearer Token Auth Fails](#bearer-token-authentication-fails) | | "OIDC discovery failed" | Network or configuration issue | [Discovery Failed](#oidc-discovery-failed) | -| "Permission denied" on .nextcloud_oauth_client.json | File permissions issue | [File Permission Error](#file-permission-error) | +| "Database error" on OAuth client storage | Database permissions issue | [Database Permission Error](#database-permission-error) | ## Configuration Issues @@ -161,39 +161,38 @@ php occ config:app:set oidc expire_time --value "86400" # 24 hours --- -### File Permission Error +### Database Permission Error **Error Message**: ``` -Permission denied when reading/writing .nextcloud_oauth_client.json +Permission denied when accessing SQLite database +Database is locked ``` -**Cause**: The server cannot access the OAuth client storage file. +**Cause**: The server cannot access the SQLite database file. **Solution**: ```bash -# Check file permissions -ls -la .nextcloud_oauth_client.json - -# Fix file permissions (owner read/write only) -chmod 600 .nextcloud_oauth_client.json +# Check database directory permissions +ls -la /app/data/ # Ensure directory is writable -chmod 755 $(dirname .nextcloud_oauth_client.json) +chmod 755 /app/data -# If file doesn't exist, ensure directory is writable -mkdir -p $(dirname .nextcloud_oauth_client.json) +# Check if database file exists and has correct permissions +ls -la /app/data/tokens.db +chmod 644 /app/data/tokens.db + +# If running in Docker, ensure volume is mounted correctly +docker compose logs mcp-oauth | grep -i "database\|sqlite" ``` -For custom storage paths: -```bash -# Set custom path in .env -NEXTCLOUD_OIDC_CLIENT_STORAGE=/path/to/custom/oauth_client.json - -# Ensure directory exists and is writable -mkdir -p $(dirname /path/to/custom/oauth_client.json) -chmod 755 $(dirname /path/to/custom/oauth_client.json) +**For Docker deployments**: +Ensure the data directory is properly mounted as a volume: +```yaml +volumes: + - ./data:/app/data # Persistent storage for SQLite database ``` --- diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index e5037bb..6fcc101 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -136,24 +136,27 @@ A patch for the `user_oidc` app is required to fix Bearer token support. See [oa --- -### Issue: "Permission denied" when reading/writing OAuth client credentials file +### Issue: "Permission denied" or "Database is locked" when accessing OAuth client storage -**Cause:** The server cannot access the OAuth client storage file (default: `.nextcloud_oauth_client.json`). +**Cause:** The server cannot access the SQLite database for OAuth client credentials storage. **Solution:** ```bash -# Check file permissions -ls -la .nextcloud_oauth_client.json +# Check database directory permissions +ls -la data/ -# Fix file permissions (should be 0600 - owner read/write only) -chmod 600 .nextcloud_oauth_client.json +# Ensure directory is writable +chmod 755 data/ -# Ensure the directory is writable -chmod 755 $(dirname .nextcloud_oauth_client.json) +# Check if database file exists and has correct permissions +ls -la data/tokens.db +chmod 644 data/tokens.db -# If the file doesn't exist, ensure the directory is writable so it can be created -mkdir -p $(dirname .nextcloud_oauth_client.json) +# For Docker deployments, ensure volume is mounted correctly: +# docker-compose.yml should have: +# volumes: +# - ./data:/app/data ``` ---