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
/oauth2/token/introspect and /oauth2/token/revoke accept any caller. They are registered in registerOAuthRoutes (internal/handler/oauth.go:156-171) with no Security and no auth middleware, and the handlers derive the tenant from the submitted token itself rather than from an authenticated caller identity:
introspectOp — internal/handler/oauth.go:328-334
revokeOp — internal/handler/oauth.go:337-340
RFC 7662 §2.1: "To prevent token scanning attacks, the endpoint MUST also require some form of authorization to access this endpoint." An open introspection endpoint lets anyone probe token validity and metadata (active status, scopes, cnf, expiry) by submitting tokens — a token-scanning / validity-oracle surface.
For revocation, RFC 7009 §2.1 requires client authentication; an unauthenticated /revoke lets anyone who can present a token force its revocation. Because revoke always returns 200 per RFC 7009 §2.2, it's also a blind operation with no caller accountability.
Impact
Introspection: token-scanning / validity oracle for anyone who obtains or guesses a token.
Revocation: anyone holding a token can force-revoke it — an availability/DoS surface against agent credentials.
No caller-identity audit trail on either endpoint; the tenant comes from the token, not the requester.
Proposed change
Require caller authentication on both endpoints (RFC 7662 §2.1 / RFC 7009 §2.1):
Confidential clients authenticate (client_secret / private_key_jwt, or the internal-service secret), consistent with how the rest of the platform authenticates service callers.
Public clients: per RFC 7662, still require some authorization — decide the policy (e.g. restrict introspection to the internal mesh, or require a client credential alongside the token).
Keep the RFC 7009 §2.2 "always 200" response for revoke, but gate access first.
Derive/verify the tenant from the authenticated caller and cross-check it against the token's tenant, rather than trusting the token alone.
Problem
/oauth2/token/introspectand/oauth2/token/revokeaccept any caller. They are registered inregisterOAuthRoutes(internal/handler/oauth.go:156-171) with noSecurityand no auth middleware, and the handlers derive the tenant from the submitted token itself rather than from an authenticated caller identity:introspectOp—internal/handler/oauth.go:328-334revokeOp—internal/handler/oauth.go:337-340RFC 7662 §2.1: "To prevent token scanning attacks, the endpoint MUST also require some form of authorization to access this endpoint." An open introspection endpoint lets anyone probe token validity and metadata (active status, scopes,
cnf, expiry) by submitting tokens — a token-scanning / validity-oracle surface.For revocation, RFC 7009 §2.1 requires client authentication; an unauthenticated
/revokelets anyone who can present a token force its revocation. Because revoke always returns200per RFC 7009 §2.2, it's also a blind operation with no caller accountability.Impact
Proposed change
Require caller authentication on both endpoints (RFC 7662 §2.1 / RFC 7009 §2.1):
private_key_jwt, or the internal-service secret), consistent with how the rest of the platform authenticates service callers.References
internal/handler/oauth.go:156-171(registration),:328-340(handlers)/oauth2/token/verifyforward-auth endpoint).