fix: Complete Keycloak external IdP integration with all tests passing
This commit completes the Keycloak external identity provider integration,
implementing the ADR-002 architecture where Keycloak acts as an external
OAuth/OIDC provider and Nextcloud validates tokens via the user_oidc app.
Architecture:
MCP Client → Keycloak (OAuth) → MCP Server → Nextcloud user_oidc → APIs
Key Fixes:
1. Keycloak JWT token configuration
- Added 'sub' claim protocol mapper to realm-export.json
- Updated token_verifier.py to accept both 'sub' and 'preferred_username'
- Ensures tokens contain required OIDC claims
2. Keycloak hostname configuration for Docker networking
- Implemented --hostname-backchannel-dynamic=true in docker-compose.yml
- External clients use localhost:8888 (public)
- Internal services use keycloak:8080 (Docker network)
- Same issuer (localhost:8888) everywhere for token consistency
- Restored frontendUrl in realm attributes
3. MCP server provider mode detection
- Fixed URL normalization to handle port differences (http://app vs http://app:80)
- Correctly distinguishes integrated mode vs external IdP mode
- Removes explicit default ports (80 for HTTP, 443 for HTTPS)
4. Nextcloud SSRF protection configuration
- Added allow_local_remote_servers=true to user_oidc install script
- Enables Nextcloud to fetch JWKS from internal Keycloak container
- Required for external IdP token validation
5. OAuth lifespan cleanup
- Fixed RefreshTokenStorage close() error (uses context managers)
- Added safe cleanup for oauth_client with hasattr check
- Prevents session crash on shutdown
6. Test suite fixes
- Fixed test_user_auto_provisioning to reflect actual behavior
- Fixed test_scope_filtering_with_keycloak tool name (nc_webdav_write_file)
- Updated test_keycloak_oauth_client_credentials_discovery for hostname config
- All 11 Keycloak external IdP tests now passing
Testing:
✅ All 11 tests in test_keycloak_external_idp.py passing
✅ OAuth token acquisition via Playwright automation
✅ Token validation through Nextcloud user_oidc app
✅ Write operations (Notes create, Calendar create, File upload)
✅ Read operations (search, list, get)
✅ Token persistence across multiple operations
✅ User authentication and bearer token validation
✅ Scope-based tool filtering
✅ Error handling for invalid operations
Implementation validates:
- ADR-002 external identity provider architecture
- No admin credentials needed in MCP server
- Centralized identity management via Keycloak
- Standards-based OAuth 2.0 / OIDC integration
- User auto-provisioning from IdP claims
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>