Chris Coutinho
76430bec21
docs: Update ADR-002 with OAuth-only focus and testing status [skip ci]
...
Major changes to ADR-002 (Vector Database Background Sync Authentication):
1. Reordered authentication tiers:
- Tier 1: Service Account Token (client_credentials) - most compatible
- Tier 2: Token Exchange with Impersonation - not implemented
- Tier 3: Token Exchange with Delegation - implemented
2. Removed admin credentials fallback:
- ADR now focuses exclusively on OAuth mode
- Background sync unavailable without proper OAuth configuration
- BasicAuth mode out of scope (credentials already available)
3. Clarified testing status:
- Tier 1: Implemented but only manual tests exist
- Tier 3: Implemented but only manual tests exist
- Added TODO for automated integration tests
4. Removed "Offline Access with Refresh Tokens":
- Documented as "Will Not Implement"
- MCP protocol architecture prevents server from accessing refresh tokens
- Violates OAuth security model (tokens must stay with client)
5. Simplified configuration:
- Removed all admin credential references
- OAuth-only environment variables
- Automatic tier detection based on provider capabilities
The ADR now accurately reflects that refresh tokens should never be shared
between MCP client and server, following OAuth best practices and the
FastMCP SDK architecture.
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-02 22:03:22 +01:00
Chris Coutinho
e81c2ad33d
docs: Update upstream OAuth status with completed oidc app PRs [skip ci]
...
Update oauth-upstream-status.md to clarify patch requirements and document
completed upstream work:
**Clarifications:**
- CORSMiddleware patch is for Nextcloud core server (not user_oidc app)
- Root cause: CORS middleware logs out sessions without CSRF tokens
- Solution: Allow Bearer tokens to bypass CORS/CSRF checks
- Updated all references with actual PR number: nextcloud/server#55878
**Completed oidc app PRs (now documented):**
- ✅ H2CK/oidc#586 : User consent management (v1.11.0+)
- ✅ H2CK/oidc#585 : JWT tokens, introspection, scope validation (v1.10.0+)
- ✅ H2CK/oidc#584 : PKCE support (RFC 7636) (v1.10.0+)
**Updated sections:**
- "What Works Without Patches" - Added JWT, scopes, consent features
- "Upstream PRs Status" - Added completed PRs table
- "Monitoring Upstream Progress" - Focus on remaining work
- Last updated date: 2025-11-02
All OAuth features except app-specific APIs now work out of the box
with oidc app v1.10.0+. Only CORSMiddleware patch remains pending.
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-02 22:03:21 +01:00
Chris Coutinho
2ca6725fc6
docs: Replace .nextcloud_oauth_client.json references with SQLite storage
...
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 <noreply@anthropic.com >
2025-11-02 22:03:21 +01:00
Chris Coutinho
e331544cee
feat: Implement RFC 8693 token exchange for Keycloak (ADR-002 Tier 2)
...
Implements OAuth 2.0 Token Exchange (RFC 8693) enabling the MCP server to
exchange service account tokens for user-scoped tokens. This provides an
alternative to refresh tokens for background operations.
**Core Implementation:**
- Added `get_service_account_token()` method to KeycloakOAuthClient for
client_credentials grant
- Added `exchange_token_for_user()` method implementing RFC 8693 token exchange
- Fixed Fernet encryption key handling in RefreshTokenStorage (was incorrectly
base64 decoding already-encoded keys)
- Updated OAuth configuration to support offline_access scope and refresh token
storage infrastructure
**Keycloak Configuration:**
- Enabled `serviceAccountsEnabled` in realm-export.json
- Added `token.exchange.grant.enabled` attribute
- Added `client.token.exchange.standard.enabled` attribute (required for
Keycloak 26.2+ Standard Token Exchange V2)
- Fresh Keycloak imports now correctly enable token exchange
**Docker Compose:**
- Added TOKEN_ENCRYPTION_KEY and ENABLE_OFFLINE_ACCESS environment variables
- Created oauth-tokens volume for refresh token storage
- Configured both mcp-oauth and mcp-keycloak services
**Testing & Documentation:**
- Added tests/manual/test_token_exchange.py - Validates complete RFC 8693 flow
- Added tests/manual/test_nextcloud_impersonate.py - Documents session-based
impersonation limitations
- Added docs/oauth-impersonation-findings.md - Comprehensive investigation
findings and resolution documentation
**Verified Working:**
✅ Service account token acquisition (client_credentials grant)
✅ RFC 8693 token exchange for internal-to-internal tokens
✅ Exchanged tokens validate with Nextcloud APIs
✅ Keycloak 26.4.2 Standard Token Exchange V2 support
**Known Limitations:**
- User impersonation (requested_subject) requires Keycloak Legacy V1 with
preview features
- Cross-client token exchange limited to same realm
- Refresh token storage infrastructure ready but unused (MCP protocol limitation)
Dependencies: aiosqlite>=0.20.0
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-02 22:03:19 +01:00
Chris Coutinho
f34366a260
feat: Add Keycloak OAuth provider support with refresh token storage
...
Implements Keycloak as an external OIDC provider following ADR-002
architecture for background job authentication using offline_access.
## Features
- Keycloak OAuth provider with PKCE and offline_access support
- Refresh token storage with Fernet encryption
- Token verifier for both JWT and opaque tokens
- Multi-client validation (realm-level trust)
- Sample configuration for Keycloak integration
## Implementation
### OAuth Provider (keycloak_oauth.py)
- Authorization Code Flow with PKCE
- Refresh token exchange
- OIDC discovery endpoint support
- Token validation with JWKS
### Token Storage (refresh_token_storage.py)
- Encrypted storage using Fernet symmetric encryption
- SQLite backend for persistence
- Token rotation support
- Per-user token management
### Token Verifier Updates
- Support both JWT (self-encoded) and opaque tokens
- JWKS-based JWT signature verification
- Introspection endpoint fallback for opaque tokens
- Scope extraction from both token types
### Configuration
- .env.keycloak.sample: Example configuration with Keycloak URLs
- docs/keycloak-multi-client-validation.md: Realm-level validation documentation
- app-hooks/post-installation/10-install-user_oidc-app.sh: Updated dependencies
## Architecture Notes
- MCP Server is a protected resource (requires OAuth)
- MCP Client initiates OAuth flow and shares refresh tokens
- Refresh tokens enable background operations without admin credentials
- Supports future token exchange delegation when Keycloak implements it
## References
- ADR-002: Vector Database Background Sync Authentication
- RFC 6749: OAuth 2.0 (offline_access, refresh tokens)
- RFC 7517: JSON Web Key (JWK)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-02 22:03:19 +01:00
Chris Coutinho
529dc4616b
docs: Implement separate clients architecture for Keycloak integration
...
Implements proper OAuth 2.0 separation following RFC 8707 best practices
with distinct resource server and OAuth client configurations.
## Architecture Changes
- Create separate "nextcloud" bearer-only client (resource server)
- Configure "nextcloud-mcp-server" OAuth client with audience mapper
- Audience mapper targets "nextcloud" resource server
- Token flow: aud="nextcloud", azp="nextcloud-mcp-server"
## Benefits
- Proper OAuth client vs resource server separation
- Support for future multi-resource tokens: aud=["nextcloud", "other-service"]
- RFC 8707 Resource Indicators compliance
- Clear requester identification via azp claim
## Documentation Updates
- Correct OAuth flow: MCP Client initiates, handles redirect, shares tokens
- Explain MCP Server as protected resource architecture
- Document offline_access with refresh tokens (Tier 1, current)
- Document token exchange with delegation (Tier 2, future when Keycloak adds support)
- Reference Keycloak issue #38279 for delegation status
## Files
- keycloak/realm-export.json: Add separate clients configuration
- app-hooks/post-installation/15-setup-keycloak-provider.sh: Setup user_oidc with "nextcloud" client
- docs/audience-validation-setup.md: Comprehensive documentation with corrected OAuth flow and delegation comparison
- docker-compose.yml: Fix Keycloak healthcheck (bash TCP instead of curl)
- scripts/test_separate_clients.sh: Verification script for architecture
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-02 22:03:19 +01:00
Chris Coutinho
ef07b1a6c9
docs: Add ADRs
2025-10-31 02:59:44 +01:00
Chris Coutinho
49f9cead69
docs: Update OAuth architecture
2025-10-25 21:54:30 +02:00
Chris Coutinho
415b1c901b
docs: Parse available scopes from registered tools and update docs
2025-10-25 21:16:40 +02:00
Chris Coutinho
d452684535
feat: Split read/write scopes into app:read/write scopes
2025-10-24 04:38:49 +02:00
Chris Coutinho
f2d2dd8068
feat: Enable token introspection for opaque tokens
2025-10-23 15:51:27 +02:00
Chris Coutinho
d915efd3f6
docs: Update jwt docs [skip ci]
2025-10-23 15:26:51 +02:00
Chris Coutinho
1a7ce5b7a7
docs: Update jwt docs [skip ci]
2025-10-23 12:22:34 +02:00
Chris Coutinho
b4039e2e40
docs: Update jwt docs
2025-10-23 11:20:49 +02:00
Chris Coutinho
aa0b6dc5dd
docs: Update docs
2025-10-20 19:10:23 +02:00
Chris Coutinho
c3ff92a8c1
test: Cleanup testing fixtures regarding canceled scopes
2025-10-18 22:02:25 +02:00
Chris Coutinho
83917b3786
perf(notes): Improve notes search performance using async iterators
2025-10-18 22:02:19 +02:00
Chris Coutinho
9de59db718
feat(cookbook): Add full Cookbook app support with 13 tools and 2 resources
...
- Import recipes from URLs using schema.org metadata
- Full CRUD operations for recipes
- Search, categorize, and organize recipes
- Manage keywords/tags and categories
- Configure app settings and trigger reindexing
2025-10-17 03:08:16 +02:00
Chris Coutinho
3ad9198f36
fix(oauth): Remove the option to force_register new clients
2025-10-15 16:27:22 +02:00
Chris Coutinho
97bbc18121
docs: Update README
...
Add comparison to the Nextcloud Assistant & Context Agent
2025-10-15 14:47:43 +02:00
Chris Coutinho
3ed24bd5e3
docs: restructure documentation
2025-10-14 01:23:49 +02:00
Chris Coutinho
4b19964817
docs: Update docs
2025-10-14 01:23:38 +02:00
Chris Coutinho
ea468889ce
docs: Remove pip
2025-10-14 01:23:38 +02:00
Chris Coutinho
9ef9fff2b0
docs: Update Docs
2025-10-14 01:23:38 +02:00
Chris Coutinho
2489a714b8
docs: Update README and docs
2025-10-14 01:23:37 +02:00
Chris Coutinho
17979accb6
test: Add patch for user_oidc app and update docs
2025-10-14 01:23:31 +02:00
Chris Coutinho
9711d1d161
docs: fix duplicate
2025-09-11 17:31:00 +02:00
Chris Coutinho
b3cd2ace34
chore: Update README.md, move docs to directory
2025-09-11 17:28:13 +02:00
Chris Coutinho
c1763ebc6a
ADR search and handling categories in notes
2025-05-07 23:06:22 +02:00
Chris Coutinho
04e4a8e0a8
Add support for attachments in notes
2025-05-06 02:52:51 +02:00