Chris Coutinho
de99296779
feat: implement scope-based audience mapping and RFC 9728 support
...
This commit removes hardcoded Keycloak audience mappers and implements
dynamic audience assignment based on OAuth client scopes and RFC 8707
resource indicators.
## MCP Server Changes
### Protected Resource Metadata (app.py)
- Change resource field from client_id to URL (RFC 9728 compliance)
- Use `{mcp_server_url}/mcp` as resource identifier
- Update DCR registration to include all Nextcloud API scopes
- Add resource_url parameter to client registration
### Client Registration (auth/client_registration.py)
- Add resource_url parameter to register_client()
- Pass resource_url to DCR endpoint
- Support RFC 9728 resource metadata
### Browser OAuth Routes (auth/browser_oauth_routes.py)
- Enhanced error logging for token exchange failures
- Log HTTP status code and response body for debugging
- Improved error messages for OAuth provisioning issues
### Token Verifier (auth/progressive_token_verifier.py)
- Add introspection_uri and client_secret parameters
- Initialize HTTP client for introspection requests
- Enable opaque token validation support
## Keycloak Configuration
### realm-export.json
- **Remove** hardcoded `audience-mcp-server` protocol mapper
- Audience now determined by client scopes:
- External clients: RFC 8707 resource parameter → `aud: {resource_url}`
- MCP Server: `token-exchange-nextcloud` scope → `aud: "nextcloud"`
### OIDC App (third_party/oidc)
- Updated submodule with RFC 9728 support
- Added resource_url database field
- Enhanced introspection authorization logic
## Architecture
Two separate audience flows:
1. **Gemini CLI → MCP Server**
- Client requests: `resource=http://localhost:8002/mcp `
- Token audience: `aud: "http://localhost:8002/mcp "`
- MCP server validates via progressive_token_verifier
2. **MCP Server → Nextcloud APIs**
- MCP server includes: `scope=token-exchange-nextcloud`
- Token audience: `aud: "nextcloud"` (via scope mapper)
- Nextcloud user_oidc validates via SelfEncodedValidator
## Benefits
- ✅ RFC 8707 compliant (resource indicators)
- ✅ RFC 9728 compliant (protected resource metadata)
- ✅ Dynamic audience based on OAuth context
- ✅ Fixes Gemini CLI authentication failures
- ✅ Maintains Nextcloud API access for background jobs
- ✅ Clear security boundaries between flows
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-04 05:28:58 +01:00
Chris Coutinho
849c67c32a
fix: Complete Keycloak external IdP integration with all tests passing
...
This commit completes the Keycloak external IdP integration for the MCP
server, implementing ADR-002 Tier 2 (External Identity Provider) with
full Bearer token authentication support.
Key Changes:
1. **Keycloak backchannel-dynamic configuration**
- Added --hostname-strict=false and --hostname-backchannel-dynamic=true
- Allows external issuer (localhost:8888) with internal endpoints (keycloak:8080)
- Solves Docker networking issue where containers can't reach localhost
2. **CORSMiddleware Bearer token patch**
- Created app-hooks/patches/cors-bearer-token.patch from upstream commit 8fb5e77db82
- Allows Bearer tokens to bypass CORS/CSRF checks (stateless authentication)
- Applied via post-installation hook 20-apply-cors-bearer-token-patch.sh
- Enables app-specific APIs (Notes, Calendar, etc.) to work with Bearer tokens
3. **Patch organization**
- Moved patches to app-hooks/patches/ directory
- Updated docker-compose.yml to mount entire app-hooks directory
- Consolidated patch management for better maintainability
4. **Test improvements**
- All 11 Keycloak integration tests passing
- Tests validate OAuth token acquisition, MCP connectivity, token validation,
tool execution, token persistence, user provisioning, scope filtering,
and error handling
Architecture:
- Keycloak acts as external OAuth/OIDC identity provider
- MCP server uses Keycloak tokens to access Nextcloud APIs
- Nextcloud user_oidc app validates Bearer tokens from Keycloak
- No admin credentials needed - all API access uses user's OAuth tokens
Cache Note:
- Discovery and JWKS caches must be cleared when switching Keycloak configurations
- Use: docker compose exec redis redis-cli DEL "<cache-key>"
- Or: docker compose exec app php occ user_oidc:provider keycloak --clientid nextcloud
Related:
- ADR-002: Vector sync background jobs authentication
- Validates external IdP integration pattern
- Demonstrates offline_access with refresh tokens (Tier 1 & 2)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-11-02 22:03:20 +01:00
Chris Coutinho
50b69a2531
fix: Add support for RFC 7592 client registration and deletion
2025-10-24 19:19:27 +02:00
Chris Coutinho
8e0a4d8ce5
feat(auth): Add support for client registration deletion
2025-10-24 18:54:24 +02:00
Chris Coutinho
1e877f17f7
test: Replace persistent OAuth client cache with session-scoped fixtures
...
Remove file-based caching of OAuth client credentials and implement automatic
client lifecycle management for test fixtures.
Changes:
- Add RFC 7592 client deletion function in auth/client_registration.py
- Remove cache_file parameter from _create_oauth_client_with_scopes helper
- Update all OAuth credential fixtures to use yield/finalizer pattern
- Add automatic client cleanup at end of test session (best-effort)
- Remove persistent .nextcloud_oauth_*.json cache files
Benefits:
- No persistent cache files cluttering repository
- Fresh OAuth clients created for each test session via DCR
- Automatic cleanup attempts (RFC 7592 DELETE endpoint)
- Cleaner test environment with proper fixture lifecycle
Note: Client deletion may fail due to Nextcloud authentication middleware
(logged as warning). The key improvement is removing persistent cache files.
OAuth clients may accumulate in Nextcloud but can be cleaned manually.
2025-10-24 08:11:22 +02:00
Chris Coutinho
e48f5f3f30
feat(server): Add support for custom OIDC scopes and permissions via JWTs
2025-10-23 08:37:36 +02:00
Chris Coutinho
c069d78f80
feat: Initialize JWT-scoped tools
2025-10-22 06:21:16 +02:00
Chris Coutinho
63b898c0e3
chore: Update logs
2025-10-20 22:57:18 +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
33b962a7fc
test: Setup interactive browser test
2025-10-14 01:23:30 +02:00
Chris Coutinho
4d7e4b9a4b
feat(server): Experimental support for OAuth2/OIDC authentication
2025-10-14 01:22:15 +02:00