ServiceTokenClaims identity.service-token-claims@1
Generated at from
openvibe-contracts v0.114.0 and
openvibe-sdk v0.35.1.
- Version
- 1.3.0
- Owner
- network
- Visibility
- public
- Status
- active
- Compatibility
- backward
- Decision
- ADR-003
- Schema
https://openvibe.network/contracts/identity/service-token-claims.v1.json
Claims of a short-lived RS256 client-credentials token issued by OpenVibe.Network to a service, app, mod, node or agent principal. Replaces X-Internal-Key. App tokens (actor_type app) also carry project_id and env; receivers refuse env=sandbox unless they opted in. Agent tokens (actor_type agent, sub agent:agt_<ULID>) are minted for the agent's host and also carry project_id, env and on_behalf_of (the owner), and optionally cap_confirm and act.
Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
iss | string | yes | Issuer; https://openvibe.network in production. Receivers pass the issuer they expect to verifyServiceToken(). |
|
sub | string | yes |
| |
actor_type | enum | yes |
| |
aud | array of string | yes |
| |
cap | array of string | yes | Granted capability ids; a trailing .* grants a family. |
|
cap_confirm | array of string | Agent tokens: capabilities the agent holds in confirm mode. Each use needs an approved network.confirmation-request@1, presented as OpenVibe-Confirmation: cnf_<ULID> and consumed by the owning service. Never also in cap, so a receiver that does not know agents refuses those actions. |
| |
ns | array of string | Namespace constraints, e.g. live.* or mod.example.*. A developer app token carries its project_id (the whole project, as issued before namespaces were rows) and app.<project_id>.*: on Media, app.<project_id> and app.<project_id>.sandbox are the project's production and sandbox namespaces, with children below them. | ||
iat | integer | yes | ||
exp | integer | yes | ||
jti | string | yes |
| |
project_id | string | Developer project of an app or agent principal (ADR-014). Services key tenancy by it. Absent on first-party service tokens. |
| |
env | enum | Environment of an app or agent principal. A receiver MUST refuse env=sandbox (401 token.sandbox_refused) unless it opted in to sandbox tokens. Absent on first-party service tokens, which are production. |
| |
on_behalf_of | string | The person who authorized an app through the authorization-code flow, or the owner an agent acts for (always present on agent tokens). Absent on client_credentials tokens. |
| |
act | object | Agent tokens: the host that runs the agent and the token was minted for (RFC 8693 actor claim), a service or an app. |
| |
act.sub | string | yes |
|
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: agent-app-host-auto-only
{
"iss": "https://openvibe.network",
"sub": "agent:agt_01J0000000000000000000000Z",
"actor_type": "agent",
"aud": [
"openvibe.media"
],
"cap": [
"media.object.read"
],
"ns": [
"prj_01J0000000000000000000000Z",
"app.prj_01J0000000000000000000000Z.*"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_agent002",
"project_id": "prj_01J0000000000000000000000Z",
"env": "sandbox",
"on_behalf_of": "usr_01J0000000000000000000000Z",
"act": {
"sub": "app:app_01J0000000000000000000000Z"
}
}Valid: agent-service-host
{
"iss": "https://openvibe.network",
"sub": "agent:agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"actor_type": "agent",
"aud": [
"openvibe.chat"
],
"cap": [
"chat.presence.read"
],
"cap_confirm": [
"chat.message.send"
],
"ns": [
"prj_01JAB2C3D4E5F6G7H8J9K0MNPQ"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_agent001",
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"on_behalf_of": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"act": {
"sub": "svc:actor"
}
}Valid: app-project-namespaces
{
"iss": "https://openvibe.network",
"sub": "app:app_01J0000000000000000000000Z",
"actor_type": "app",
"aud": [
"openvibe.media"
],
"cap": [
"media.object.upload",
"media.object.read",
"media.object.list",
"media.object.delete"
],
"ns": [
"prj_01J0000000000000000000000Z",
"app.prj_01J0000000000000000000000Z.*"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_abcdef13",
"project_id": "prj_01J0000000000000000000000Z",
"env": "production"
}Valid: app-sandbox
{
"iss": "https://openvibe.network",
"sub": "app:app_01J0000000000000000000000Z",
"actor_type": "app",
"aud": [
"openvibe.media"
],
"cap": [
"media.object.upload",
"media.object.read"
],
"ns": [
"live.*"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_abcdef12",
"project_id": "prj_01J0000000000000000000000Z",
"env": "sandbox",
"on_behalf_of": "usr_01J0000000000000000000000Z"
}Valid: live-to-media
{
"iss": "https://openvibe.network",
"sub": "svc:live",
"actor_type": "service",
"aud": [
"openvibe.media"
],
"cap": [
"media.object.upload",
"media.object.read"
],
"ns": [
"live.*"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_abcdef12"
}Valid: node-token
{
"iss": "https://openvibe.network",
"sub": "node:nod_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"actor_type": "node",
"aud": [
"openvibe.bot"
],
"cap": [
"network.node.self.manage"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_node0001"
}Rejected: agent-actor-with-service-sub
{
"iss": "https://openvibe.network",
"sub": "svc:actor",
"actor_type": "agent",
"aud": [
"openvibe.chat"
],
"cap": [
"chat.presence.read"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_agent005",
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"on_behalf_of": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}Rejected: agent-bad-actor-claim
{
"iss": "https://openvibe.network",
"sub": "agent:agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"actor_type": "agent",
"aud": [
"openvibe.chat"
],
"cap": [
"chat.presence.read"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_agent006",
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"on_behalf_of": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"act": {
"sub": "agent:agt_01J0000000000000000000000Z"
}
}Rejected: agent-sub-as-service
{
"iss": "https://openvibe.network",
"sub": "agent:agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"actor_type": "service",
"aud": [
"openvibe.chat"
],
"cap": [
"chat.message.send"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_agent004"
}Rejected: agent-without-owner
{
"iss": "https://openvibe.network",
"sub": "agent:agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"actor_type": "agent",
"aud": [
"openvibe.chat"
],
"cap": [],
"cap_confirm": [
"chat.message.send"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_agent003",
"project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"env": "production",
"act": {
"sub": "svc:actor"
}
}Rejected: app-without-project
{
"iss": "https://openvibe.network",
"sub": "app:app_01J0000000000000000000000Z",
"actor_type": "app",
"aud": [
"openvibe.media"
],
"cap": [
"media.object.upload",
"media.object.read"
],
"ns": [
"live.*"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_abcdef12",
"env": "sandbox",
"on_behalf_of": "usr_01J0000000000000000000000Z"
}Rejected: no-audience
{
"iss": "https://openvibe.network",
"sub": "svc:live",
"actor_type": "service",
"aud": [],
"cap": [],
"iat": 1,
"exp": 2,
"jti": "tok_abcdef12"
}Rejected: node-bad-id
{
"iss": "https://openvibe.network",
"sub": "node:nod_42",
"actor_type": "node",
"aud": [
"openvibe.bot"
],
"cap": [
"network.node.self.manage"
],
"iat": 1790000000,
"exp": 1790000300,
"jti": "tok_node0001"
}Rejected: non-uri-issuer
{
"iss": "openvibe network",
"sub": "svc:live",
"actor_type": "service",
"aud": [
"openvibe.media"
],
"cap": [],
"iat": 1,
"exp": 2,
"jti": "tok_abcdef12"
}Rejected: user-subject
{
"iss": "https://openvibe.network",
"sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"actor_type": "service",
"aud": [
"openvibe.media"
],
"cap": [],
"iat": 1,
"exp": 2,
"jti": "tok_abcdef12"
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('identity.service-token-claims@1', value); // { valid, errors: [{ path, message }] }