You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit implements and documents both RFC 8693 token exchange tiers
from ADR-002, enabling both production-ready delegation and advanced
impersonation capabilities.
- Enable Keycloak preview features (`--features=preview`) to support
both Standard V2 and Legacy V1 token exchange modes
- Update Tier 1 status from "NOT IMPLEMENTED" to "IMPLEMENTED (Legacy V1)"
- Add detailed empirical testing results showing:
- Standard V2 rejects `requested_subject` parameter
- Legacy V1 accepts parameter but requires impersonation permissions
- Complete configuration steps for enabling impersonation
- Add comparison table showing when to use each tier
- Add "When to Use" guidance for both tiers
- Document that Tier 2 (Delegation) is the recommended default
- Update docstring to document both Tier 1 and Tier 2 support
- Add tier-specific logging (shows which tier is being used)
- Document permission requirements for Tier 1 impersonation
**tests/integration/auth/test_token_exchange_standard_v2.py**:
- Test delegation without impersonation (Tier 2)
- Verify sub claim remains unchanged (service account identity)
- Verify no special permissions required
- Test exchanged tokens work with Nextcloud APIs
- All tests PASS ✅
**tests/integration/auth/test_token_exchange_legacy_v1.py**:
- Test impersonation with `requested_subject` (Tier 1)
- Verify sub claim changes to target user
- Auto-skip if impersonation permissions not configured
- Document permission requirements in test docstrings
- Test exchanged tokens work with Nextcloud APIs
**tests/manual/test_impersonation.py**:
- Comprehensive impersonation validation script
- Tests both Standard V2 and Legacy V1 behavior
- Decodes JWT tokens to verify sub claim changes
- Validates tokens against Nextcloud APIs
**tests/manual/configure_impersonation.py**:
- Automated permission configuration helper
- Documents manual Keycloak CLI configuration steps
Both token exchange tiers are now fully implemented and tested:
- **Tier 2 (Delegation)** - ✅ RECOMMENDED
- Standard V2 (production-ready)
- No special permissions required
- Service account identity preserved
- **Tier 1 (Impersonation)** - ✅ Advanced use only
- Legacy V1 (--features=preview required)
- Requires manual permission grant via Keycloak CLI
- Subject claim changes to target user
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
This tier is documented for completeness but is not currently implemented due to lack of provider support.
144
+
**Status**: Implemented and working with Keycloak Legacy V1 (`--features=preview`). Requires additional permission configuration. Recommended for advanced use cases only.
145
145
146
-
#### 1.1 Impersonation Flow (Conceptual)
146
+
**When to Use**: When you need the exchanged token to have the exact same identity as the target user (sub claim changes). This provides the cleanest separation but requires preview features.
147
+
148
+
#### 1.1 Impersonation Flow
147
149
148
150
```python
149
-
asyncdefexchange_for_impersonated_user_token(
150
-
service_token: str,
151
+
asyncdefexchange_token_for_user(
152
+
subject_token: str,
151
153
target_user_id: str,
152
-
scopes: list[str]
153
-
) -> str:
154
-
"""Exchange service token to impersonate specific user (NOT IMPLEMENTED)"""
154
+
audience: str|None=None,
155
+
scopes: list[str] |None=None,
156
+
) -> dict:
157
+
"""Exchange service token to impersonate specific user.
158
+
159
+
Requires Keycloak Legacy V1 (--features=preview) and impersonation permissions.
160
+
The returned token will have the target_user_id as the 'sub' claim.
"requested_subject": target_user_id, # Impersonate this user
165
-
"audience": "nextcloud",
166
-
"scope": "".join(scopes)
167
-
},
168
-
auth=(client_id, client_secret)
169
-
)
184
+
**Implementation Requirements**:
185
+
- ✅ Keycloak Legacy V1 with `--features=preview` flag
186
+
- ✅ Impersonation role granted to service account (see configuration below)
187
+
- ❌ NOT supported in Keycloak Standard V2 (rejects `requested_subject` parameter)
188
+
- ⚠️ Very few OIDC providers support user impersonation via token exchange
170
189
171
-
response.raise_for_status()
172
-
return response.json()["access_token"]
190
+
**Empirical Testing (2025-11-02)**:
191
+
192
+
Tested impersonation with `requested_subject` parameter against Keycloak 26.4.2:
193
+
194
+
**Test Command**: `uv run python tests/manual/test_impersonation.py`
195
+
196
+
**Keycloak Standard V2 Result**:
197
+
```
198
+
HTTP/1.1 400 Bad Request
199
+
{
200
+
"error": "invalid_request",
201
+
"error_description": "Parameter 'requested_subject' is not supported for standard token exchange"
202
+
}
173
203
```
174
204
175
-
**Why Not Implemented**:
176
-
- Keycloak Standard V2 doesn't support `requested_subject` parameter
177
-
- Requires Legacy Keycloak V1 with preview features (not production-ready)
178
-
- Very few OIDC providers support user impersonation via token exchange
205
+
**Confirmation**: Keycloak explicitly rejects `requested_subject` in Standard V2, confirming this feature is unsupported. The error message is unambiguous - this parameter is not available in the current production token exchange implementation.
179
206
180
-
**See**: `docs/oauth-impersonation-findings.md` for detailed investigation
207
+
**Keycloak Legacy V1 Result - Initial Test** (with `--features=preview`):
208
+
```
209
+
HTTP/1.1 403 Forbidden
210
+
{
211
+
"error": "access_denied",
212
+
"error_description": "Client not allowed to exchange"
**Analysis**: Legacy V1 **accepts** the `requested_subject` parameter (error changed from "not supported" to "not allowed"), indicating the feature is present but requires permission configuration.
222
+
223
+
**Configuration Steps to Enable Impersonation**:
224
+
225
+
1.**Enable Keycloak preview features** (in docker-compose.yml):
226
+
```yaml
227
+
command:
228
+
- "start-dev"
229
+
- "--features=preview"# Required for Legacy V1 token exchange
230
+
```
231
+
232
+
2. **Grant impersonation role to service account** (using Keycloak CLI):
Original sub: service-account-nextcloud-mcp-server
263
+
New sub: 47c3ba5a-9104-45e0-b84e-0e39ab942c9c
264
+
➡️ The subject claim CHANGED - impersonation worked!
265
+
```
266
+
267
+
**Nextcloud API Validation**:
268
+
The impersonated token successfully authenticated with Nextcloud APIs, confirming the token is valid and properly represents the target user.
269
+
270
+
**Implementation Status**: Impersonation **IS IMPLEMENTED** and working with Keycloak Legacy V1. The implementation has been tested and verified to work correctly when properly configured.
271
+
272
+
**Production Considerations**:
273
+
- ⚠️ Requires preview features (`--features=preview`) - not production-ready
274
+
- ⚠️ Requires Legacy V1 token exchange (may be deprecated in future Keycloak versions)
275
+
- ⚠️ Requires manual CLI configuration for each service account
276
+
- ⚠️ More complex permission model compared to delegation
277
+
278
+
**When to Use Tier 1 (Impersonation)**:
279
+
- ✅ You need the exchanged token to have the exact same identity as the target user
280
+
- ✅ You want the cleanest separation (sub claim changes completely)
281
+
- ✅ Your environment can support preview features
282
+
- ✅ You have operational processes to manage impersonation permissions
283
+
284
+
**Recommendation**: For most use cases, use Tier 2 (Delegation) instead. It provides equivalent "act on-behalf-of" capability using production-ready Standard V2 token exchange. Use Tier 1 only when you specifically need identity impersonation.
285
+
286
+
**Test Scripts**:
287
+
-`tests/manual/test_impersonation.py` - Complete impersonation test with validation
**Status**: Implemented and working with Keycloak Standard V2 (production-ready). This is the **recommended** approach for most use cases.
294
+
295
+
**When to Use**: When you need "act on-behalf-of" functionality with production-ready features. The service account maintains its identity (sub claim unchanged) but acts on behalf of the user. Fully supported in Keycloak Standard V2 without preview features.
**Note**: Full delegation with `act` claim requires provider support that is currently very rare. Keycloak tracking: [Issue #38279](https://github.com/keycloak/keycloak/issues/38279)
0 commit comments