docs: Rewrite ADR-004 for Federated Authentication Architecture

Major rewrite of ADR-004 to reflect federated authentication pattern with
shared identity provider (IdP) instead of direct Nextcloud authentication.

Key changes:
- Replaced "Sign-in with Nextcloud" with "Federated Authentication"
- Added shared IdP (Keycloak, Okta, Azure AD) as central auth provider
- MCP server now acts as OAuth client to shared IdP, not Nextcloud
- Single user authentication grants both identity and Nextcloud access
- Updated all diagrams to show 4-party architecture
- Removed authorize_nextcloud tool - uses standard 401 flow
- Added proper token rotation with reuse detection
- Clarified Pattern 3 vs Pattern 4 differences in comparison doc
- Pattern 3 can use external IdPs via user_oidc (not limited to NC)

Architecture benefits:
- True single sign-on with enterprise IdP support
- OAuth-compliant on-behalf-of pattern
- Supports SAML/LDAP backends through IdP
- Nextcloud validates IdP tokens, not MCP-specific tokens

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2025-11-02 23:58:15 +01:00
co-authored by Claude
parent f2af5a39a8
commit bf8120682e
2 changed files with 491 additions and 347 deletions
+133 -76
View File
@@ -102,101 +102,141 @@ A: MCP server never sees refresh tokens (by design)
---
## Pattern 3: MCP Server as OAuth Client (ADR-004 - Solution)
## Pattern 3: Sign-in with Nextcloud (Previous ADR-004 Draft)
### Architecture
```
Layer 1: MCP Authentication Layer 2: Nextcloud Authorization
┌─────────────┐ ┌───────────────── ┌─────────────┐
MCP Client │ MCP Server │ │ Nextcloud
│ (Claude) │ │ (OAuth Client) │ │OAuth Provider
└──────┬──────┘ └────────┬────────┘ └──────┬──────┘
│ │ │
│ 1. MCP Request2. Check stored tokens
├─────────────────────────────────────►│
│ │ │
│ 3. "Need Nextcloud Auth" │ │
│◄─────────────────────────────────────┤ │
│ │ │
│ 4. User initiates OAuth │ 5. OAuth Authorization │
├─────────────────────────────────────►├───────────────────────────────►│
│ │ │
│ │ 6. Access + Refresh Tokens │
│ │◄───────────────────────────────┤
│ │ │
│ │ 7. Store encrypted tokens │
│ ├────────┐ │
│ │ ▼ │
│ │ ┌─────────────┐ │
│ │ │Token Storage│ │
│ │ └─────────────┘ │
│ 8. "Auth Complete" │ │
│◄─────────────────────────────────────┤ │
│ │ │
│ 9. Subsequent requests │ 10. Use stored tokens │
├─────────────────────────────────────►├───────────────────────────────►│
│ │ Nextcloud APIs
│ │ │
│ Background │ 11. Refresh when expired │
│ Worker──►├───────────────────────────────►│
│ (No client needed!) │
┌─────────────┐ ┌─────────────────┐ ┌────────────┐
│ MCP Client ├───────────────────> MCP Server ├────────────────────>│ Nextcloud │
(Claude)(MCP Protocol) │ (OAuth Client) │ (OIDC + APIs) │ (IdP)
└─────────────┘ └─────────────────┘ └────────────┘
┌──────▼────────┐
Token Storage
│ (NC Tokens)
└───────────────┘
```
### Characteristics
| Aspect | Description |
|--------|-------------|
| **Token Flow** | MCP Server owns Nextcloud tokens |
| **Token Storage** | ✅ Encrypted refresh tokens |
| **Token Flow** | MCP Server uses Nextcloud as identity provider |
| **Token Storage** | ✅ Encrypted Nextcloud refresh tokens |
| **Offline Access** | ✅ Full support |
| **Background Workers** | ✅ Use stored refresh tokens |
| **User Consent** | Two OAuth flows (app + Nextcloud) |
| **Complexity** | Medium-High |
| **Security** | High (proper OAuth compliance) |
| **User Consent** | Single OAuth flow (Nextcloud only) |
| **Complexity** | Medium |
| **Security** | High (with token rotation) |
### How It Works
1. **Initial Setup**:
- User connects to MCP server (Layer 1 auth)
- MCP server checks for stored Nextcloud tokens
- If missing, triggers OAuth flow with Nextcloud
- User authorizes MCP server to access Nextcloud
- MCP server stores refresh token (encrypted)
- User tries to use MCP tool
- MCP server returns auth required
- User authenticates with Nextcloud's OIDC endpoint
- Nextcloud may use user_oidc to delegate to external IdP (Keycloak, etc.)
- MCP server stores Nextcloud-issued refresh token (encrypted)
2. **Subsequent Requests**:
- MCP server uses stored access token
- MCP server uses stored Nextcloud tokens
- Refreshes automatically when expired
- No client involvement needed
3. **Background Operations**:
- Worker retrieves stored refresh token
- Gets new access token from Nextcloud
- Refreshes with Nextcloud directly
- Performs operations independently
### Advantages
- ✅ Single sign-on with Nextcloud
- ✅ True offline access capability
- ✅ OAuth-compliant with proper consent
-Background workers can operate independently
-Tokens persist across MCP sessions
- ✅ Users can revoke access anytime
-Supports external IdPs via user_oidc
-Simpler integration - only one OAuth endpoint
### Trade-offs
- Users must authorize twice (MCP + Nextcloud)
- More complex token management
- Requires secure token storage
- Authentication flows through Nextcloud
- Nextcloud manages IdP relationships (via user_oidc)
- MCP server only knows about Nextcloud, not the underlying IdP
---
## Pattern 4: Federated Authentication Architecture (ADR-004 - Solution)
### Architecture
```
┌─────────────┐ ┌─────────────────┐ ┌──────────────┐ ┌────────────┐
│ MCP Client │◄──────401──────│ MCP Server │◄────OAuth──────│ Shared IdP │──Validates──►│ Nextcloud │
│ (Claude) │ │ (OAuth Client) │ (On-Behalf) │ (Keycloak) │ Tokens │(Resource) │
└─────────────┘ └─────────────────┘ └──────────────┘ └────────────┘
┌───────▼────────┐
│ Token Storage │
│ (IdP Tokens) │
└────────────────┘
```
### Characteristics
| Aspect | Description |
|--------|-------------|
| **Token Flow** | Shared IdP issues tokens for Nextcloud access |
| **Token Storage** | ✅ Encrypted IdP refresh tokens |
| **Offline Access** | ✅ Full support |
| **Background Workers** | ✅ Use stored IdP refresh tokens |
| **User Consent** | Single OAuth flow (IdP manages consent) |
| **Complexity** | Medium-High |
| **Security** | Highest (enterprise-grade IdP) |
### How It Works
1. **Initial Setup**:
- MCP client connects, receives 401
- Browser opens MCP server OAuth URL
- MCP server redirects to shared IdP
- User authenticates once to IdP
- IdP shows consent for both identity and Nextcloud access
- MCP server stores IdP refresh token (encrypted)
- MCP server issues session token to client
2. **Subsequent Requests**:
- MCP server validates session token
- Uses stored IdP token for Nextcloud
- Refreshes with IdP when expired
- No client involvement needed
3. **Background Operations**:
- Worker retrieves stored IdP refresh token
- Gets new access token from IdP
- Uses token to access Nextcloud
- Performs operations independently
### Advantages
- ✅ True single sign-on (SSO)
- ✅ Enterprise-ready with SAML/LDAP support
- ✅ OAuth-compliant with proper delegation
- ✅ Direct IdP relationship - no intermediary
- ✅ Flexible - can swap resource servers
- ✅ Industry-standard federated pattern
### Trade-offs
- Requires shared IdP infrastructure
- More complex initial setup
- Token validation overhead
---
## Comparison Matrix
| Feature | Pass-Through | Token Exchange | MCP as OAuth Client |
|---------|--------------|----------------|-------------------|
| **Offline Access** | ❌ No | ❌ No | ✅ Yes |
| **Background Workers** | ❌ No | ❌ No* | ✅ Yes |
| **Token Storage** | None | None | Refresh tokens |
| **OAuth Compliance** | ✅ Full | ⚠️ Violates | ✅ Full |
| **User Consent** | Once | Implicit | Twice |
| **Implementation Complexity** | Low | High | Medium |
| **Security** | High | Medium | High |
| **Suitable For** | Interactive only | N/A (flawed) | Full platform |
| Feature | Pass-Through | Token Exchange | Sign-in with NC | Federated Auth |
|---------|--------------|----------------|-----------------|----------------|
| **Offline Access** | ❌ No | ❌ No | ✅ Yes | ✅ Yes |
| **Background Workers** | ❌ No | ❌ No* | ✅ Yes | ✅ Yes |
| **Token Storage** | None | None | NC refresh tokens | IdP refresh tokens |
| **OAuth Compliance** | ✅ Full | ⚠️ Violates | ✅ Full | ✅ Full |
| **User Consent** | Once | Implicit | Once (NC) | Once (IdP) |
| **Implementation Complexity** | Low | High | Medium | Medium-High |
| **Security** | High | Medium | High | Highest |
| **Enterprise Ready** | ❌ No | ❌ No | ⚠️ Indirect | ✅ Yes |
| **Identity Provider** | Client-managed | N/A | Nextcloud (+user_oidc) | Shared IdP |
| **Suitable For** | Interactive only | N/A (flawed) | Small teams | Enterprise |
\* *Requires service accounts that violate OAuth principles*
@@ -214,24 +254,34 @@ A: MCP server never sees refresh tokens (by design)
- **Result**: Circular dependencies, OAuth violations
- **Learning**: MCP protocol constraints are fundamental
### Stage 3: Application Pattern ✅
### Stage 3: Sign-in with Nextcloud ⚠️
- **Goal**: True offline access with OAuth compliance
- **Result**: MCP server as independent OAuth client
- **Trade-off**: Additional complexity justified by requirements
- **Result**: MCP server uses Nextcloud as identity provider
- **Limitation**: Tight coupling to Nextcloud, no enterprise IdP
### Stage 4: Federated Pattern ✅
- **Goal**: Enterprise-ready offline access
- **Result**: Shared IdP for both MCP server and Nextcloud
- **Trade-off**: Additional infrastructure justified by enterprise needs
---
## Key Insights
1. **The MCP Protocol Boundary**: The MCP protocol creates a fundamental boundary between client and server token management. Attempting to breach this boundary (ADR-002) leads to architectural contradictions.
1. **Pattern 3 vs Pattern 4**: Both support external IdPs, but differ in integration approach:
- Pattern 3: MCP → Nextcloud OIDC → (user_oidc) → External IdP
- Pattern 4: MCP → External IdP directly (Nextcloud also uses same IdP)
- Choose Pattern 3 for Nextcloud-centric deployments, Pattern 4 for IdP-centric enterprises
2. **Service Accounts Don't Solve User Problems**: Using service accounts for user operations violates OAuth's core principle of acting on behalf of users, not as a service identity.
2. **The MCP Protocol Boundary**: The MCP protocol creates a fundamental boundary between client and server token management. Attempting to breach this boundary (ADR-002) leads to architectural contradictions.
3. **Double OAuth is Industry Standard**: Major platforms (Zapier, IFTTT, Microsoft Power Automate) use this pattern - the integration platform is an OAuth client that maintains its own relationships with upstream services.
3. **Service Accounts Don't Solve User Problems**: Using service accounts for user operations violates OAuth's core principle of acting on behalf of users, not as a service identity.
4. **Refresh Tokens Are The Solution**: The OAuth spec designed refresh tokens specifically for offline access. Rejecting them (as ADR-002 did) means rejecting the standard solution.
4. **Double OAuth is Industry Standard**: Major platforms (Zapier, IFTTT, Microsoft Power Automate) use this pattern - the integration platform is an OAuth client that maintains its own relationships with upstream services.
5. **Complexity is Justified**: The additional complexity of managing two OAuth flows is acceptable when offline access is a requirement. The alternative is no offline access at all.
5. **Refresh Tokens Are The Solution**: The OAuth spec designed refresh tokens specifically for offline access. Rejecting them (as ADR-002 did) means rejecting the standard solution.
6. **Complexity is Justified**: The additional complexity of managing OAuth flows is acceptable when offline access is a requirement. The alternative is no offline access at all.
---
@@ -243,12 +293,19 @@ Use **Pattern 1 (Pass-Through)** if:
- Only interactive operations required
- Simplicity is priority
### For Platform Deployments
Use **Pattern 3 (MCP as OAuth Client)** if:
### For Teams Using Nextcloud
Use **Pattern 3 (Sign-in with Nextcloud)** if:
- Background sync/indexing required
- Multiple users need service
- Building integration platform
- Offline operations critical
- Nextcloud manages your authentication
- Can use external IdPs via user_oidc
- Prefer single integration point through Nextcloud
### For Enterprise Deployments
Use **Pattern 4 (Federated Authentication)** if:
- Enterprise IdP already exists (Keycloak, Okta, Azure AD)
- Multiple resource servers beyond Nextcloud
- Compliance requirements for centralized auth
- Building platform for multiple organizations
### Never Use Pattern 2
Token Exchange with service accounts should not be used as it: