Skip to content

OAuth Package

The OAuth packages call the STS /oauth/2/token endpoint for RFC 8693 exchanges. The returned mandate class depends on the authenticated flow: lifecycle bootstrap returns use=session, a bound direct mint returns use=gateway, and Gateway’s authenticated exchange returns use=resource privately to Gateway.

Use this package only when composing a custom authority client. Normal applications should use the language SDK facade, which supplies the correct Authority-record, Session, and Delegation identifiers.

EcosystemPackage
TypeScriptnpm install @caracalai/oauth
Pythonpip install caracalai-oauth
Gogo get github.com/garudex-labs/caracal/packages/oauth/go
OptionMeaning
Subject tokenExisting session mandate, or a Federated user’s identity token from a registered issuer; omit to exchange as the application Subject.
ResourceOne or more resource identifiers. Clients trim, exact-deduplicate, and sort the set.
Client secretApplication authentication. Public client assertions are not supported.
Authority record IDSent in the STS form field session_id. It is distinct from a governed Session ID.
Session IDSent in the STS form field agent_session_id.
Delegation IDSent in the STS form field delegation_edge_id.
ScopesRequested resource scopes.
TTL secondsRequested mandate lifetime.
import { OAuthClient, ApprovalRequiredError } from '@caracalai/oauth'
const oauth = new OAuthClient(stsUrl, zoneId, applicationId)
try {
const token = await oauth.exchange(subjectToken, 'resource://pipernet', {
scopes: ['pipernet:read'],
clientSecret: process.env.CARACAL_APP_CLIENT_SECRET,
})
console.log(token.accessToken, token.expiresIn)
} catch (error) {
if (error instanceof ApprovalRequiredError) {
console.log('approval required', error.approvalId)
} else {
throw error
}
}
  • Successful responses are validated for access_token, token_type, and expires_in.
  • Public responses expose the granted target_resources subset; private Gateway upstream directives are not part of the SDK response type.
  • Cache-enabled responses are isolated by identity, canonical resources, scopes, TTL, and credential context. One-shot, approval-bearing, and cache-disabled exchanges bypass both cache and single-flight sharing.
  • Issuance uses one network attempt. A lost response may hide a successfully minted token, so the clients never retry STS exchange automatically.
  • STS interaction_required responses surface as ApprovalRequiredError.
  • Default exchange timeout is 30 seconds. invalidate() / invalidate clears the client cache; it does not revoke already issued mandates or cancel exchanges already in flight.
  • Never retry an exchange merely because the response was lost. If the surrounding business operation is replayable, mint a fresh mandate for that new attempt.

Every exchange acts for a Subject: the application itself by default, or a Federated user. When the zone registers the application’s identity system as a Federated user issuer, the client exchanges an end user’s identity token for a Caracal Authority record and can post that user’s decision on an approval hold reserved for them:

  • federateSubject(idToken, opts) / federate_subject(id_token, ...) / FederateSubject(ctx, idToken, opts) - creates the Federated user’s Authority record and returns its session mandate response. Never cached: each federation is an explicit identity event, and the record carries no resource authority. The high-level SDK wrappers also return the Authority record ID as subjectAuthorityRecordId, subject_authority_record_id, or SubjectAuthorityRecordID.
  • decideApproval({...}) / decide_approval(...) / DecideApproval(ctx, input) - posts the Federated user’s decision with their session mandate, echoing the hold’s exact binding.

See Human Approval for the end-to-end flow.