diff --git a/README.md b/README.md index 0ddf4e7..08fc445 100644 --- a/README.md +++ b/README.md @@ -75,11 +75,12 @@ See [Configuration Guide](docs/configuration.md) for all options. ### 3. Set Up Authentication **OAuth Setup (recommended):** -1. Install Nextcloud OIDC app +1. Install Nextcloud OIDC apps (`oidc` + `user_oidc`) 2. Enable dynamic client registration -3. Start the server +3. Configure Bearer token validation +4. Start the server -See [OAuth Setup Guide](docs/oauth-setup.md) for step-by-step instructions. +See [OAuth Quick Start](docs/quickstart-oauth.md) for 5-minute setup or [OAuth Setup Guide](docs/oauth-setup.md) for production deployment. ### 4. Run the Server @@ -117,12 +118,17 @@ Or connect from: - **[Installation](docs/installation.md)** - Install the server - **[Configuration](docs/configuration.md)** - Environment variables and settings - **[Authentication](docs/authentication.md)** - OAuth vs BasicAuth -- **[OAuth Setup Guide](docs/oauth-setup.md)** - Step-by-step OAuth configuration - **[Running the Server](docs/running.md)** - Start and manage the server +### OAuth Documentation +- **[OAuth Quick Start](docs/quickstart-oauth.md)** - 5-minute setup guide +- **[OAuth Setup Guide](docs/oauth-setup.md)** - Production deployment +- **[OAuth Architecture](docs/oauth-architecture.md)** - How OAuth works +- **[OAuth Troubleshooting](docs/oauth-troubleshooting.md)** - OAuth-specific issues +- **[Upstream Status](docs/oauth-upstream-status.md)** - Required patches and PRs + ### Reference - **[Troubleshooting](docs/troubleshooting.md)** - Common issues and solutions -- **[OAuth Bearer Token Issue](docs/oauth2-bearer-token-session-issue.md)** - Required patch for non-OCS endpoints ### App-Specific Documentation - [Notes API](docs/notes.md) diff --git a/docs/authentication.md b/docs/authentication.md index 9db7785..cf6b9d4 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -13,6 +13,23 @@ The Nextcloud MCP server supports two authentication modes for connecting to you OAuth2/OIDC authentication provides secure, token-based authentication following modern security standards. +### Architecture + +The Nextcloud MCP Server acts as an **OAuth 2.0 Resource Server**, protecting access to Nextcloud resources: + +``` +MCP Client ←→ MCP Server (Resource Server) ←→ Nextcloud (Authorization Server + APIs) + OAuth Flow with PKCE Bearer Token Auth +``` + +**Key Components**: +- **MCP Server**: OAuth Resource Server (validates tokens, provides MCP tools) +- **Nextcloud `oidc` app**: OAuth Authorization Server (issues tokens) +- **Nextcloud `user_oidc` app**: Token validation middleware +- **MCP Client**: Any MCP-compatible client (Claude, custom clients) + +For detailed architecture, see [OAuth Architecture](oauth-architecture.md). + ### Required Nextcloud Apps OAuth authentication requires **two Nextcloud apps** to work together: @@ -39,14 +56,17 @@ OAuth authentication requires **two Nextcloud apps** to work together: **Installation:** Available in Nextcloud App Store under "Security" -**Important:** The `user_oidc` app requires a patch for Bearer token support on non-OCS endpoints (like Notes API). See [oauth2-bearer-token-session-issue.md](oauth2-bearer-token-session-issue.md) for details. +**Important:** The `user_oidc` app requires a patch for Bearer token support on non-OCS endpoints (like Notes API). See [Upstream Status](oauth-upstream-status.md) for details. ### Benefits - **Zero-config deployment** via dynamic client registration - **No credential storage** in environment variables - **Per-user authentication** with access tokens -- **Automatic token validation** via Nextcloud OIDC -- **Secure by design** following OAuth 2.0 standards +- **Per-user permissions** - each user has their own Nextcloud client +- **Automatic token validation** via Nextcloud OIDC userinfo endpoint +- **Token caching** for performance (default: 1 hour TTL) +- **PKCE required** for enhanced security (S256 code challenge) +- **Secure by design** following OAuth 2.0 and OpenID Connect standards ### Current Implementation Limitations @@ -54,31 +74,49 @@ OAuth authentication requires **two Nextcloud apps** to work together: > **Tested Configuration:** > - ✅ Nextcloud `oidc` app (OIDC Identity Provider) + `user_oidc` app (OIDC User Backend) > - ✅ Nextcloud acting as its own identity provider (self-hosted OIDC) +> - ✅ MCP server as OAuth Resource Server +> - ✅ PKCE with S256 code challenge method > > **Not Tested:** > - ❌ External identity providers (Azure AD, Keycloak, Okta, etc.) > - ❌ Using `user_oidc` with external OIDC providers > > **Known Requirements:** -> - 🔧 The `user_oidc` app requires a patch for Bearer token support on non-OCS endpoints (see [oauth2-bearer-token-session-issue.md](oauth2-bearer-token-session-issue.md)) +> - 🔧 The `user_oidc` app requires a patch for Bearer token support on non-OCS endpoints (see [Upstream Status](oauth-upstream-status.md)) > - ⏱️ Dynamic client registration credentials expire (default: 1 hour) - use pre-configured clients for production +> - 🔐 PKCE must be advertised in OIDC discovery (see [Upstream Status](oauth-upstream-status.md)) ### How OAuth Works -When a client connects to the MCP server with OAuth enabled: +The MCP server implements the OAuth 2.0 Resource Server pattern: -1. Client receives OAuth authorization URL from the MCP server -2. User authenticates via browser to Nextcloud -3. Nextcloud redirects back with authorization code -4. Client exchanges code for access token -5. Client uses token to access MCP server +**Phase 1: Authorization (OAuth Flow with PKCE)** +1. MCP client connects and receives OAuth settings (issuer URL, scopes) +2. Client initiates OAuth flow with PKCE (Proof Key for Code Exchange) +3. User authenticates via browser to Nextcloud +4. Nextcloud redirects back with authorization code +5. Client exchanges code + code_verifier for access token -All API requests to Nextcloud use the user's OAuth token, ensuring proper permissions and audit trails. +**Phase 2: API Access (Bearer Token Validation)** +6. Client sends MCP requests with `Authorization: Bearer ` header +7. MCP server validates token by calling Nextcloud's userinfo endpoint +8. Server creates per-user NextcloudClient instance with the token +9. All Nextcloud API requests use the user's Bearer token +10. User-specific permissions and audit trails apply + +This ensures: +- Each user has their own authenticated session +- Actions appear from the correct user in Nextcloud logs +- Proper permission boundaries are maintained +- No shared credentials between users ### See Also -- [OAuth Setup Guide](oauth-setup.md) - Step-by-step setup instructions +- [OAuth Quick Start](quickstart-oauth.md) - 5-minute setup for development +- [OAuth Setup Guide](oauth-setup.md) - Detailed production setup +- [OAuth Architecture](oauth-architecture.md) - Technical details +- [Upstream Status](oauth-upstream-status.md) - Required patches and PR status +- [OAuth Troubleshooting](oauth-troubleshooting.md) - OAuth-specific issues - [Configuration](configuration.md) - Environment variables -- [Troubleshooting](troubleshooting.md) - Common OAuth issues ## Basic Authentication (Legacy) diff --git a/docs/configuration.md b/docs/configuration.md index 3742b1f..ab2bd30 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -78,9 +78,9 @@ Before using OAuth configuration: - Enable dynamic client registration (if using auto-registration) - Settings → OIDC - Enable Bearer token validation: `php occ config:system:set user_oidc oidc_provider_bearer_validation --value=true --type=boolean` -3. **Apply Bearer token patch** - The `user_oidc` app requires a patch for non-OCS endpoints - See [oauth2-bearer-token-session-issue.md](oauth2-bearer-token-session-issue.md) +3. **Apply Bearer token patch** - The `user_oidc` app requires a patch for non-OCS endpoints - See [Upstream Status](oauth-upstream-status.md) for details -See the [OAuth Setup Guide](oauth-setup.md) for detailed instructions. +See the [OAuth Setup Guide](oauth-setup.md) for detailed step-by-step instructions, or [OAuth Quick Start](quickstart-oauth.md) for a 5-minute setup. --- @@ -243,7 +243,11 @@ uv run nextcloud-mcp-server --no-oauth \ ## See Also -- [OAuth Setup Guide](oauth-setup.md) - Step-by-step OAuth configuration +- [OAuth Quick Start](quickstart-oauth.md) - 5-minute OAuth setup for development +- [OAuth Setup Guide](oauth-setup.md) - Detailed OAuth configuration for production +- [OAuth Architecture](oauth-architecture.md) - How OAuth works in the MCP server +- [Upstream Status](oauth-upstream-status.md) - Required patches and upstream PRs - [Authentication](authentication.md) - Authentication modes comparison - [Running the Server](running.md) - Starting the server with different configurations - [Troubleshooting](troubleshooting.md) - Common configuration issues +- [OAuth Troubleshooting](oauth-troubleshooting.md) - OAuth-specific troubleshooting diff --git a/docs/oauth-architecture.md b/docs/oauth-architecture.md new file mode 100644 index 0000000..dbf9864 --- /dev/null +++ b/docs/oauth-architecture.md @@ -0,0 +1,322 @@ +# OAuth Architecture + +This document explains how OAuth2/OIDC authentication works in the Nextcloud MCP Server implementation. + +## Overview + +The Nextcloud MCP Server acts as an **OAuth 2.0 Resource Server**, protecting access to Nextcloud resources. It relies on Nextcloud's OIDC Identity Provider for user authentication and token validation. + +## Architecture Diagram + +``` +┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐ +│ │ │ │ │ │ +│ MCP Client │ │ MCP Server │ │ Nextcloud │ +│ (Claude, │ │ (Resource │ │ Instance │ +│ etc.) │ │ Server) │ │ │ +│ │ │ │ │ │ +└──────┬──────┘ └────────┬─────────┘ └────────┬────────┘ + │ │ │ + │ │ │ + │ 1. Connect to MCP │ │ + ├─────────────────────────────────>│ │ + │ │ │ + │ 2. Return auth settings │ │ + │ (issuer_url, scopes) │ │ + │<─────────────────────────────────┤ │ + │ │ │ + │ │ │ + │ 3. Start OAuth flow (with PKCE) │ │ + ├──────────────────────────────────┼────────────────────────────────────>│ + │ │ /apps/oidc/authorize │ + │ │ │ + │ 4. User authenticates in browser│ │ + │<─────────────────────────────────┼─────────────────────────────────────┤ + │ │ │ + │ 5. Authorization code (redirect)│ │ + │<─────────────────────────────────┤ │ + │ │ │ + │ 6. Exchange code for token │ │ + ├──────────────────────────────────┼────────────────────────────────────>│ + │ │ /apps/oidc/token │ + │ │ │ + │ 7. Access token │ │ + │<─────────────────────────────────┼─────────────────────────────────────┤ + │ │ │ + │ │ │ + │ 8. API request with Bearer token│ │ + ├─────────────────────────────────>│ │ + │ Authorization: Bearer xxx │ │ + │ │ │ + │ │ 9. Validate token via userinfo │ + │ ├────────────────────────────────────>│ + │ │ /apps/oidc/userinfo │ + │ │ │ + │ │ 10. User info (token valid) │ + │ │<────────────────────────────────────┤ + │ │ │ + │ │ 11. Nextcloud API request │ + │ ├────────────────────────────────────>│ + │ │ Authorization: Bearer xxx │ + │ │ (Notes, Calendar, etc.) │ + │ │ │ + │ │ 12. API response │ + │ │<────────────────────────────────────┤ + │ │ │ + │ 13. MCP tool response │ │ + │<─────────────────────────────────┤ │ + │ │ │ +``` + +## Components + +### 1. MCP Client +- Any MCP-compatible client (Claude Desktop, Claude Code, custom clients) +- Initiates OAuth flow with PKCE (Proof Key for Code Exchange) +- Stores and sends access token with each request +- **Example**: Claude Desktop, Claude Code + +### 2. MCP Server (Resource Server) +- **Role**: OAuth 2.0 Resource Server +- **Location**: This Nextcloud MCP Server implementation +- **Responsibilities**: + - Validates Bearer tokens by calling Nextcloud's userinfo endpoint + - Caches validated tokens (default: 1 hour TTL) + - Creates authenticated Nextcloud client instances per-user + - Enforces PKCE requirements (S256 code challenge method) + - Exposes Nextcloud functionality via MCP tools + +**Key Files**: +- [`app.py`](../nextcloud_mcp_server/app.py) - OAuth mode detection and configuration +- [`auth/token_verifier.py`](../nextcloud_mcp_server/auth/token_verifier.py) - Token validation logic +- [`auth/context_helper.py`](../nextcloud_mcp_server/auth/context_helper.py) - Per-user client creation + +### 3. Nextcloud OIDC Apps + +#### a) `oidc` - OIDC Identity Provider +- **Role**: OAuth 2.0 Authorization Server +- **Location**: Nextcloud app (`apps/oidc`) +- **Endpoints**: + - `/.well-known/openid-configuration` - Discovery endpoint + - `/apps/oidc/authorize` - Authorization endpoint + - `/apps/oidc/token` - Token endpoint + - `/apps/oidc/userinfo` - User info endpoint (token validation) + - `/apps/oidc/jwks` - JSON Web Key Set + - `/apps/oidc/register` - Dynamic client registration + +**Configuration**: +```bash +# Enable dynamic client registration (optional) +# Settings → OIDC → "Allow dynamic client registration" +``` + +#### b) `user_oidc` - OpenID Connect User Backend +- **Role**: Bearer token validation middleware +- **Location**: Nextcloud app (`apps/user_oidc`) +- **Responsibilities**: + - Validates Bearer tokens for Nextcloud API requests + - Creates user sessions from valid Bearer tokens + - Integrates with Nextcloud's authentication system + +**Configuration**: +```bash +# Enable Bearer token validation (required) +php occ config:system:set user_oidc oidc_provider_bearer_validation --value=true --type=boolean +``` + +> [!IMPORTANT] +> The `user_oidc` app requires a patch to properly support Bearer token authentication for non-OCS endpoints. See [Upstream Status](oauth-upstream-status.md) for details. + +### 4. Nextcloud Instance +- **Role**: Resource Owner / API Provider +- **Provides**: Notes, Calendar, Contacts, Deck, Files, etc. + +## Authentication Flow + +### Phase 1: OAuth Authorization (Steps 1-7) + +1. **Client Connects**: MCP client connects to MCP server +2. **Auth Settings**: MCP server returns OAuth settings: + ```json + { + "issuer_url": "https://nextcloud.example.com", + "resource_server_url": "http://localhost:8000", + "required_scopes": ["openid", "profile"] + } + ``` +3. **OAuth Flow**: Client initiates OAuth flow with PKCE + - Generates `code_verifier` (random string) + - Calculates `code_challenge` = SHA256(code_verifier) + - Redirects user to `/apps/oidc/authorize` with `code_challenge` +4. **User Authentication**: User logs in to Nextcloud via browser +5. **Authorization Code**: Nextcloud redirects back with authorization code +6. **Token Exchange**: Client exchanges code for access token + - Sends `code` + `code_verifier` to `/apps/oidc/token` + - OIDC app validates PKCE challenge +7. **Access Token**: Client receives access token (JWT or opaque) + +### Phase 2: API Access (Steps 8-13) + +8. **API Request**: Client sends MCP request with Bearer token +9. **Token Validation**: MCP server validates token: + - Checks cache (1-hour TTL by default) + - If not cached, calls `/apps/oidc/userinfo` with Bearer token + - Extracts username from `sub` or `preferred_username` claim +10. **User Info**: Nextcloud returns user info if token is valid +11. **Nextcloud API Call**: MCP server calls Nextcloud API on behalf of user + - Creates `NextcloudClient` instance with Bearer token + - User-specific permissions apply +12. **API Response**: Nextcloud returns data +13. **MCP Response**: MCP server returns formatted response to client + +## Token Validation + +The MCP server validates tokens using the **userinfo endpoint approach**: + +### Why Userinfo (vs JWT Validation)? + +**Advantages**: +- Works with both JWT and opaque tokens +- No need to manage JWKS rotation +- Always up-to-date (respects token revocation) +- Simpler implementation + +**Caching Strategy**: +- Validated tokens cached for 1 hour (configurable) +- Cache keyed by token string +- Expired tokens re-validated automatically + +**Implementation**: See [`NextcloudTokenVerifier`](../nextcloud_mcp_server/auth/token_verifier.py) + +## PKCE Requirement + +The MCP server **requires** PKCE with S256 code challenge method: + +1. Server validates OIDC discovery advertises PKCE support +2. Checks for `code_challenge_methods_supported` field +3. Verifies `S256` is included in supported methods +4. Logs error if PKCE not properly advertised + +**Why PKCE?**: +- Required by MCP specification +- Protects against authorization code interception +- Essential for public clients (desktop apps, CLI tools) + +**Implementation**: See [`validate_pkce_support()`](../nextcloud_mcp_server/app.py#L31-L93) + +## Client Registration + +The MCP server supports two client registration modes: + +### Automatic Registration (Dynamic Client Registration) + +```bash +# No client credentials needed +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 new client +3. Saves credentials to `.nextcloud_oauth_client.json` +4. Re-registers if credentials expire + +**Best for**: Development, testing, short-lived deployments + +### Pre-configured Client + +```bash +# Manual client registration via CLI +php occ oidc:create --name="MCP Server" --type=confidential --redirect-uri="http://localhost:8000/oauth/callback" + +# Configure MCP server +NEXTCLOUD_HOST=https://nextcloud.example.com +NEXTCLOUD_OIDC_CLIENT_ID=abc123 +NEXTCLOUD_OIDC_CLIENT_SECRET=xyz789 +``` + +**Best for**: Production, long-running deployments + +## Per-User Client Instances + +Each authenticated user gets their own `NextcloudClient` instance: + +```python +# From MCP context (contains validated token) +client = get_client_from_context(ctx) + +# Creates NextcloudClient with: +# - username: from token's 'sub' or 'preferred_username' claim +# - auth: BearerAuth(token) +``` + +**Benefits**: +- User-specific permissions +- Audit trail (actions appear from correct user) +- No shared credentials +- Multi-user support + +**Implementation**: See [`get_client_from_context()`](../nextcloud_mcp_server/auth/context_helper.py) + +## Security Considerations + +### Token Storage +- MCP client stores access token +- MCP server does NOT store tokens (validates per-request) +- Token validation results cached in-memory only + +### PKCE Protection +- Server validates PKCE is advertised +- Client MUST use PKCE with S256 +- Protects against authorization code interception + +### Scopes +- Required scopes: `openid`, `profile` +- Additional scopes inferred from userinfo response + +### Token Validation +- Every MCP request validates Bearer token +- Cached for performance (1-hour default) +- Calls userinfo endpoint for validation + +## Configuration + +See [Configuration Guide](configuration.md) for all OAuth environment variables: + +| Variable | Purpose | +|----------|---------| +| `NEXTCLOUD_HOST` | Nextcloud instance URL | +| `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 + +The integration test suite includes comprehensive OAuth testing: + +- **Automated tests** (Playwright): [`tests/integration/test_oauth_playwright.py`](../tests/integration/test_oauth_playwright.py) +- **Interactive tests**: [`tests/integration/test_oauth_interactive.py`](../tests/integration/test_oauth_interactive.py) +- **Fixtures**: [`tests/conftest.py`](../tests/conftest.py) + +Run OAuth tests: +```bash +# Start OAuth-enabled MCP server +docker-compose up --build -d mcp-oauth + +# Run automated tests +uv run pytest tests/integration/test_oauth_playwright.py --browser firefox -v + +# Run interactive tests (manual login) +uv run pytest tests/integration/test_oauth_interactive.py -v +``` + +## See Also + +- [OAuth Setup Guide](oauth-setup.md) - Configuration steps +- [OAuth Quick Start](quickstart-oauth.md) - Get started quickly +- [Upstream Status](oauth-upstream-status.md) - Required upstream patches +- [OAuth Troubleshooting](oauth-troubleshooting.md) - Common issues +- [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749) - OAuth 2.0 Authorization Framework +- [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636) - PKCE +- [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html) diff --git a/docs/oauth-setup.md b/docs/oauth-setup.md index aa7c692..3024f3f 100644 --- a/docs/oauth-setup.md +++ b/docs/oauth-setup.md @@ -1,255 +1,545 @@ # OAuth Setup Guide -This guide walks you through setting up OAuth2/OIDC authentication for the Nextcloud MCP server. +This guide walks you through setting up OAuth2/OIDC authentication for the Nextcloud MCP server in production. + +> **Quick Start?** If you want a 5-minute setup for development, see [OAuth Quick Start](quickstart-oauth.md). + +## Table of Contents + +- [Prerequisites](#prerequisites) +- [Architecture Overview](#architecture-overview) +- [Step 1: Install Nextcloud Apps](#step-1-install-nextcloud-apps) +- [Step 2: Configure OIDC Apps](#step-2-configure-oidc-apps) +- [Step 3: Choose Deployment Mode](#step-3-choose-deployment-mode) +- [Step 4: Configure MCP Server](#step-4-configure-mcp-server) +- [Step 5: Start and Verify](#step-5-start-and-verify) +- [Testing Authentication](#testing-authentication) +- [Production Recommendations](#production-recommendations) ## Prerequisites -- Nextcloud instance with administrator access -- Python 3.11+ installed -- Nextcloud MCP server installed (see [Installation Guide](installation.md)) +Before beginning, ensure you have: -## Step 1: Install Required Nextcloud Apps +- **Nextcloud instance** with administrator access +- **Nextcloud version** 28 or later +- **SSH/CLI access** to Nextcloud server (for `occ` commands) +- **Python 3.11+** installed on MCP server host +- **MCP server installed** (see [Installation Guide](installation.md)) -OAuth authentication requires **two apps** to work together: +## Architecture Overview -### Install the OIDC Identity Provider App +The OAuth implementation uses the following components: -1. Open your Nextcloud instance as an administrator +``` +MCP Client ←→ MCP Server (Resource Server) ←→ Nextcloud (Authorization Server + APIs) + OAuth Flow Bearer Token Auth +``` + +**Key Roles**: +- **MCP Server**: OAuth Resource Server (validates tokens, provides MCP tools) +- **Nextcloud `oidc` app**: OAuth Authorization Server (issues tokens) +- **Nextcloud `user_oidc` app**: Token validation middleware + +For detailed architecture, see [OAuth Architecture](oauth-architecture.md). + +## Step 1: Install Nextcloud Apps + +OAuth authentication requires **two Nextcloud apps** to work together. + +### Required Apps + +#### 1. `oidc` - OIDC Identity Provider + +**Purpose**: Makes Nextcloud an OAuth2/OIDC authorization server + +**Installation**: +1. Open Nextcloud as administrator 2. Navigate to **Apps** → **Security** -3. Find and install the **OIDC** app (full name: "OIDC Identity Provider") -4. Enable the app +3. Find **"OIDC"** (full name: "OIDC Identity Provider") +4. Click **Enable** or **Download and enable** -This app makes Nextcloud an OAuth2/OIDC authorization server. +**Provides**: +- OAuth2 authorization endpoint +- Token endpoint +- User info endpoint +- JWKS endpoint +- Dynamic client registration endpoint (optional) -### Install the OpenID Connect User Backend App +#### 2. `user_oidc` - OpenID Connect User Backend +**Purpose**: Authenticates users and validates Bearer tokens + +**Installation**: 1. In **Apps** → **Security** -2. Find and install the **OpenID Connect user backend** app (app ID: `user_oidc`) -3. Enable the app +2. Find **"OpenID Connect user backend"** (app ID: `user_oidc`) +3. Click **Enable** or **Download and enable** -This app handles Bearer token validation and user authentication. +**Provides**: +- Bearer token validation against OIDC provider +- User authentication via OIDC +- Session management for authenticated users > [!IMPORTANT] -> **Required Patch:** The `user_oidc` app needs a patch for Bearer token authentication to work with non-OCS endpoints (like Notes API). See [oauth2-bearer-token-session-issue.md](oauth2-bearer-token-session-issue.md) for the patch and installation instructions. +> **Upstream Patch Required**: The `user_oidc` app needs a patch for Bearer token support with app-specific APIs (Notes, Calendar, etc.). The patch is pending upstream review. +> +> **Status**: See [Upstream Status](oauth-upstream-status.md) for current PR status and workarounds. +> +> **Impact**: OCS APIs work without patch, but app-specific APIs require the patch. + +### Verify Installation + +```bash +# Check both apps are installed and enabled +php occ app:list | grep -E "oidc|user_oidc" + +# Expected output: +# - oidc: enabled +# - user_oidc: enabled +``` ## Step 2: Configure OIDC Apps -### Enable Dynamic Client Registration (for `oidc` app) +### Configure `oidc` App (Identity Provider) -1. Navigate to **Settings** → **OIDC** (in Administration settings) -2. Find the **Dynamic Client Registration** section -3. Enable **"Allow dynamic client registration"** -4. (Optional) Configure client expiration time: +#### Option A: Dynamic Client Registration (Development) + +**Best for**: Development, testing, auto-registration + +1. Navigate to **Settings** → **OIDC** (Administration settings) +2. Enable **"Allow dynamic client registration"** +3. (Optional) Configure client expiration: ```bash - # Via Nextcloud CLI (occ) - optional, default is 3600 seconds (1 hour) + # Default: 3600 seconds (1 hour) php occ config:app:set oidc expire_time --value "86400" # 24 hours ``` -### Enable Bearer Token Validation (for `user_oidc` app) +#### Option B: Pre-configured Clients (Production) -Configure the `user_oidc` app to validate bearer tokens from the `oidc` Identity Provider: +**Best for**: Production, long-running deployments + +Skip the dynamic registration setting. You'll manually register clients via CLI in Step 3. + +### Configure `user_oidc` App (Token Validation) + +**Required**: Enable Bearer token validation: ```bash -# Via Nextcloud CLI (occ) - required for Bearer token authentication +# SSH into Nextcloud server php occ config:system:set user_oidc oidc_provider_bearer_validation --value=true --type=boolean ``` -This tells the `user_oidc` app to validate Bearer tokens against Nextcloud's own OIDC Identity Provider. +This tells `user_oidc` to validate Bearer tokens against Nextcloud's OIDC Identity Provider. -## Step 3: Choose Your Setup Approach +### Verify OIDC Discovery -You have two options for configuring OAuth clients: +Test that OIDC discovery endpoint is accessible: -### Approach A: Automatic Registration (Zero-config) +```bash +curl https://your.nextcloud.instance.com/.well-known/openid-configuration | jq +``` -**Best for:** Development, testing, short-lived deployments +Expected response: +```json +{ + "issuer": "https://your.nextcloud.instance.com", + "authorization_endpoint": "https://your.nextcloud.instance.com/apps/oidc/authorize", + "token_endpoint": "https://your.nextcloud.instance.com/apps/oidc/token", + "userinfo_endpoint": "https://your.nextcloud.instance.com/apps/oidc/userinfo", + "jwks_uri": "https://your.nextcloud.instance.com/apps/oidc/jwks", + "registration_endpoint": "https://your.nextcloud.instance.com/apps/oidc/register", + ... +} +``` -**How it works:** The MCP server automatically registers a new OAuth client with Nextcloud at startup using dynamic client registration. +### PKCE Support -**Pros:** +The MCP server **requires PKCE** (Proof Key for Code Exchange) with S256 code challenge method. + +**Validation**: The MCP server automatically validates PKCE support at startup by checking the discovery response for `code_challenge_methods_supported`. + +**Note**: If PKCE is not advertised in discovery metadata, the server logs a warning but continues (PKCE still works, it's just not advertised). See [Upstream Status](oauth-upstream-status.md) for tracking. + +## Step 3: Choose Deployment Mode + +You have two options for managing OAuth clients: + +### Mode A: Automatic Registration (Dynamic Client Registration) + +**Best for**: Development, testing, short-lived deployments + +**How it works**: +- MCP server automatically registers OAuth client at startup +- Uses Nextcloud's dynamic client registration endpoint +- Saves credentials to `.nextcloud_oauth_client.json` +- Re-registers automatically if credentials expire + +**Pros**: - Zero configuration required -- Quick to set up +- Quick setup - No manual client management -**Cons:** -- Clients expire (default: 1 hour) -- Server must re-register on restart if expired -- Not recommended for long-running production deployments +**Cons**: +- Clients expire (default: 1 hour, configurable) +- Must re-register on restart if expired +- Not ideal for long-running production -[Jump to Approach A setup →](#approach-a-automatic-registration) +**Configuration**: Skip to [Step 4](#step-4-configure-mcp-server) with minimal config. -### Approach B: Pre-configured Client (Production) +--- -**Best for:** Production, long-running deployments +### Mode B: Pre-configured Client (Production) -**How it works:** You manually create an OAuth client via Nextcloud CLI and provide credentials to the MCP server. +**Best for**: Production, long-running deployments, stable environments -**Pros:** +**How it works**: +- You manually register OAuth client via Nextcloud CLI +- Provide client credentials to MCP server - Credentials don't expire -- Stable for production use + +**Pros**: +- Credentials don't expire +- Stable for production - More control over client configuration +- Better for audit trails -**Cons:** +**Cons**: - Requires manual setup -- Needs access to Nextcloud server CLI +- Needs SSH/CLI access to Nextcloud server -[Jump to Approach B setup →](#approach-b-pre-configured-client) - ---- - -## Approach A: Automatic Registration - -### 1. Configure Environment - -Create your `.env` file with only the Nextcloud host: - -```dotenv -# .env file -NEXTCLOUD_HOST=https://your.nextcloud.instance.com - -# Leave these EMPTY for OAuth mode -NEXTCLOUD_USERNAME= -NEXTCLOUD_PASSWORD= -``` - -### 2. Start the MCP Server +**Setup**: Register a client via CLI: ```bash -# Load environment variables -export $(grep -v '^#' .env | xargs) - -# Start server with OAuth enabled -uv run nextcloud-mcp-server --oauth -``` - -### 3. Verify Registration - -The server will automatically register a new OAuth client. Look for these log messages: - -``` -INFO OAuth mode detected (NEXTCLOUD_USERNAME/PASSWORD not set) -INFO Configuring MCP server for OAuth mode -INFO Performing OIDC discovery: https://your.nextcloud.instance.com/.well-known/openid-configuration -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 OAuth initialization complete -``` - -### 4. Client Credential Storage - -Registered client credentials are saved to `.nextcloud_oauth_client.json` by default. The server will: -- Load existing credentials on startup -- Check if they've expired -- Re-register automatically if expired or missing - -**Note:** Since dynamically registered clients expire (default: 1 hour), the server checks credentials at startup. For long-running deployments, consider using Approach B (pre-configured clients) instead. - ---- - -## Approach B: Pre-configured Client - -### 1. Register Client via Nextcloud CLI - -SSH into your Nextcloud server and run: - -```bash -# Create OAuth client +# SSH into Nextcloud server php occ oidc:create \ --name="Nextcloud MCP Server" \ --type=confidential \ --redirect-uri="http://localhost:8000/oauth/callback" # Example output: -# Client ID: abc123xyz -# Client Secret: secret456def +# Client ID: abc123xyz789 +# Client Secret: secret456def012 + +# Save these credentials for Step 4 ``` -**Note:** Adjust the `--redirect-uri` to match your MCP server URL if different from `http://localhost:8000`. +**Important**: Adjust `--redirect-uri` to match your MCP server URL: +- Local: `http://localhost:8000/oauth/callback` +- Remote: `http://your-server:8000/oauth/callback` +- Custom port: `http://your-server:PORT/oauth/callback` -### 2. Configure Environment - -Add the client credentials to your `.env` file: - -```dotenv -# .env file -NEXTCLOUD_HOST=https://your.nextcloud.instance.com - -# OAuth Client Credentials -NEXTCLOUD_OIDC_CLIENT_ID=abc123xyz -NEXTCLOUD_OIDC_CLIENT_SECRET=secret456def - -# Optional: Custom OAuth configuration -NEXTCLOUD_MCP_SERVER_URL=http://localhost:8000 -NEXTCLOUD_OIDC_CLIENT_STORAGE=.nextcloud_oauth_client.json - -# Leave these EMPTY for OAuth mode -NEXTCLOUD_USERNAME= -NEXTCLOUD_PASSWORD= +The redirect URI **must** be: +``` +{NEXTCLOUD_MCP_SERVER_URL}/oauth/callback ``` -See [Configuration Guide](configuration.md#oauth2oidc-configuration) for all available options. +## Step 4: Configure MCP Server -### 3. Start the MCP Server +Create or update your `.env` file with OAuth configuration. + +### For Mode A (Automatic Registration) ```bash -# Load environment variables -export $(grep -v '^#' .env | xargs) +# Copy sample if needed +cp env.sample .env -# Start server - it will use pre-configured credentials -uv run nextcloud-mcp-server --oauth +# Edit .env +cat > .env << 'EOF' +# Nextcloud Instance +NEXTCLOUD_HOST=https://your.nextcloud.instance.com + +# Leave EMPTY for OAuth mode (do not set USERNAME/PASSWORD) +NEXTCLOUD_USERNAME= +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 ``` -### 4. Verify Configuration +### For Mode B (Pre-configured Client) -Look for these log messages: +```bash +# Copy sample if needed +cp env.sample .env +# Edit .env +cat > .env << 'EOF' +# Nextcloud Instance +NEXTCLOUD_HOST=https://your.nextcloud.instance.com + +# OAuth Client Credentials (from Step 3) +NEXTCLOUD_OIDC_CLIENT_ID=abc123xyz789 +NEXTCLOUD_OIDC_CLIENT_SECRET=secret456def012 + +# MCP server URL (must match redirect URI) +NEXTCLOUD_MCP_SERVER_URL=http://localhost:8000 + +# Leave EMPTY for OAuth mode +NEXTCLOUD_USERNAME= +NEXTCLOUD_PASSWORD= +EOF +``` + +### Environment Variables Reference + +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `NEXTCLOUD_HOST` | ✅ Yes | - | Full URL of Nextcloud instance | +| `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 | + +See [Configuration Guide](configuration.md) for all options. + +## Step 5: Start and Verify + +### Load Environment Variables + +```bash +# Load from .env file +export $(grep -v '^#' .env | xargs) + +# Verify key variables are set +echo "NEXTCLOUD_HOST: $NEXTCLOUD_HOST" +echo "NEXTCLOUD_MCP_SERVER_URL: $NEXTCLOUD_MCP_SERVER_URL" +``` + +### Start MCP Server + +```bash +# Start with OAuth mode +uv run nextcloud-mcp-server --oauth + +# Or with custom options +uv run nextcloud-mcp-server --oauth --port 8000 --log-level info +``` + +### Verify Startup + +Look for these success messages: + +**For Mode A (Auto-registration)**: ``` INFO OAuth mode detected (NEXTCLOUD_USERNAME/PASSWORD not set) INFO Configuring MCP server for OAuth mode INFO Performing OIDC discovery: https://your.nextcloud.instance.com/.well-known/openid-configuration +✓ PKCE support validated: ['S256'] INFO OIDC discovery successful -INFO Using pre-configured OAuth client: abc123xyz +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 OAuth initialization complete +INFO MCP server ready at http://127.0.0.1:8000 ``` -**Benefits:** Pre-configured clients don't expire automatically and are more stable for production use. +**For Mode B (Pre-configured)**: +``` +INFO OAuth mode detected (NEXTCLOUD_USERNAME/PASSWORD not set) +INFO Configuring MCP server for OAuth mode +INFO Performing OIDC discovery: https://your.nextcloud.instance.com/.well-known/openid-configuration +✓ PKCE support validated: ['S256'] +INFO OIDC discovery successful +INFO Using pre-configured OAuth client: abc123xyz789 +INFO OAuth initialization complete +INFO MCP server ready at http://127.0.0.1:8000 +``` ---- +### Common Startup Issues -## Step 4: Test Authentication +| Issue | Solution | +|-------|----------| +| "OAuth mode requires NEXTCLOUD_HOST" | Set `NEXTCLOUD_HOST` in `.env` | +| "OIDC discovery failed" | Verify Nextcloud URL and network connectivity | +| "Dynamic registration failed" | Enable dynamic registration in OIDC app settings | +| "PKCE validation failed" | See [Upstream Status](oauth-upstream-status.md) | -The MCP server is now configured for OAuth. When clients connect: +See [OAuth Troubleshooting](oauth-troubleshooting.md) for detailed solutions. -1. Client connects to MCP server -2. Server provides OAuth authorization URL -3. User opens URL in browser and authenticates to Nextcloud -4. Nextcloud redirects back with authorization code -5. Client exchanges code for access token -6. Client uses Bearer token to access MCP server -7. All Nextcloud API requests use the user's OAuth token +## Testing Authentication ### Test with MCP Inspector +The MCP Inspector provides a web UI for testing: + ```bash -# Start MCP Inspector +# In a new terminal uv run mcp dev -# In the browser UI: -# 1. Enter your MCP server URL (e.g., http://localhost:8000) -# 2. Complete OAuth flow in browser -# 3. Test tools and resources +# Opens browser at http://localhost:6272 ``` +In the MCP Inspector UI: +1. Enter server URL: `http://localhost:8000/mcp` +2. Click **Connect** +3. Complete OAuth flow in browser popup: + - Login to Nextcloud + - Authorize MCP server access + - Redirected back to MCP Inspector +4. Test tools: + - Try `nc_notes_create_note` + - Try `nc_notes_search_notes` + - Try `nc_calendar_list_events` + +### Test from Command Line + +```bash +# Get an OAuth token (you'll need to implement client flow or extract from browser) +TOKEN="your_access_token_here" + +# Test OCS API (should work) +curl -H "Authorization: Bearer $TOKEN" \ + "$NEXTCLOUD_HOST/ocs/v2.php/cloud/capabilities?format=json" \ + -H "OCS-APIRequest: true" + +# Test Notes API (requires upstream patch) +curl -H "Authorization: Bearer $TOKEN" \ + "$NEXTCLOUD_HOST/apps/notes/api/v1/notes" +``` + +### Verify Token Validation + +Check MCP server logs for token validation: + +```bash +# Start server with debug logging +uv run nextcloud-mcp-server --oauth --log-level debug + +# Look for: +# DEBUG Token validation via userinfo endpoint +# DEBUG Token validated successfully for user: username +``` + +## Production Recommendations + +### Security Best Practices + +1. **Use Pre-configured Clients** (Mode B) + - More stable + - Better audit trails + - No expiration issues + +2. **Secure Credential Storage** + ```bash + # Set restrictive permissions + chmod 600 .nextcloud_oauth_client.json + chmod 600 .env + ``` + +3. **Use HTTPS for MCP Server** + - Especially important for remote access + - Use reverse proxy (nginx, Apache) with SSL + +4. **Restrict Redirect URIs** + - Only register necessary redirect URIs + - Use specific URLs (not wildcards) + +### Deployment Considerations + +1. **MCP Server URL** + - Must be accessible to OAuth clients + - Must match redirect URI registered with Nextcloud + - For Docker: expose port and use correct host + +2. **Network Configuration** + - MCP server must reach Nextcloud (OIDC endpoints) + - OAuth clients must reach MCP server (callbacks) + - OAuth clients must reach Nextcloud (authorization flow) + +3. **Process Management** + - Use systemd, supervisord, or Docker for MCP server + - Ensure automatic restart on failure + - Monitor logs for OAuth errors + +### Example Production Configs + +#### Docker Compose + +```yaml +version: '3' +services: + nextcloud-mcp: + image: ghcr.io/cbcoutinho/nextcloud-mcp-server:latest + ports: + - "127.0.0.1:8000:8000" + environment: + NEXTCLOUD_HOST: https://your.nextcloud.instance.com + NEXTCLOUD_OIDC_CLIENT_ID: ${NEXTCLOUD_OIDC_CLIENT_ID} + 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 + command: ["--oauth", "--transport", "streamable-http"] + restart: unless-stopped +``` + +#### Systemd Service + +```ini +[Unit] +Description=Nextcloud MCP Server (OAuth) +After=network.target + +[Service] +Type=simple +User=mcp +WorkingDirectory=/opt/nextcloud-mcp-server +Environment="NEXTCLOUD_HOST=https://your.nextcloud.instance.com" +Environment="NEXTCLOUD_OIDC_CLIENT_ID=abc123xyz789" +Environment="NEXTCLOUD_OIDC_CLIENT_SECRET=secret456def012" +Environment="NEXTCLOUD_MCP_SERVER_URL=http://your-server:8000" +ExecStart=/opt/nextcloud-mcp-server/.venv/bin/nextcloud-mcp-server --oauth +Restart=on-failure +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +### Monitoring and Maintenance + +1. **Log Monitoring** + ```bash + # Watch for OAuth errors + tail -f /var/log/nextcloud-mcp/server.log | grep -i "oauth\|token" + ``` + +2. **Token Expiration** (Mode A only) + - Monitor for "Stored client has expired" messages + - Consider increasing expiration or switching to Mode B + +3. **Upstream Patches** + - Subscribe to [Upstream Status](oauth-upstream-status.md) + - Plan to update when patches are merged + +## Troubleshooting + +For OAuth-specific issues, see [OAuth Troubleshooting](oauth-troubleshooting.md). + +Common issues: +- [OIDC discovery failed](oauth-troubleshooting.md#oidc-discovery-failed) +- [Bearer token auth fails](oauth-troubleshooting.md#bearer-token-authentication-fails) +- [Client expired](oauth-troubleshooting.md#client-expired) +- [PKCE errors](oauth-troubleshooting.md#pkce-not-advertised) + ## Next Steps -- [Running the Server](running.md) - Additional server options +- [OAuth Architecture](oauth-architecture.md) - Understand how OAuth works +- [OAuth Troubleshooting](oauth-troubleshooting.md) - Solve common issues +- [Upstream Status](oauth-upstream-status.md) - Track required patches - [Configuration](configuration.md) - All environment variables -- [Troubleshooting](troubleshooting.md) - Common OAuth issues +- [Running the Server](running.md) - Additional server options ## See Also - [Authentication Overview](authentication.md) - OAuth vs BasicAuth comparison -- [OAuth Bearer Token Issue](oauth2-bearer-token-session-issue.md) - Required patch for non-OCS endpoints +- [Quick Start Guide](quickstart-oauth.md) - 5-minute setup for development +- [MCP Specification](https://spec.modelcontextprotocol.io/) - MCP protocol details +- [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749) - OAuth 2.0 Framework +- [RFC 7636](https://www.rfc-editor.org/rfc/rfc7636) - PKCE Extension diff --git a/docs/oauth-troubleshooting.md b/docs/oauth-troubleshooting.md new file mode 100644 index 0000000..08e7197 --- /dev/null +++ b/docs/oauth-troubleshooting.md @@ -0,0 +1,554 @@ +# OAuth Troubleshooting + +This guide covers OAuth-specific issues and solutions for the Nextcloud MCP server. + +For general troubleshooting, see [Troubleshooting Guide](troubleshooting.md). + +## Quick Diagnosis + +Start here to identify your issue: + +| Symptom | Likely Cause | Quick Fix Link | +|---------|--------------|----------------| +| "OAuth mode requires NEXTCLOUD_HOST" | Missing environment variable | [Missing NEXTCLOUD_HOST](#missing-nextcloud_host) | +| "OAuth mode requires client credentials OR dynamic registration" | OIDC apps not configured | [Missing OIDC Apps](#missing-or-misconfigured-oidc-apps) | +| "PKCE support validation failed" | OIDC app doesn't advertise PKCE | [PKCE Not Advertised](#pkce-not-advertised) | +| "Stored client has expired" | Dynamic client expired | [Client Expired](#client-expired) | +| 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) | + +## Configuration Issues + +### Missing NEXTCLOUD_HOST + +**Error Message**: +``` +OAuth mode requires NEXTCLOUD_HOST environment variable +``` + +**Cause**: The `NEXTCLOUD_HOST` environment variable is not set or empty. + +**Solution**: + +1. Add to your `.env` file: + ```bash + NEXTCLOUD_HOST=https://your.nextcloud.instance.com + ``` + +2. Reload environment variables: + ```bash + export $(grep -v '^#' .env | xargs) + ``` + +3. Verify it's set: + ```bash + echo $NEXTCLOUD_HOST + # Should output: https://your.nextcloud.instance.com + ``` + +--- + +### Missing or Misconfigured OIDC Apps + +**Error Message**: +``` +OAuth mode requires either client credentials OR dynamic client registration +``` + +**Cause**: The required Nextcloud OIDC apps are either: +- Not installed +- Not enabled +- Missing configuration + +**Solution**: + +**Step 1**: Verify both apps are installed: + +```bash +# Check installed apps +php occ app:list | grep -E "oidc|user_oidc" + +# Should show: +# - oidc: enabled +# - user_oidc: enabled +``` + +If not installed: +1. Open Nextcloud as administrator +2. Navigate to **Apps** → **Security** +3. Install **"OIDC"** (OIDC Identity Provider) +4. Install **"OpenID Connect user backend"** (user_oidc) +5. Enable both apps + +**Step 2**: Enable dynamic client registration: + +1. Go to **Settings** → **OIDC** (Administration) +2. Enable **"Allow dynamic client registration"** + +**Step 3**: Configure Bearer token validation: + +```bash +php occ config:system:set user_oidc oidc_provider_bearer_validation --value=true --type=boolean +``` + +**Step 4**: Verify discovery endpoint: + +```bash +curl https://your.nextcloud.instance.com/.well-known/openid-configuration | jq '.registration_endpoint' + +# Should output: +# "https://your.nextcloud.instance.com/apps/oidc/register" +``` + +**Alternative**: Use pre-configured client credentials: + +```bash +# Register client via CLI +php occ oidc:create \ + --name="Nextcloud MCP Server" \ + --type=confidential \ + --redirect-uri="http://localhost:8000/oauth/callback" + +# Add to .env +echo "NEXTCLOUD_OIDC_CLIENT_ID=" >> .env +echo "NEXTCLOUD_OIDC_CLIENT_SECRET=" >> .env +``` + +--- + +### Client Expired + +**Error Message**: +``` +Stored client has expired +``` + +**Cause**: Dynamically registered OAuth clients expire (default: 1 hour). + +**Solution**: + +**Option 1: Restart the Server** (Automatic re-registration) + +```bash +uv run nextcloud-mcp-server --oauth +# Server automatically re-registers if credentials expired +``` + +**Option 2: Use Pre-configured Credentials** (Recommended for production) + +```bash +# Register permanent client via Nextcloud CLI +php occ oidc:create \ + --name="Nextcloud MCP Server" \ + --type=confidential \ + --redirect-uri="http://localhost:8000/oauth/callback" + +# Add to .env +NEXTCLOUD_OIDC_CLIENT_ID= +NEXTCLOUD_OIDC_CLIENT_SECRET= +``` + +Pre-configured clients don't expire. + +**Option 3: Increase Expiration Time** + +```bash +# Via Nextcloud CLI (default: 3600 seconds = 1 hour) +php occ config:app:set oidc expire_time --value "86400" # 24 hours +``` + +--- + +### File Permission Error + +**Error Message**: +``` +Permission denied when reading/writing .nextcloud_oauth_client.json +``` + +**Cause**: The server cannot access the OAuth client storage 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 + +# Ensure directory is writable +chmod 755 $(dirname .nextcloud_oauth_client.json) + +# If file doesn't exist, ensure directory is writable +mkdir -p $(dirname .nextcloud_oauth_client.json) +``` + +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) +``` + +--- + +## Discovery and Connection Issues + +### OIDC Discovery Failed + +**Error Message**: +``` +OIDC discovery failed +Cannot reach OIDC discovery endpoint +``` + +**Cause**: The server cannot reach the Nextcloud OIDC discovery endpoint. + +**Solution**: + +**Step 1**: Verify Nextcloud URL is correct: + +```bash +echo $NEXTCLOUD_HOST +# Should be full URL: https://your.nextcloud.instance.com +``` + +**Step 2**: Test discovery endpoint manually: + +```bash +curl https://your.nextcloud.instance.com/.well-known/openid-configuration + +# Should return JSON with OIDC configuration +# { +# "issuer": "https://your.nextcloud.instance.com", +# "authorization_endpoint": "https://your.nextcloud.instance.com/apps/oidc/authorize", +# ... +# } +``` + +**Step 3**: Check network connectivity: + +```bash +# Test basic connectivity +ping your.nextcloud.instance.com + +# Test HTTPS +curl -I https://your.nextcloud.instance.com +``` + +**Step 4**: Verify both OIDC apps are enabled: + +```bash +php occ app:list | grep -E "oidc|user_oidc" +``` + +**Step 5**: Check firewall rules (if using Docker): + +```bash +# Check if MCP server can reach Nextcloud +docker exec nextcloud-mcp-server curl https://your.nextcloud.instance.com/.well-known/openid-configuration +``` + +--- + +## Authentication Issues + +### Bearer Token Authentication Fails + +**Error Message**: +``` +HTTP 401 Unauthorized when calling Nextcloud APIs +``` + +**Symptoms**: +- OCS APIs work (`/ocs/v2.php/cloud/capabilities`) +- App APIs fail (`/apps/notes/api/`, `/apps/calendar/`, etc.) + +**Cause**: The `user_oidc` app's CORS middleware interferes with Bearer token authentication for non-OCS endpoints. + +**Solution**: Apply the Bearer token patch to `user_oidc` app. + +See [Upstream Status](oauth-upstream-status.md#1-bearer-token-support-for-non-ocs-endpoints) for details. + +**Quick Patch**: + +```bash +# SSH into Nextcloud server +cd /path/to/nextcloud/apps/user_oidc + +# Edit lib/User/Backend.php +# Add this line before each return statement in getCurrentUserId() method: +$this->session->set('app_api', true); + +# Lines to modify: ~243, ~310, ~315, ~337 +``` + +**Test the fix**: + +```bash +# Get an OAuth token (from MCP client or test) +TOKEN="your_access_token" + +# Test Notes API +curl -H "Authorization: Bearer $TOKEN" \ + https://your.nextcloud.instance.com/apps/notes/api/v1/notes + +# Should return notes JSON (not 401) +``` + +--- + +### PKCE Not Advertised + +**Error Message**: +``` +ERROR: OIDC CONFIGURATION ERROR - Missing PKCE Support Advertisement +⚠️ MCP clients (like Claude Code) WILL REJECT this provider! +``` + +**Cause**: The OIDC discovery endpoint doesn't include `code_challenge_methods_supported` field. + +**Impact**: +- Some MCP clients may refuse to connect +- Standards compliance issue (RFC 8414) +- **Functionality still works** (PKCE is accepted, just not advertised) + +**Solution**: + +**Short-term**: The MCP server logs a warning but continues. OAuth flow still works. + +**Long-term**: Update the `oidc` app to advertise PKCE support. + +See [Upstream Status](oauth-upstream-status.md#2-pkce-support-advertisement-in-discovery) for tracking. + +**Verify**: + +```bash +curl https://your.nextcloud.instance.com/.well-known/openid-configuration | jq '.code_challenge_methods_supported' + +# Should return: +# ["S256", "plain"] + +# If null, PKCE isn't advertised (but still works) +``` + +--- + +## Runtime Issues + +### MCP Client Can't Authenticate + +**Symptoms**: +- Client connects but OAuth flow fails +- Authorization redirects don't work +- Token exchange fails + +**Diagnosis**: + +**Step 1**: Verify OAuth is configured correctly: + +```bash +uv run nextcloud-mcp-server --oauth --log-level debug +``` + +Look for: +``` +INFO OAuth initialization complete +INFO MCP server ready at http://127.0.0.1:8000 +``` + +**Step 2**: Check OIDC discovery: + +```bash +curl https://your.nextcloud.instance.com/.well-known/openid-configuration +``` + +**Step 3**: Verify MCP server URL matches client expectations: + +```bash +echo $NEXTCLOUD_MCP_SERVER_URL +# Should match the URL clients use to connect +# Default: http://localhost:8000 +``` + +If MCP server is on a different host/port, update: +```bash +NEXTCLOUD_MCP_SERVER_URL=http://actual-host:actual-port +``` + +**Step 4**: Check redirect URI configuration: + +For pre-configured clients, ensure redirect URI matches: +```bash +# Client redirect URI should be: +http://your-mcp-server-url/oauth/callback + +# Example for local server: +http://localhost:8000/oauth/callback +``` + +--- + +### Tools Return 401 Errors + +**Symptoms**: +- OAuth flow completes successfully +- Token is valid +- MCP tools return 401 errors + +**Cause**: Bearer token not working with Nextcloud APIs. + +**Solution**: See [Bearer Token Authentication Fails](#bearer-token-authentication-fails) above. + +--- + +## Switching Authentication Modes + +### From BasicAuth to OAuth + +```bash +# 1. Remove or comment out USERNAME/PASSWORD in .env +sed -i 's/^NEXTCLOUD_USERNAME/#NEXTCLOUD_USERNAME/' .env +sed -i 's/^NEXTCLOUD_PASSWORD/#NEXTCLOUD_PASSWORD/' .env + +# 2. Ensure NEXTCLOUD_HOST is set +grep NEXTCLOUD_HOST .env + +# 3. Restart server with OAuth +export $(grep -v '^#' .env | xargs) +uv run nextcloud-mcp-server --oauth +``` + +### From OAuth to BasicAuth + +```bash +# 1. Add USERNAME/PASSWORD to .env +echo "NEXTCLOUD_USERNAME=your-username" >> .env +echo "NEXTCLOUD_PASSWORD=your-password" >> .env + +# 2. Restart server (BasicAuth auto-detected) +export $(grep -v '^#' .env | xargs) +uv run nextcloud-mcp-server --no-oauth +``` + +--- + +## Advanced Debugging + +### Enable Debug Logging + +```bash +uv run nextcloud-mcp-server --oauth --log-level debug +``` + +Look for: +- OIDC discovery details +- Client registration attempts +- Token validation logs +- API request/response details + +### Test Discovery Endpoint + +```bash +# Full discovery response +curl https://your.nextcloud.instance.com/.well-known/openid-configuration | jq + +# Check specific fields +curl https://your.nextcloud.instance.com/.well-known/openid-configuration | jq '{ + issuer, + authorization_endpoint, + token_endpoint, + userinfo_endpoint, + registration_endpoint, + code_challenge_methods_supported +}' +``` + +### Test Token Validation + +```bash +# Get userinfo with token +curl -H "Authorization: Bearer $TOKEN" \ + https://your.nextcloud.instance.com/apps/oidc/userinfo + +# Should return user info: +# { +# "sub": "username", +# "preferred_username": "username", +# "name": "Display Name", +# ... +# } +``` + +### Test Nextcloud API Access + +```bash +# Test OCS API (should work) +curl -H "Authorization: Bearer $TOKEN" \ + "$NEXTCLOUD_HOST/ocs/v2.php/cloud/capabilities?format=json" \ + -H "OCS-APIRequest: true" + +# Test app API (requires patch) +curl -H "Authorization: Bearer $TOKEN" \ + "$NEXTCLOUD_HOST/apps/notes/api/v1/notes" +``` + +--- + +## Getting Help + +If you continue to experience issues: + +### 1. Collect Diagnostic Information + +```bash +# Server version +uv run nextcloud-mcp-server --version + +# Python version +python3 --version + +# Server logs with debug +uv run nextcloud-mcp-server --oauth --log-level debug 2>&1 | tee mcp-server.log + +# OIDC discovery +curl https://your.nextcloud.instance.com/.well-known/openid-configuration > oidc-discovery.json + +# Nextcloud version +# Check in Nextcloud admin panel or: +php occ -V +``` + +### 2. Check Documentation + +- [OAuth Architecture](oauth-architecture.md) - How OAuth works +- [OAuth Setup Guide](oauth-setup.md) - Configuration steps +- [Upstream Status](oauth-upstream-status.md) - Required patches +- [Configuration](configuration.md) - Environment variables + +### 3. Open an Issue + +If problems persist, [open an issue](https://github.com/cbcoutinho/nextcloud-mcp-server/issues) with: + +- **Error messages** (full text) +- **Server logs** (with `--log-level debug`) +- **OIDC discovery response** (from curl command above) +- **Nextcloud version** +- **OIDC app versions** (`oidc` and `user_oidc`) +- **Steps to reproduce** +- **Environment details** (OS, Python version, Docker vs local) + +--- + +## See Also + +- [OAuth Quick Start](quickstart-oauth.md) - Get started quickly +- [OAuth Setup Guide](oauth-setup.md) - Detailed configuration +- [OAuth Architecture](oauth-architecture.md) - Technical details +- [Upstream Status](oauth-upstream-status.md) - Required patches +- [General Troubleshooting](troubleshooting.md) - Non-OAuth issues diff --git a/docs/oauth-upstream-status.md b/docs/oauth-upstream-status.md new file mode 100644 index 0000000..bdfc593 --- /dev/null +++ b/docs/oauth-upstream-status.md @@ -0,0 +1,226 @@ +# OAuth Upstream Status + +This document tracks the status of upstream patches and pull requests required for full OAuth functionality. + +## Overview + +The Nextcloud MCP Server's OAuth implementation relies on two Nextcloud apps: +- **`oidc`** - OIDC Identity Provider (Authorization Server) +- **`user_oidc`** - OpenID Connect user backend (Token validation) + +While the core OAuth flow works, there are **pending upstream improvements** that enhance functionality and standards compliance. + +## Required Patches + +### 1. Bearer Token Support for Non-OCS Endpoints + +**Status**: 🟡 **Patch Required** (Pending Upstream) + +**Affected Component**: `user_oidc` app + +**Issue**: Bearer token authentication fails for app-specific APIs (Notes, Calendar, etc.) with `401 Unauthorized` errors, even though OCS APIs work correctly. + +**Root Cause**: The `CORSMiddleware` in Nextcloud logs out sessions created by Bearer token authentication when CSRF tokens are missing, which breaks API requests. + +**Solution**: Set the `app_api` session flag during Bearer token authentication to bypass CSRF checks. + +**Upstream PR**: [nextcloud/user_oidc#1221](https://github.com/nextcloud/user_oidc/issues/1221) + +**Workaround**: Manually apply the patch to `lib/User/Backend.php` in the `user_oidc` app + +**Impact**: +- ✅ **Works**: OCS APIs (`/ocs/v2.php/cloud/capabilities`) +- ❌ **Requires Patch**: App APIs (`/apps/notes/api/`, `/apps/calendar/`, etc.) + +**Files Modified**: `lib/User/Backend.php` in `user_oidc` app + +**Patch Summary**: +```php +// Add before successful Bearer token authentication returns +$this->session->set('app_api', true); +``` + +This is added at lines ~243, ~310, ~315, and ~337 in `Backend.php`. + +--- + +### 2. PKCE Support Advertisement in Discovery + +**Status**: 🟢 **PR Submitted** (Pending Review) + +**Affected Component**: `oidc` app + +**Issue**: The OIDC discovery endpoint (`/.well-known/openid-configuration`) does not advertise PKCE support in the `code_challenge_methods_supported` field. + +**Why It Matters**: +- MCP specification requires PKCE with S256 code challenge method +- RFC 8414 states that absence of `code_challenge_methods_supported` means PKCE is **not supported** +- Some MCP clients may reject providers without proper PKCE advertisement + +**Current Behavior**: +- PKCE **functionally works** (the OIDC app accepts and validates PKCE) +- PKCE just isn't **advertised** in discovery metadata + +**Recommended Fix**: Update `oidc` app to include: +```json +{ + "code_challenge_methods_supported": ["S256"] +} +``` + +**Workaround**: The MCP server implements PKCE validation and logs a warning if not advertised. Functionality still works. + +**Upstream PR**: [H2CK/oidc#584](https://github.com/H2CK/oidc/pull/584) - Submitted 2025-10-13 +- **Changes**: Adds `code_challenge_methods_supported: ["S256"]` to discovery document when PKCE is enabled +- **Size**: +5 lines added, 0 deleted +- **Status**: Open, awaiting review + +--- + +## Upstream PRs Status + +| PR/Issue | Component | Status | Priority | Notes | +|----------|-----------|--------|----------|-------| +| [user_oidc#1221](https://github.com/nextcloud/user_oidc/issues/1221) | `user_oidc` | 🟡 Open | High | Required for app-specific APIs | +| [H2CK/oidc#584](https://github.com/H2CK/oidc/pull/584) | `oidc` | 🟢 PR Open | Medium | PKCE advertisement for standards compliance | + +## What Works Without Patches + +The following functionality works **out of the box** without any patches: + +✅ **OAuth Flow**: +- OIDC discovery +- Dynamic client registration +- Authorization code flow with PKCE +- Token exchange +- Userinfo endpoint + +✅ **MCP Server as Resource Server**: +- Token validation via userinfo +- Per-user client instances +- Token caching + +✅ **Nextcloud OCS APIs**: +- Capabilities endpoint +- All OCS-based APIs + +## What Requires Patches + +The following functionality requires upstream patches: + +🟡 **App-Specific APIs** (Requires user_oidc#1221): +- Notes API (`/apps/notes/api/`) +- Calendar API (CalDAV) +- Contacts API (CardDAV) +- Deck API +- Tables API +- Custom app APIs + +🟡 **Standards Compliance** (PKCE advertisement): +- Full RFC 8414 compliance +- MCP client compatibility guarantee + +## Installation Instructions + +### For Development/Testing + +If the upstream PRs are not yet merged, you can apply patches manually: + +#### 1. Apply Bearer Token Patch + +```bash +# SSH into Nextcloud server +cd /path/to/nextcloud/apps/user_oidc + +# Download and apply patch +# (Patch file to be created once PR is ready) +wget https://github.com/nextcloud/user_oidc/pull/XXXX.patch +git apply XXXX.patch + +# Or manually edit lib/User/Backend.php +# Add this line before each return statement in getCurrentUserId(): +# $this->session->set('app_api', true); +``` + +#### 2. Verify Installation + +```bash +# Test with OAuth token +curl -H "Authorization: Bearer YOUR_TOKEN" \ + https://your.nextcloud.com/apps/notes/api/v1/notes + +# Should return notes JSON (not 401) +``` + +### For Production + +**Recommendation**: Wait for upstream PRs to be merged and included in official Nextcloud releases before deploying OAuth in production. + +**Alternative**: Use a patched version of `user_oidc` app in your deployment: +1. Fork the `user_oidc` app +2. Apply the required patches +3. Install your patched version +4. Document the changes for your team + +## Testing + +The integration test suite validates OAuth functionality: + +```bash +# Start OAuth-enabled MCP server +docker-compose up --build -d mcp-oauth + +# Run comprehensive OAuth tests +uv run pytest tests/integration/test_oauth_playwright.py --browser firefox -v + +# Tests verify: +# - OAuth flow completion +# - Token validation +# - MCP tool calls with Bearer tokens +# - Notes API access (requires patch) +``` + +## Monitoring Upstream Progress + +To track progress on these issues: + +1. **Watch the upstream repositories**: + - [nextcloud/user_oidc](https://github.com/nextcloud/user_oidc) + - [nextcloud/oidc](https://github.com/nextcloud/oidc) + +2. **Subscribe to specific issues**: + - [user_oidc#1221](https://github.com/nextcloud/user_oidc/issues/1221) - Bearer token support + +3. **Check Nextcloud release notes** for mentions of: + - Bearer token authentication improvements + - OIDC/OAuth enhancements + - AppAPI compatibility + +## Contributing + +Want to help get these patches merged? + +1. **Test the patches**: Run the integration tests and report results +2. **Review PRs**: Provide feedback on upstream pull requests +3. **Document issues**: Report any problems or edge cases +4. **Contribute code**: Submit improvements or fixes to upstream + +## Timeline Expectations + +**Best Case**: PRs merged in next Nextcloud minor release (est. 3-6 months) + +**Realistic**: PRs reviewed and merged within 6-12 months + +**Meanwhile**: Use the workarounds documented in this guide + +## See Also + +- [OAuth Architecture](oauth-architecture.md) - How OAuth works in this implementation +- [OAuth Troubleshooting](oauth-troubleshooting.md) - Common issues and solutions +- [OAuth Setup Guide](oauth-setup.md) - Configuration instructions + +--- + +**Last Updated**: 2025-10-14 + +**Next Review**: When PR #584 or issue #1221 has activity diff --git a/docs/oauth2-bearer-token-session-issue.md b/docs/oauth2-bearer-token-session-issue.md deleted file mode 100644 index 797c101..0000000 --- a/docs/oauth2-bearer-token-session-issue.md +++ /dev/null @@ -1,97 +0,0 @@ -# Root Cause Analysis: OAuth2 Bearer Token Session Invalidation - -## Problem -Bearer token authentication fails for app-specific APIs (like Notes) with 401 Unauthorized, even though it works for OCS APIs (capabilities). - -## Root Cause -The CORSMiddleware in Nextcloud server is logging out the session created by Bearer token authentication: - -``` -/home/chris/Software/server/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php:84 -$this->session->logout(); -``` - -### Why Session is Logged Out -1. Notes API has @CORS annotation -2. Bearer auth via user_oidc creates a logged-in session -3. Request has NO CSRF token -4. Request has NO AppAPI auth flag -5. Request has NO PHP_AUTH_USER/PHP_AUTH_PW (basic auth) -6. Therefore CORSMiddleware calls logout() - -### Log Evidence -``` -{"message":"[TokenInvalidatedListener] Could not find the OIDC session related with an invalidated token"} -``` - -Token validated successfully, then immediately invalidated by session logout. - -## Token Type Investigation (Opaque vs JWT) -- **Finding**: Token type (opaque vs JWT) does NOT affect the issue -- **Reason**: Session invalidation happens AFTER successful token validation -- Both opaque and JWT tokens validate correctly via TokenValidationRequestEvent -- The logout happens in CORSMiddleware, not in token validation - -## ✅ SOLUTION (Tested & Working) - -### Option A: Set AppAPI Flag for Bearer Auth ✅ -**Status**: Successfully tested and verified working - -Modified user_oidc `Backend.php` `getCurrentUserId()` method to set the `app_api` session flag before returning the user ID: - -```php -$this->session->set('app_api', true); -``` - -This bypasses CORS middleware's logout logic at line 81-82 by setting the same flag used by Nextcloud's AppAPI framework. - -### Implementation -The flag is added before all successful Bearer token authentication return statements in `/var/www/html/custom_apps/user_oidc/lib/User/Backend.php`: - -- Line ~243: After OIDC provider validation -- Line ~310: After auto-provisioning with bearer provisioning -- Line ~315: After existing user authentication -- Line ~337: After LDAP user sync - -### Test Results -All OAuth Bearer token operations now work correctly: - -✅ **Capabilities endpoint** (OCS API) - 200 OK -✅ **Notes API listing** - 200 OK -✅ **Notes API create** - 200 OK (created note 112) -✅ **Notes API delete** - 200 OK (deleted note 112) - -No session invalidation occurs, and all API operations complete successfully. - -### Patch File -See `patches/user_oidc-bearer-auth-app-api-flag.patch` for the exact changes. - -## Alternative Solutions (Not Tested) - -### Option B: Avoid Creating Full Session for Bearer Auth -Bearer token auth should not create a full session that triggers CORS middleware checks. This would require deeper architectural changes. - -### Option C: Add CSRF Exemption -Modify CORSMiddleware to exempt Bearer token authenticated requests from CSRF check. This would require changes to Nextcloud core. - -### Option D: Use Basic Auth Headers -Set PHP_AUTH_USER/PHP_AUTH_PW server variables during Bearer auth so CORSMiddleware can re-authenticate. This could have security implications. - -## Recommendations - -### Short-term (Current Implementation) -The `app_api` flag solution works correctly and follows Nextcloud's existing pattern for API authentication. This is the recommended approach for immediate use. - -### Long-term (Upstream Contribution) -Consider submitting this fix to the upstream user_oidc project as it enables proper Bearer token authentication for all Nextcloud APIs, not just OCS endpoints. - -## Files Involved -- `/home/chris/Software/user_oidc/lib/User/Backend.php` (getCurrentUserId) - **MODIFIED** -- `/home/chris/Software/server/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php` (logout logic) -- `/home/chris/Software/user_oidc/lib/Listener/TokenInvalidatedListener.php` (cleanup handler) - -## Testing -Run the OAuth interactive test to verify: -```bash -uv run pytest tests/integration/test_oauth_interactive.py -v -``` diff --git a/docs/quickstart-oauth.md b/docs/quickstart-oauth.md new file mode 100644 index 0000000..47f8fae --- /dev/null +++ b/docs/quickstart-oauth.md @@ -0,0 +1,163 @@ +# OAuth Quick Start Guide + +Get up and running with OAuth authentication in 5 minutes. + +## Prerequisites Checklist + +Before you begin, ensure you have: + +- [ ] Nextcloud instance with **administrator access** +- [ ] Nextcloud version 28 or later +- [ ] Python 3.11+ installed +- [ ] `uv` package manager installed ([installation instructions](https://docs.astral.sh/uv/getting-started/installation/)) + +## Step 1: Install Nextcloud Apps + +Install **both** required apps in your Nextcloud instance: + +1. Open Nextcloud as administrator +2. Navigate to **Apps** → **Security** +3. Install: + - **OIDC** (OIDC Identity Provider app) + - **OpenID Connect user backend** (user_oidc app) +4. Enable both apps + +> [!IMPORTANT] +> The `user_oidc` app requires an upstream patch for Bearer token support. See [Upstream Status](oauth-upstream-status.md) for details. The functionality works, but the PR is pending. + +## Step 2: Configure Nextcloud OIDC + +Enable dynamic client registration and Bearer token validation: + +### Via Web UI + +1. Go to **Settings** → **OIDC** (Administration settings) +2. Enable **"Allow dynamic client registration"** + +### Via CLI (Required) + +SSH into your Nextcloud server and run: + +```bash +# Enable Bearer token validation +php occ config:system:set user_oidc oidc_provider_bearer_validation --value=true --type=boolean +``` + +## Step 3: Install MCP Server + +Clone and install the MCP server: + +```bash +# Clone repository +git clone https://github.com/cbcoutinho/nextcloud-mcp-server.git +cd nextcloud-mcp-server + +# Install dependencies +uv sync +``` + +## Step 4: Configure Environment + +Create a `.env` file with minimal configuration: + +```bash +# Copy sample +cp env.sample .env + +# Edit .env and set: +NEXTCLOUD_HOST=https://your.nextcloud.instance.com + +# IMPORTANT: Leave these EMPTY for OAuth mode +NEXTCLOUD_USERNAME= +NEXTCLOUD_PASSWORD= +``` + +## Step 5: Start the Server + +Load environment variables and start the server: + +```bash +# Load environment +export $(grep -v '^#' .env | xargs) + +# Start server with OAuth +uv run nextcloud-mcp-server --oauth +``` + +Look for this success message: + +``` +✓ PKCE support validated: ['S256'] +INFO OAuth initialization complete +INFO MCP server ready at http://127.0.0.1:8000 +``` + +## Step 6: Test with MCP Inspector + +Open a new terminal and test the connection: + +```bash +# Start MCP Inspector +uv run mcp dev +``` + +This opens your browser. In the MCP Inspector UI: + +1. Enter server URL: `http://127.0.0.1:8000/mcp` +2. Click **Connect** +3. Complete the OAuth flow in the browser popup +4. After authorization, you'll see available tools and resources + +Test a tool by trying: +- **Tool**: `nc_notes_create_note` +- **Title**: "Test Note" +- **Content**: "Hello from MCP!" +- **Category**: "Notes" + +## Troubleshooting Quick Fixes + +### PKCE Error + +If you see: +``` +ERROR: OIDC CONFIGURATION ERROR - Missing PKCE Support Advertisement +``` + +**Fix**: The Nextcloud OIDC app needs to be updated to advertise PKCE support. See [Upstream Status](oauth-upstream-status.md) for the required PR. + +### 401 Unauthorized for Notes API + +If OAuth works but Notes API returns 401: + +**Fix**: The `user_oidc` app needs the Bearer token patch. See [Upstream Status](oauth-upstream-status.md) for details. + +### Can't Reach OIDC Discovery Endpoint + +**Fix**: Verify your Nextcloud URL is correct and accessible: + +```bash +curl https://your.nextcloud.instance.com/.well-known/openid-configuration +``` + +## Next Steps + +- [OAuth Setup Guide](oauth-setup.md) - Detailed configuration options +- [OAuth Architecture](oauth-architecture.md) - How it works under the hood +- [OAuth Troubleshooting](oauth-troubleshooting.md) - Common issues and solutions +- [Configuration](configuration.md) - All environment variables + +## Development vs Production + +This quick start uses **automatic client registration** which is perfect for: +- Development +- Testing +- Short-lived deployments + +For **production deployments**, you should: +1. Pre-register OAuth clients manually +2. Use dedicated client credentials +3. See [OAuth Setup Guide](oauth-setup.md) for production configuration + +--- + +**Need help?** Check [OAuth Troubleshooting](oauth-troubleshooting.md) or [open an issue](https://github.com/cbcoutinho/nextcloud-mcp-server/issues). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index d75a5a8..e5037bb 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -2,7 +2,9 @@ This guide covers common issues and solutions for the Nextcloud MCP server. -## OAuth Issues +> **OAuth-specific issues?** See the dedicated [OAuth Troubleshooting Guide](oauth-troubleshooting.md) for OAuth authentication problems, OIDC discovery issues, token validation failures, and more. + +## OAuth Issues (Quick Reference) ### Issue: "OAuth mode requires NEXTCLOUD_HOST environment variable" @@ -218,6 +220,18 @@ uv run nextcloud-mcp-server --no-oauth --- +### For More OAuth Help + +See the dedicated **[OAuth Troubleshooting Guide](oauth-troubleshooting.md)** for: +- Bearer token authentication failures +- PKCE validation errors +- Token validation issues +- Client registration problems +- Advanced OAuth debugging +- And much more... + +--- + ## Configuration Issues ### Issue: Environment variables not loaded @@ -534,7 +548,9 @@ If problems persist, open an issue on the [GitHub repository](https://github.com ## See Also +- **[OAuth Troubleshooting](oauth-troubleshooting.md)** - Dedicated OAuth troubleshooting guide - [OAuth Setup Guide](oauth-setup.md) - OAuth configuration +- [OAuth Architecture](oauth-architecture.md) - How OAuth works +- [Upstream Status](oauth-upstream-status.md) - Required patches and upstream PRs - [Configuration](configuration.md) - Environment variables - [Running the Server](running.md) - Server options -- [OAuth Bearer Token Issue](oauth2-bearer-token-session-issue.md) - Required patch diff --git a/docs/user_oidc-pr-description.md b/docs/user_oidc-pr-description.md deleted file mode 100644 index d8829b2..0000000 --- a/docs/user_oidc-pr-description.md +++ /dev/null @@ -1,96 +0,0 @@ -# Fix Bearer Token Authentication Causing Session Logout - -## Problem - -Bearer token authentication with OIDC fails for app-specific APIs (like Notes, Calendar, etc.) with `401 Unauthorized` errors, even though the same Bearer token works fine for OCS APIs (like `/ocs/v2.php/cloud/capabilities`). - -### Root Cause - -When using Bearer token authentication: - -1. ✅ Bearer token validation successfully authenticates the user -2. ✅ A session is created for the authenticated user -3. ❌ **Nextcloud's `CORSMiddleware` detects the logged-in session but no CSRF token** -4. ❌ **`CORSMiddleware` calls `$this->session->logout()` to prevent CSRF attacks** -5. ❌ The logout invalidates the session, breaking the API request with 401 Unauthorized - -This occurs because app-specific APIs (Notes, Calendar, etc.) use the `@CORS` annotation, which triggers the `CORSMiddleware` security checks. The OCS APIs don't have this annotation, which is why they work correctly. - -### Error Logs - -``` -[TokenInvalidatedListener] Could not find the OIDC session related with an invalidated token -Session token invalidated before logout -Logging out -``` - -## Solution - -Set the `app_api` session flag during Bearer token authentication. This instructs `CORSMiddleware` to skip the CSRF check and logout logic, as the authentication is API-based rather than session-based. - -This is the same mechanism used by Nextcloud's [AppAPI framework](https://github.com/cloud-py-api/app_api) for external application authentication. - -### Changes - -The fix adds `$this->session->set('app_api', true);` before all successful Bearer token authentication return statements in `lib/User/Backend.php`: - -- **Line 243**: After OIDC Identity Provider validation -- **Line 310**: After auto-provisioning with bearer provisioning -- **Line 315**: After existing user authentication -- **Line 337**: After LDAP user sync - -## Testing - -Tested with the [nextcloud-mcp-server](https://github.com/cccs-nik/nextcloud-mcp-server) project's integration tests: - -### Before Fix -``` -✅ Capabilities endpoint (OCS API) - 200 OK -❌ Notes API listing - 401 Unauthorized -❌ Notes API create - 401 Unauthorized -``` - -### After Fix -``` -✅ Capabilities endpoint (OCS API) - 200 OK -✅ Notes API listing - 200 OK -✅ Notes API create - 200 OK -✅ Notes API delete - 200 OK -``` - -All OAuth Bearer token operations now work correctly across all Nextcloud APIs without session invalidation. - -## Configuration - -This fix works with the standard Bearer token validation configuration: - -```php -// config.php -'user_oidc' => [ - 'oidc_provider_bearer_validation' => true, -], -``` - -And in the OIDC Identity Provider app: -```bash -php occ config:app:set oidc dynamic_client_registration --value='true' -``` - -## Impact - -This fix enables proper Bearer token authentication for: -- All Nextcloud app APIs (Notes, Calendar, Contacts, etc.) -- External applications using OAuth 2.0 / OpenID Connect -- MCP servers and other API integrations -- Any application using the `Authorization: Bearer` header - -## Related Files - -- `lib/User/Backend.php` - Modified to set `app_api` flag -- `/server/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php` - Contains the CSRF/logout logic that this bypasses - -## References - -- [Nextcloud CORS Middleware](https://github.com/nextcloud/server/blob/master/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php) -- [Nextcloud AppAPI](https://github.com/cloud-py-api/app_api) -- [OpenID Connect Bearer Token Usage](https://openid.net/specs/openid-connect-core-1_0.html#TokenUsage)