Signaling authentication
Signaling endpoints require a signed OAuth access token when auth.enabled is true. Browser sessions and ordinary management tokens cannot authorize signaling. Management endpoints retain their existing permission checks. Setting auth.enabled: false is for local experiments and disables signaling authentication too.
Each token carries an audience identifying the receiving plane, the dplane-signaling scope, a fixed tenant slug, and a client_id identifying the sending plane. The receiver validates the signature and issuer using its configured OpenID metadata, and requires exp, iat, jti and sub. Control plane requests require execute:dp.transfer; callbacks require execute:cp.transfer. A plane cannot use callback permission to drive another data plane.
Configure identities
The control plane's receiving identity is auth.signalingId, or auth.clientId when omitted. On each data plane configure:
controlPlane:
controlplaneId: provider-control-plane
dataplaneId: provider-http-plane
tenantSlug: provider
controlEndpoint: https://provider.example/control-plane/api/tenants/provider
dataplaneId is the stable public registration identity, distinct from the control plane's internal registration database id. Set it before first registration and match it to the data plane's SSO signaling identity. With authentication enabled, PUT /dataplanes and DELETE /dataplanes/:id only accept the caller's own identity (azp, client_id or sub of its management token), so a plane cannot replace another plane's registration. If omitted, registration retains the stored generated identity, which must still match the configured SSO identity. The control plane checks callback ownership against the registration identity of the flow's selected plane. The tenant claim must equal the addressed tenant slug; a token for one tenant cannot be reused with another tenant under the same issuer.
The SSO bridge configures these identities through signalingClients. Each entry binds an authenticated OAuth clientId to tenant, role, and allowed audiences. identity defaults to the OAuth client id and becomes JWT client_id. subject defaults to the identity and becomes JWT sub. These are deployment configuration, never values copied from a token request. The configured role must match the client's existing transfer permission.
signalingClients:
- clientId: cp-provider-credential
identity: provider-control-plane
tenant: provider
role: controlplane
audiences: [provider-http-plane]
- clientId: dp-provider-credential
identity: provider-http-plane
tenant: provider
role: dataplane
audiences: [provider-control-plane]
Use one credential per tenant relationship. Full SSO bridge tenancy is not required. For Siglet, configure the control plane entry's subject to the participant context id in its signaling path, and set the audience to Siglet's data plane identity. Configure Siglet with the SSO bridge issuer and JWKS from /api/oauth/jwks. This fixed subject mapping does not let the token caller choose another context.
Token requests and registration credentials
Send grant_type=client_credentials, audience=<receiving-plane-id> and scope=dplane-signaling to the SSO bridge token endpoint. The control plane obtains and caches a token per tenant, receiving plane and credential. Data planes obtain audience-bound callback tokens automatically. Token acquisition failures stop signaling rather than falling back to a management token.
A registration can contain a private authorization object with tokenEndpoint, clientId and clientSecret for a data plane that uses a separate OAuth client. Optional jwks or jwksUri configuration remains private too. When the object is omitted, the control plane uses its configured OAuth client. Registration, management creation, update and list responses omit the entire object. Internal signaling reads the stored credentials. Configure receiver trust through its OpenID settings; registering a JWKS does not change global issuer trust.
GET /api/tenants/:slug/transfers/:id/agreement returns the DSP Agreement only to an authenticated data plane with a flow belonging to that transfer in that tenant. All callback endpoints apply the same ownership check before changing transfer state.
Siglet 0.1.4 advertises an incorrect access-token expiry and omits fresh credentials on resume. Authenticated signaling does not establish compatibility with credential renewal or resume.