Class AgentRuleTokenService
xl.features.ai.agent-rules.oauth:
- Service identity (
serviceToken()): short-lived access tokens via the client-credentials grant (RFC 6749 section 4.4) against the platform IdP. Dispatches to assistant-resolved agents authenticate as this service principal — the agent's permissions become the service account's roles, reviewable in one place, and tokens are auto-refreshed rather than pasted and left to expire. - Approver on-behalf-of (
exchangeApproverToken(java.lang.String, java.lang.String)): RFC 8693 token exchange of an approver's own access token, so an action a human approved runs on the approver's identity (sub = approver) with the exchange client as the acting party — the audit trail an approval should leave. Configured separately under...oauth.exchangebecause the exchanging client is usually Release's own login client (the IdP requires the subject token's audience to include the requesting client).
Built on Spring Security's OAuth2 client, but entirely module-local: the registrations and
authorized-client manager are private to this service, deliberately NOT the OIDC auth
plugin's beans — these identities must exist whatever auth profile Release runs. The
AuthorizedClientServiceOAuth2AuthorizedClientManager is the servlet-context-free
variant made for background threads; its providers cache tokens per principal and re-authorize
inside a 60s pre-expiry clock-skew window. The one plugin bean this service looks up
(never requires) is the host's request-bound OAuth2AuthorizedClientManager, used only
to read the approver's current token on their own request thread.
Every method returns null instead of throwing when unconfigured or when the IdP is
unreachable, so callers degrade gracefully (approver identity → service identity → no token).
Service-token failures are negative-cached briefly so an unreachable IdP costs one request
per cooldown, not one per event.
-
Constructor Summary
ConstructorsConstructorDescriptionAgentRuleTokenService(com.xebialabs.xlrelease.config.XlrConfig config, org.springframework.beans.factory.ObjectProvider<org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager> hostManagerProvider) -
Method Summary
Modifier and TypeMethodDescriptioncurrentUserToken(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) The approver's current access token, read from the host's request-bound authorized-client manager (the OIDC auth plugin's bean; absent on other auth profiles).exchangeApproverToken(String subjectToken, String approverName) Exchanges an approver's access token (RFC 8693) so a delegated agent call carries the approver's identity.booleanTrue when the client-credentials service identity is configured.booleanTrue when the RFC 8693 approver on-behalf-of exchange is configured.The current service access token, minted or refreshed by the authorized-client manager as needed.
-
Constructor Details
-
AgentRuleTokenService
public AgentRuleTokenService(com.xebialabs.xlrelease.config.XlrConfig config, org.springframework.beans.factory.ObjectProvider<org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager> hostManagerProvider)
-
-
Method Details
-
isConfigured
public boolean isConfigured()True when the client-credentials service identity is configured. -
isExchangeConfigured
public boolean isExchangeConfigured()True when the RFC 8693 approver on-behalf-of exchange is configured. -
serviceToken
The current service access token, minted or refreshed by the authorized-client manager as needed. Returnsnullwhen the identity is not configured or the IdP cannot be reached — never throws, so a broken IdP degrades to token-less dispatch instead of killing it. Blocking (one bounded HTTP round trip on mint/refresh): call it from the agent-rules executor only, never from an event-bus handler thread. -
currentUserToken
public String currentUserToken(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) The approver's current access token, read from the host's request-bound authorized-client manager (the OIDC auth plugin's bean; absent on other auth profiles). Must be called on the approver's own HTTP request thread — this is the subject-token acquisition step of the on-behalf-of flow, and the session-bound token exists nowhere else. -
exchangeApproverToken
Exchanges an approver's access token (RFC 8693) so a delegated agent call carries the approver's identity. Cached per approver by the manager. Returnsnullwhen the exchange is not configured, the subject token is absent, or the IdP refuses — callers fall back to the service identity. Blocking (one bounded IdP round trip); called on the approver's own request thread so the subject token is exchanged while fresh.
-