9fab6cb550
Replace two non-compliant token verifiers (NextcloudTokenVerifier and
ProgressiveConsentTokenVerifier) with a single UnifiedTokenVerifier that properly
validates token audiences per MCP Security Best Practices specification.
The previous implementation had a critical security vulnerability where tokens
intended for the MCP server were passed directly to Nextcloud APIs without
proper audience validation (token passthrough anti-pattern). This violates
OAuth 2.0 security principles and the MCP specification.
Changes:
- Add UnifiedTokenVerifier supporting two compliant modes:
* Multi-audience mode (default): Validates tokens contain BOTH MCP and
Nextcloud audiences, enabling direct use without exchange
* Token exchange mode (opt-in): Validates MCP audience only, exchanges
for Nextcloud tokens via RFC 8693 with caching to minimize latency
- Remove token passthrough vulnerability from context.py and context_helper.py
- Implement token exchange caching (5-minute TTL default) to reduce network calls
- Add required environment variables for audience validation:
* NEXTCLOUD_MCP_SERVER_URL - MCP server URL (used as audience)
* NEXTCLOUD_RESOURCE_URI - Nextcloud resource identifier
* TOKEN_EXCHANGE_CACHE_TTL - Cache TTL for exchanged tokens
- Update docker-compose.yml with resource URI configuration for both OAuth modes
- Add comprehensive test suite (29 tests) covering both authentication modes
- Remove legacy NextcloudTokenVerifier and ProgressiveConsentTokenVerifier
Security improvements:
- Eliminates token passthrough anti-pattern
- Enforces proper audience separation between MCP and Nextcloud
- Complies with MCP Security Best Practices and RFC 8707/8693
- Maintains performance with token exchange caching
Test results: 65/65 unit tests passed, 5/5 smoke tests passed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
41 lines
1.7 KiB
Bash
Executable File
41 lines
1.7 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -euox pipefail
|
|
|
|
echo "Installing and configuring OIDC app for testing..."
|
|
|
|
# Check if development OIDC app is mounted at /opt/apps/oidc
|
|
if [ -d /opt/apps/oidc ]; then
|
|
echo "Development OIDC app found at /opt/apps/oidc"
|
|
|
|
# Remove any existing OIDC app in custom_apps (from app store or old symlink)
|
|
if [ -e /var/www/html/custom_apps/oidc ]; then
|
|
echo "Removing existing OIDC in custom_apps..."
|
|
rm -rf /var/www/html/custom_apps/oidc
|
|
fi
|
|
|
|
# Create symlink from custom_apps to the mounted development version
|
|
# Per Nextcloud docs: apps outside server root need symlinks in server root
|
|
echo "Creating symlink: custom_apps/oidc -> /opt/apps/oidc"
|
|
ln -sf /opt/apps/oidc /var/www/html/custom_apps/oidc
|
|
|
|
echo "Enabling OIDC app from /opt/apps (development mode via symlink)"
|
|
php /var/www/html/occ app:enable oidc
|
|
elif [ -d /var/www/html/custom_apps/oidc ]; then
|
|
echo "OIDC app directory found in custom_apps (already installed)"
|
|
php /var/www/html/occ app:enable oidc
|
|
else
|
|
echo "OIDC app not found, installing from app store..."
|
|
php /var/www/html/occ app:install oidc
|
|
php /var/www/html/occ app:enable oidc
|
|
fi
|
|
|
|
# Configure OIDC Identity Provider with dynamic client registration enabled
|
|
php /var/www/html/occ config:app:set oidc dynamic_client_registration --value='true' # NOTE: String
|
|
php /var/www/html/occ config:app:set oidc proof_key_for_code_exchange --value=true --type=boolean
|
|
php /var/www/html/occ config:app:set oidc allow_user_settings --value='enabled'
|
|
php /var/www/html/occ config:app:set oidc default_token_type --value='jwt'
|
|
php /var/www/html/occ config:app:set oidc default_resource_identifier --value='http://localhost:8080'
|
|
|
|
echo "OIDC app installed and configured successfully"
|