docs: Reject service account tokens as OAuth authentication pattern
Service account tokens (client_credentials grant) violate OAuth "act on-behalf-of" principles and have been moved to ADR-002's "Will Not Implement" section. ## Problem Discovery Testing revealed that service account tokens create Nextcloud user accounts (e.g., `service-account-nextcloud-mcp-server`) due to user_oidc's bearer provisioning feature. This violates core OAuth principles: - ❌ Creates stateful server identity in Nextcloud - ❌ All actions attributed to service account, not real user - ❌ Breaks audit trail and user attribution - ❌ Service account becomes "admin by another name" ## Changes ### Documentation (ADR-002) - Moved service account (old Tier 1) to "Will Not Implement" section - Added "OAuth Act On-Behalf-Of Principle" section - Renumbered tiers: - Tier 1: Impersonation (NOT IMPLEMENTED) - Tier 2: Delegation via token exchange (IMPLEMENTED) - Updated status to reflect rejection of service accounts ### Code Warnings - Added comprehensive warning to KeycloakOAuthClient.get_service_account_token() - Clarified VALID use: only as subject_token for RFC 8693 token exchange - Clarified INVALID use: direct API access with service account token ### Supporting Documentation - CLAUDE.md: Removed outdated "Tier 1" references, added rejection note - oauth-impersonation-findings.md: Added prominent update banner - audience-validation-setup.md: Updated tier numbers, added rejection note - tests/manual/test_token_exchange.py: Added warning comment ## Valid Patterns (ADR-002) ✅ Foreground operations: User's access token from MCP request ✅ Background operations: Token exchange (impersonation/delegation) ✅ Offline access: Refresh tokens with user consent ❌ Service accounts: Creates independent server identity (REJECTED) ## Alternative If service account pattern is truly needed, use BasicAuth mode instead of OAuth mode. OAuth mode MUST maintain "act on-behalf-of" semantics. Related: c12df98 (revert of service account test) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,16 @@ async def main():
|
||||
logger.info("")
|
||||
|
||||
# Step 3: Get service account token
|
||||
# ⚠️ WARNING: Service account tokens MUST NOT be used directly with Nextcloud APIs!
|
||||
# Using this token directly violates OAuth "act on-behalf-of" principles:
|
||||
# - Creates Nextcloud user: service-account-{client_id}
|
||||
# - Breaks audit trail (actions not attributable to real user)
|
||||
# - Creates stateful server identity in Nextcloud
|
||||
#
|
||||
# VALID USE: ONLY as subject_token for RFC 8693 token exchange (Step 4 below)
|
||||
# INVALID USE: Direct API access (see ADR-002 "Will Not Implement" section)
|
||||
#
|
||||
# If you need background operations without token exchange support, use BasicAuth mode.
|
||||
logger.info("Step 3: Requesting service account token (client_credentials)...")
|
||||
try:
|
||||
service_token_response = await oauth_client.get_service_account_token(
|
||||
|
||||
Reference in New Issue
Block a user