Skip to main content
applies to MistServer 3.9 and newer

JSON Web Token (JWT) Support - Docs

JWT Support

MistServer 3.9 comes with JSON Web Token (JWT) support. Other terms you might find are JSON Web Key (JWK) and JSON Web Signature (JWS). JWT support within MistServer implements a secure exchange between two parties using JSON data allowing for cleaner integration with Customer Relation Management (CRM) systems allowing a clean method of Access Control.

If you want to build something compatible we recommend going over the following RFCs:

Need an example on how to set up JWT in MistServer?

Need to knows

Jargon

  • JSON Web Token (JWT): The secure exchange method between MistServer and another endpoint to determine whether the other side is allowed to push and/or view a stream within MistServer. Specifically JWS are implemented and not JSON Web Encryption (JWE).
  • JSON Web Signature (JWS): This is the specific JWT to use when using the JWT support within MistServer as a contributor or taker.
  • JSON Web Key (JWK): This is the key that is used to sign/verify a JWT with. Using the algorithm defined in the JWA.
  • JSON Web Algorithm (JWA): The JWA defines the encryption algorithm for the JWT.
  • Contributor: Users which will be sending in stream data into a MistServer platform.
  • Taker: Users which will be receiving stream data from a MistServer instance.

JWA / JWK

A JWK within MistServer MUST contain the following values:

{"kty":"value","alg":"value"}

Any required parameters by setting kty or alg should be followed accordingly. The RFC 7518 - JSON Web Algorithm is referenced as it describes the practical information.

RECOMMENDED

  • kid RFC 7515 - 4.1.4 The kid while optional is recommended to add as it can be used to match against when editing/deleting a JWK from MistServer.

Adding JWK to MistServer

This can be done through the jwks, addjwks calls or through the add jwk feature within the general tab of the MistServer configuration. Deletion can be done through the deletejwks call or through the general tab of the MistServer configuration.

{"jwks":[[{"alg":"HS256","k":"KEY","key_ops":["sign","verify"],"kty":"oct"}, {"input": true, "output": true, "admin": true, "stream": ""}]]}

JWT

JWTs MUST contain the following value:

  • sub RFC 7519 - 4.1.2 the use of sub is REQUIRED with MistServer and must contain the streamname with an optional wildcard. Whether wildcards are accepted depends on how JWTs are passed to MistServer, we define the following supported methods:

    • JWS as streamname
      • MistServer requires sub to be a valid streamname OR streamname+wildcardname
    • JWS as parameter (e.g. tkn) or cookie value, additionally the following is supported:
      • Setting sub to * allows access to every stream unconditionally
      • Setting sub to a value containing one * symbol provides access to streams that match the pattern defined by sub. For example, setting example*stream provides access to all streams prefixed with example and suffixed with stream, such as example+mist+stream. The * symbol may also be the first or last symbol.
warning

Using 'sub' = '*' for a viewer will allow the viewer to watch any stream.

Any other registered claim names may be used optionally.

Using JWS

A JWS can be used both by contributors and by takers.

Contributors and JWT / JWS

When pushing a stream to a MistServer platform the JWS can be used instead of the stream name as a pushing token. This is compatible with RTMP, E-RTMP, SRT and WebRTC.

Keep the following in mind when using JWS and MistServer:

  • MistServer will detect, verify and use passed JWS against any JWK setup within MistServer
  • If the stream matching the JWS does not exist it will be created while in use
  • Any settings that would reject the push are side-stepped and ignored
  • If the JWS is found invalid the JWS itself will be used as stream name and will get rejected

The following syntax should be used:

RTMP & E-RTMP
rtmp://mistserveraddress:RTMPport/live/JWS
SRT
srt://mistserveraddress:SRTport?streamid=JWS
WebRTC
https://mistserveraddress:httpsport/webrtc/JWS

Takers and JWT / JWS

There are 3 methods to use a JWS while receiving streams from MistServer.

  • JWS as stream name
  • JWS as tkn URL parameter
  • JWS as tkn cookie value

For most HTTP based outputs passing the JWS as cookie or Url parameter would generally be preferred. However some outputs like SRT and RTMP would filter out such a method. In these cases the JWS can be used as stream name.

Keys API

There are three API calls: jwks, addjwks and deletejwks that all operate on the same array of keys and endpoints (URLs) stored in the Mist configuration. The endpoints we currently accept are the well-known and certificate endpoints from KeyCloak1. The jwks call overwrites whatever is in the configuration, and addjwks and deletejwks append and remove keys respectively. Keys and endpoints are either standalone, or have a set of permissions attached to them. Permissions can be set by passing a size two array containing the key as first element, and a permissions object2 as second element. This object takes booleans for input (viewing), output (creating stream), and admin rights. Additionally, the streams member can be used to set which streams the key(s) applies to, and should be set to a string or array of strings. For any missing permissions the defaults are assumed. Valid formats for keys3 and endpoints4 can be found in the footnotes. The underlying structure of the configuration is a JSON array, which contains any combination of the following:

  • JSON web key (JSON object); this must contain a "kty" member that is set to "oct", "RSA" or "EC" as the keytype.
  • URL (JSON string); this must be a valid URL, currently we support two Keycloak endpoints1, any other URLs are ignored in the back-end.
  • JSON keys array (JSON object with "keys" array); this array follows the same structure as the array it is in and contains any amount of keys, URLs, or further nested arrays.

Each call accepts this array structure. Note that keys and URLs may also be passed in a size two array, where the first element is the key and the second a permissions object. On top of that, there is support for handling the URL as JSON string and JSON web key as JSON object directly without the need to wrap them in a single-element array. The jwks call5 overwrites the current config, whereas the addjwks call67 appends to the config.

The deletejwks call8 supports additional formats. While not required, most JSON web keys will have a key ID in its 'kid' member. Typically, you would want to use the key ID ('kid') to remove keys instead of providing the full key. If no key ID is present the back-end will attempt to remove a key by matching whole JSON key objects passed in the API call to the keys it has stored. In addition to the JSON web key, URL, and keys array, the following value may be provided directly, or as an array element:

  • Key ID 'kid' (JSON string); this can be any non-URL string but is typically a UUID
  • Key ID object 'kid' (JSON string); an object containing the member "kid"; this is similar to JSON web keys but we do not require the "kty" member.

The jwks and addjwks accept nested structures as well9, deletejwks does not.

The response contains the keys that were succesfully written to (jwks and addjwks) or deleted (deletejwks) from the config. There is one exception to this, if jwks does not contain an array or valid URL, the API responds with the current contents of the configuration[^10] and takes no further action.

Footnotes

  1. For a localhost instance on HTTPS port 8443, that has the default realm called master configured, the endpoints are the well-known endpoint and certificate endpoint. 2

  2. Permissions object examples, please observe that none of the members are required.

    [
    {
    "admin": true,
    },
    {
    "input": true,
    "stream": "live"
    },
    {
    "input": false,
    "output": true,
    "stream": ["coding", "broadcast"]
    },
    ]
  3. Valid formats for various keys, of which the last has a permissions object.

    [
    {
    "kty": "RSA",
    "kid": "uuid-rsa",
    "use": "sig",
    "n": "base64n",
    "e": "AQAB"
    },
    [
    {
    "kty": "EC",
    "crv": "P-256",
    "x": "base64x",
    "y": "base64y",
    "d": "base64d",
    "alg": "ES256",
    "kid": "uuid-ec"
    }
    ],
    [
    {
    "kty": "oct",
    "k": "42",
    "kid": "uuid-oct"
    },
    {
    "admin": true,
    }
    ]
    ]
  4. Valid formats for endpoints, as string, string in array, and string in array with permissions.

    [
    "https://key-endpoint.com/jwks",
    ["https://jwk-api.eu/keys"],
    [
    "https://well-known.nl/certs",
    {
    "input": true,
    "output": true,
    "stream": "live"
    }
    ]
    ]
  5. Overwriting all keys in the configuration with a single endpoint, with and without permissions.

    {
    "jwks": "https://some-url.com/.well-known/openid-configuration"
    }
    {
    "jwks":
    [
    [
    "https://some-url.com/.well-known/openid-configuration",
    {
    "output": true,
    "stream": "streamname"
    }
    ]
    ]
    }
  6. Adding a JSON web key as object, with and without permissions.

    {
    "addjwks":
    {
    "kty": "oct",
    "k": "42",
    "kid": "uuid"
    }
    }
    {
    "addjwks":
    [
    {
    "kty": "oct",
    "k": "42",
    "kid": "uuid"
    },
    {
    "input": true,
    "stream": "live"
    }
    ]
    }
  7. Adding an endpoint and key wrapped in an array to the configuration, with and without permissions.

    {
    "addjwks":
    [
    "https://localhost:8443/realms/master/protocol/openid-connect/certs",
    {
    "kty": "RSA",
    "kid": "uuid-rsa",
    "use": "sig",
    "n": "base64n",
    "e": "AQAB"
    },
    ]
    }
    {
    "addjwks":
    [
    [
    "https://localhost:8443/realms/master/protocol/openid-connect/certs",
    {
    "admin": true
    }
    ]
    [
    {
    "kty": "RSA",
    "kid": "uuid-rsa",
    "use": "sig",
    "n": "base64n",
    "e": "AQAB"
    },
    {
    "admin": true
    }
    ]
    ]
    }
  8. Deleting keys from the configuration using key ID, object containing key ID, complete key object, and endpoint URL.

    {
    "jwks":
    [
    "uuid-generic",
    {
    "kty": "oct",
    "k": "42",
    "kid": "uuid-oct"
    },
    {
    "kid": "uuid-rsa"
    },
    "https://localhost:8443/realms/master/protocol/openid-connect/certs"
    ]
    }
  9. More complex calls of which some contain nested arrays, one for overwriting the configuration and one for adding keys to the configuration.

    {
    "jwks":
    [
    [
    {
    "keys": [
    {
    "kty": "oct",
    "kid": "key-with-perms-1",
    "k": "abc123"
    },
    {
    "kty": "oct",
    "kid": "key-with-perms-2",
    "k": "def456"
    }
    ]
    },
    {
    "admin": true,
    "stream": "secure"
    }
    ]
    ]
    }
    {
    "addjwks":
    [
    "https://example.com/jwks.json",
    {
    "keys":
    [
    {
    "kty": "oct",
    "k": "YWJjMTIz",
    "kid": "uuid-nested-1",
    "alg": "HS256"
    },
    [
    ["https://other.com/key"],
    {
    "admin": false,
    "output": false,
    "stream": "no"
    }
    ],
    {
    "kty": "oct",
    "k": "YWJjMTIzdfWdfMTsZ",
    "kid": "uuid-nested-2",
    "alg": "HS512"
    },
    {
    "keys":
    [
    "https://nested-url.site/"
    ]
    }
    ]
    },
    {
    "kty": "RSA",
    "n": "base64n",
    "e": "base64e",
    "kid": "uuid-rsa",
    "use": "sig"
    }
    ]
    }