Tracks deferred follow-up work identified during the review of #5691 (XAA auth strategy CRD support). Each item was checked against the ID-JAG draft (draft-ietf-oauth-identity-assertion-authz-grant-04) and found non-blocking for the CRD-support PR — hence this tracking issue rather than blocking that PR.
Refs #5681.
A. RFC 9470 step-up detection for XAA Step A
Context: ID-JAG draft-04 §9.2 says the IdP may return insufficient_user_authentication on the Step A token exchange when the subject's auth context is too weak, similar to RFC 9470. Today XAAStrategy propagates the raw Step A OAuth error but does not recognize this case or surface a step-up signal.
Scope: In the Step A error path (pkg/vmcp/auth/strategies/xaa.go), detect insufficient_user_authentication, log a structured WARN with acr_values/max_age, and surface ErrStepUpRequired → an RFC 9470 WWW-Authenticate challenge.
Caveats: Draft §9.2 is explicitly TBD and normatively only "may" (not a MUST) — track draft evolution before fixing a wire format (the draft's own example uses a JSON max_age body field, not an RFC 9470 header). Also entangled with the known pre-SDK-403 timing problem (token-missing is discovered inside the MCP handler, but the challenge must be emitted pre-SDK).
B. RFC 6749 §3.3 scope-grammar validation (defense-in-depth)
Context: parseXAAConfig copies cfg.Scopes verbatim into the Step A/B requests. RFC 6749 §3.3 defines the scope wire grammar (space-delimited scope-tokens, restricted charset). Malformed scopes currently reach the IdP/AS and produce an opaque invalid_scope.
Scope: Add a cheap grammar check in parseXAAConfig to reject malformed scopes before sending, per the repo's "Validate Parsed Results" rule.
Caveat: The §3.3 MUSTs bind servers (IdP/RAS), not the client — so this is defense-in-depth, not ID-JAG compliance. Low priority.
C. Validate MCPExternalAuthConfig secret refs at reconcile across all auth types
Context: MCPExternalAuthConfigReconciler stamps Valid=True without verifying that referenced Secrets/keys exist. A typo'd SecretKeyRef surfaces only at pod container-create (inline mode) or vMCP serve time (discovered mode). OBO already validates handler-side concerns before Valid=True (triageOBOValidation).
Scope: Add a reconcile-time step that Gets each non-nil *SecretKeyRef — tokenExchange.ClientSecretRef, headerInjection.ValueSecretRef, xaa.IDPClientSecretRef/TargetClientSecretRef, etc. — and sets Valid=False / Reason=InvalidConfig on miss. Do it consistently across all auth types, not XAA-only.
Caveat: Requires adding Secret get RBAC to that reconciler — an added permission surface to weigh.
Tracks deferred follow-up work identified during the review of #5691 (XAA auth strategy CRD support). Each item was checked against the ID-JAG draft (
draft-ietf-oauth-identity-assertion-authz-grant-04) and found non-blocking for the CRD-support PR — hence this tracking issue rather than blocking that PR.Refs #5681.
A. RFC 9470 step-up detection for XAA Step A
Context: ID-JAG draft-04 §9.2 says the IdP may return
insufficient_user_authenticationon the Step A token exchange when the subject's auth context is too weak, similar to RFC 9470. TodayXAAStrategypropagates the raw Step A OAuth error but does not recognize this case or surface a step-up signal.Scope: In the Step A error path (
pkg/vmcp/auth/strategies/xaa.go), detectinsufficient_user_authentication, log a structured WARN withacr_values/max_age, and surfaceErrStepUpRequired→ an RFC 9470WWW-Authenticatechallenge.Caveats: Draft §9.2 is explicitly TBD and normatively only "may" (not a MUST) — track draft evolution before fixing a wire format (the draft's own example uses a JSON
max_agebody field, not an RFC 9470 header). Also entangled with the known pre-SDK-403 timing problem (token-missing is discovered inside the MCP handler, but the challenge must be emitted pre-SDK).insufficient_user_authenticationdetection + step-up surfacing (pending draft stabilization)B. RFC 6749 §3.3 scope-grammar validation (defense-in-depth)
Context:
parseXAAConfigcopiescfg.Scopesverbatim into the Step A/B requests. RFC 6749 §3.3 defines the scope wire grammar (space-delimitedscope-tokens, restricted charset). Malformed scopes currently reach the IdP/AS and produce an opaqueinvalid_scope.Scope: Add a cheap grammar check in
parseXAAConfigto reject malformed scopes before sending, per the repo's "Validate Parsed Results" rule.Caveat: The §3.3 MUSTs bind servers (IdP/RAS), not the client — so this is defense-in-depth, not ID-JAG compliance. Low priority.
parseXAAConfigC. Validate
MCPExternalAuthConfigsecret refs at reconcile across all auth typesContext:
MCPExternalAuthConfigReconcilerstampsValid=Truewithout verifying that referenced Secrets/keys exist. A typo'dSecretKeyRefsurfaces only at pod container-create (inline mode) or vMCP serve time (discovered mode). OBO already validates handler-side concerns beforeValid=True(triageOBOValidation).Scope: Add a reconcile-time step that
Gets each non-nil*SecretKeyRef—tokenExchange.ClientSecretRef,headerInjection.ValueSecretRef,xaa.IDPClientSecretRef/TargetClientSecretRef, etc. — and setsValid=False/Reason=InvalidConfigon miss. Do it consistently across all auth types, not XAA-only.Caveat: Requires adding Secret
getRBAC to that reconciler — an added permission surface to weigh.