Networked Media Open Specifications

Node to Authorization Server Interactions

←Implementing Authenticated API Calls · Index↑ · Node to Registry Interactions (IS-04)→

Overview

This section details the interactions between an NMOS Node and the Authorization Server. These include:

Node to Authorization Server Interactions

The sequence diagram above gives an overview of these interactions which are described in more detail below.

Authorization Server Discovery

In order to interact with the Authorization Server, you need to know where it is. IS-10 specifies that the Authorization Server advertise itself using unicast DNS-SD to advertise itself to the Node.

Once the Node knows the whereabouts of the Authorization Server it can then fetch the Authorization Server Metadata to obtain supported features and endpoints.

Example request to get server metadata:

GET /.well-known/oauth-authorization-server HTTP/1.1
Host: authorization-server.example.com

Example server metadata HTTP response:

HTTP/1.1 200 OK
Content-Type: application/json
{
  "authorization_endpoint": "https://authorization-server.example.com/authorize",
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ],
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "refresh_token",
    "password",
    "client_credentials"
  ],
  "issuer": "https://authorization-server.example.com",
  "jwks_uri": "https://authorization-server.example.com/jwks",
  "registration_endpoint": "https://authorization-server.example.com/register",
  "request_object_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512",
    "none"
  ],
  "response_types_supported": [
    "code",
    "none",
    "token",
    "code token"
  ],
  "scopes_supported": [
    "channelmapping",
    "connection",
    "events",
    "node",
    "query",
    "registration"
  ],
  "token_endpoint": "https://authorization-server.example.com/token",
  "token_endpoint_auth_methods_supported": [
    "private_key_jwt",
    "client_secret_basic",
    "client_secret_post",
    "tls_client_auth",
    "client_secret_jwt"
  ],
  "token_endpoint_auth_signing_alg_values_supported": [
    "PS384",
    "ES384",
    "RS384",
    "HS256",
    "HS512",
    "ES256",
    "RS256",
    "HS384",
    "ES512",
    "PS256",
    "PS512",
    "RS512"
  ]
}

Client Registration

NMOS Nodes first need to register with the Authorization Server. This is usually a one-time operation that a Node would typically perform when first activated on the network.

The registration is done via a dynamic client registration with the Authorization Server. The registration includes the expected grant type, which is set to client credentials grant.

Depending on how the Authorization Server has been configured, it is likely that the Client Registration will need to be authenticated using an Initial Access Token. This token will be generated by the Authorization Server, and provided to the NMOS Node by some proprietary method.

Example client registration request including an Initial Access Token (this follows the Authorization: Bearer in the HTTP header):

POST /register HTTP/1.1
Host: authorization-server.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCIg...
{
  "client_name": "My Example Node",
  "grant_types": [
    "client_credentials"
  ],
  "jwks_uri": "https://node.example.com/jwks",
  "response_types": [
    "none"
  ],
  "scope": "registration",
  "token_endpoint_auth_method": "private_key_jwt"
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/json
{
  "client_id": "30baf617-1744-4c24-9baf-22351bec1a73",
  "client_name": "My Example Node",
  "client_id_issued_at": 1611940142,
  "grant_types": [
    "client_credentials"
  ],
  "jwks_uri": "https://node.example.com/jwks",
  "response_types": [
  ],
  "token_endpoint_auth_method": "private_key_jwt"
}

Client Credentials Flow

The Node can now request a bearer token from the Authorization Server using the client credentials flow. This access token will allow the Node to authenticate API calls on other NMOS Nodes, for instance, the NMOS Registry.

Example request to get bearer token:

POST /token HTTP/1.1
Host: authorization-server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVC...
&client_id=30baf617-1744-4c24-9baf-22351bec1a73
&scope=registration

In this request the client_assertion is a self-signed JWT and client_id is the result from client registration.

Details of the content of the client_assertion JWT can be found in section 3 of RFC7523. Note also, as mentioned in the Authorization Server Setup page, that the Keycloak authentication server used as an example here is an OpenID Connect server, which places some additional restrictions on the JWT. In particular, the iss claim should also be the client_id, and the jti claim becomes mandatory. See the OpenID Connect documentation on Client Authentication for details and examples.

Example token response:

HTTP/1.1 200 OK
Content-Type: application/json
{
  "access_token": "eyJhbGciOiJSUzUxMiIsInR5cCIgOiAiSl...",
  "expires_in": 180,
  "scope": "registration",
  "token_type": "bearer"
}

Refreshing Bearer Tokens

The Bearer Token has a limited life specified by the value of the expires_in parameter in seconds. The Node needs to refresh the token before it exceeds its half life (if the token lifetime is 30 seconds, then refresh it at least 15 seconds before token expiry).

Unlike the Authorization Code Flow, the Client Credential Flow does not issue a refresh token; ‘refreshing’ the token simply involves repeating the Client Credential Flow.

Fetching Authorization Server Public Keys

As well as acquiring a token to allow this Node to register, the Node also needs the Authorization Server’s public keys so that it can authenticate calls on its own APIs. These keys need to be fetched every hour to ensure the keys are always up to date.

Example request to get server public keys:

GET /jwks HTTP/1.1
Host: authorization-server.example.com

Example server public keys response:

HTTP/1.1 200 OK
Content-Type: application/json
[
  {
    "alg": "RS512",
    "e": "AQAB",
    "kid": "O4QEicS70s1DWFyt84niI80Z2SLsdNrVyeGwJe8g8qw",
    "kty": "RSA",
    "n": "yeSbbHw18xN3hh_VeHpSI01Fcp0xaI1znmWBVkm...",
    "use": "sig",
    "x5c": [
      "MIIFlTCCA32gAwIBAgICEAAwDQYJKoZIhvcNAQ..."
    ],
    "x5t": "LD3awp-sYoVbcfwOgB9BRO4HFYQ",
    "x5t#S256": "yCrclAKahB6SE68rbx5cRwuBZoeTXfW9smoLgt6u9t4"
  }
]

Note that since there can be multiple Authorization Servers, there are some extra things to consider about management of their corresponding public keys.

←Implementing Authenticated API Calls · Index↑ · Node to Registry Interactions (IS-04)→