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
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
iss | string | yes | Network's issuer followed by /realtime (https://openvibe.network/realtime in production): not the issuer of a session. |
|
sub | string | yes | The person's subject id; subject-visibility events for this subject reach the connection. |
|
aud | array of const | yes |
| |
typ | const | yes | Token class. A service that finds typ on a Network token does not treat it as a session. |
|
purpose | const | yes | Single purpose: opening one realtime stream. |
|
iat | integer | yes |
| |
exp | integer | yes | iat + 120 as Network mints it; Events refuses a lifetime over 300 s. |
|
jti | string | yes | Unique per ticket; Events accepts each once. |
|
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 }] }