RealtimeTicketClaims identity.realtime-ticket-claims@1

Generated at from openvibe-contracts v0.76.0 and openvibe-sdk v0.20.1.

Version
1.0.0
Owner
network
Visibility
first-party
Status
active
Compatibility
backward
Decision
ADR-005
Schema
https://openvibe.network/contracts/identity/realtime-ticket-claims.v1.json

Claims of a realtime ticket (ADR-005 amendment 2; roadmap WS-E task 3, WS-F task 1): a two-minute RS256 JWT that OpenVibe.Network signs for the signed-in person (POST /api/v1/realtime/ticket) so a browser on any OpenVibe site can open Events' /realtime/stream?ticket=... as that person. A browser cannot put a header on an EventSource, and the ov_token cookie of events.openvibe.network is third-party on every other site, so the ticket travels in the URL; that is why it is short-lived, single-purpose and single-use. It is never a session token, by three independent rules: its issuer is Network's issuer followed by /realtime (every service checks the issuer of a session token), it carries typ (services refuse a session token that has one, as for FedCM assertions), and its only audience is openvibe.events. Events accepts it only as ?ticket= on /realtime/stream, verifies the signature with Network's key, iss, aud, typ, purpose and expiry (lifetime at most 300 s), refuses a jti it has already seen while the ticket is valid, and never logs it. The connection then sees what the person's session would: public events and subject events addressed to `sub`.

Fields

FieldTypeRequiredDescriptionConstraints
issstringyesNetwork's issuer followed by /realtime (https://openvibe.network/realtime in production): not the issuer of a session.
  • pattern ^https?://[^/?#]+/realtime$
  • format uri
substringyesThe person's subject id; subject-visibility events for this subject reach the connection.
  • pattern ^usr_[0-9A-HJKMNP-TV-Z]{26}$
audarray of constyes
  • minItems 1
  • maxItems 1
  • items: = "openvibe.events"
typconstyesToken class. A service that finds typ on a Network token does not treat it as a session.
  • = "realtime"
purposeconstyesSingle purpose: opening one realtime stream.
  • = "realtime"
iatintegeryes
  • minimum 0
expintegeryesiat + 120 as Network mints it; Events refuses a lifetime over 300 s.
  • minimum 0
jtistringyesUnique per ticket; Events accepts each once.
  • pattern ^rtk_[0-9a-f]{24}$

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: badge-ticket
{
  "iss": "https://openvibe.network/realtime",
  "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "aud": [
    "openvibe.events"
  ],
  "typ": "realtime",
  "purpose": "realtime",
  "iat": 1790000000,
  "exp": 1790000120,
  "jti": "rtk_0123456789abcdef01234567"
}
Rejected: no-typ
{
  "iss": "https://openvibe.network/realtime",
  "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "aud": [
    "openvibe.events"
  ],
  "purpose": "realtime",
  "iat": 1790000000,
  "exp": 1790000120,
  "jti": "rtk_0123456789abcdef01234567"
}
Rejected: numeric-user-id
{
  "iss": "https://openvibe.network/realtime",
  "sub": "57",
  "aud": [
    "openvibe.events"
  ],
  "typ": "realtime",
  "purpose": "realtime",
  "iat": 1790000000,
  "exp": 1790000120,
  "jti": "rtk_0123456789abcdef01234567"
}
Rejected: other-audience
{
  "iss": "https://openvibe.network/realtime",
  "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "aud": [
    "openvibe.events",
    "openvibe.live"
  ],
  "typ": "realtime",
  "purpose": "realtime",
  "iat": 1790000000,
  "exp": 1790000120,
  "jti": "rtk_0123456789abcdef01234567"
}
Rejected: other-purpose
{
  "iss": "https://openvibe.network/realtime",
  "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "aud": [
    "openvibe.events"
  ],
  "typ": "realtime",
  "purpose": "session",
  "iat": 1790000000,
  "exp": 1790000120,
  "jti": "rtk_0123456789abcdef01234567"
}
Rejected: session-claims
{
  "iss": "https://openvibe.network/realtime",
  "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "aud": [
    "openvibe.events"
  ],
  "typ": "realtime",
  "purpose": "realtime",
  "iat": 1790000000,
  "exp": 1790000120,
  "jti": "rtk_0123456789abcdef01234567",
  "username": "alice",
  "role": "admin"
}
Rejected: session-issuer
{
  "iss": "https://openvibe.network",
  "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "aud": [
    "openvibe.events"
  ],
  "typ": "realtime",
  "purpose": "realtime",
  "iat": 1790000000,
  "exp": 1790000120,
  "jti": "rtk_0123456789abcdef01234567"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('identity.realtime-ticket-claims@1', value);   // { valid, errors: [{ path, message }] }