Controller to Authorization Server Interactions
←Node to Registry Interactions (IS-04) · Index↑ · Controller to Registry (IS-04) and Node Interactions (IS-05, IS-08)→
Overview
This section details the interactions between an NMOS Controller and the Authorization Server. These include:
- Authorization Server Discovery
- Client Registration: Registration of the NMOS Controller with the Authorization Server.
- Authentication Code Flow: Request of an Access Token from the Authorization Server.
- Refreshing Bearer Tokens: Ensuring the token is always valid.
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 Controller.
Once the Controller 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
The NMOS Controller first needs to register with the Authorization Server. This is usually a one-time operation that a Controller 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 authorization code 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 Controller by some proprietary method.
When registering an NMOS Controller with more than one Authorization Server, the registration of unique redirect_uris
for each Authorization Server can help in avoiding Authorization Server Mix-Up attacks on your controller, whether it be a native application (RFC 8252, Section 8.10) or browser-based application (OAuth 2.0 for Browser-Based Apps, Section 9.5).
Example public client registration request including an Initial Access Token (this follows the Authorization: Bearer
in the HTTP header):
NOTE: The parameters passed as part of the dynamic client registration of NMOS Controllers are different to those passed when registering an NMOS Node.
POST /register HTTP/1.1
Host: authorization-server.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCIg...
{
"client_name": "My Example Controller",
"grant_types": [
"authorization_code",
"refresh_token"
],
"redirect_uris": [
"https://controller.example.com/auth/callback"
],
"response_types": [
"code"
],
"scope": "channelmapping connection events node query",
"token_endpoint_auth_method": "none"
}
Example response:
HTTP/1.1 201 Created
Content-Type: application/json
{
"client_id": "40baf617-1744-4c24-9baf-22351bec1a73",
"client_name": "My Example Controller",
"client_id_issued_at": 1611940142,
"grant_types": [
"authorization_code",
"refresh_token"
],
"redirect_uris": [
"https://controller.example.com/auth/callback"
],
"response_types": [
"code"
],
"token_endpoint_auth_method": "none"
}
Authorization Code Flow
NMOS Controllers can be implemented as either OAuth 2.0 public clients or confidential clients.
The IS-10 specification recommends making use of a Proof Key for Code Exchange (PKCE) (defined in OAuth 2.0 RFC 7636) as part of the Authorization Code Flow.
- To start the Authorization Code Flow, in place of a Client Secret, the Controller generates a cryptographically-random
code_verifier
which is used to generate acode_challenge
value. - The client redirects the Controller to the Authorization Server
/authorize
endpoint, passing thecode_challenge
as a parameter.
Example request to start authorization code flow:
GET /authorize
?client_id=30baf617-1744-4c24-9baf-22351bec1a73
&redirect_uri=https%3A%2F%2controller.example.com/auth/callback
&response_type=code
&code_challenge=HbYjeCHvDfKpyYacEHKLdffF0geuyu3A-b4ir7ZG8-E
&code_challenge_method=S256
&state=ricgtUUXODcOzifiJDnOw25rZ8wTZCxU
&scope=channelmapping%20connection%20events%20node%20query
HTTP/1.1
Host: authorization-server.example.com
- The Authorization Server will redirect the client to the login and authorization prompt.
- The Controller operator can then login and give consent on the Authorization Server for the Controller.
- The Authorization Server then redirects back to the Controller via the registered redirect URI, passing the authorization code as a parameter.
Example of authorization code ‘returned’ via the redirect URI (in this example, passed in the code
parameter):
HTTP/1.1 302 Found
Location: https://controller.example.com/auth/callback
?state=ricgtUUXODcOzifiJDnOw25rZ8wTZCxU
&code=2b7488e0-0682-42bb-893c-9d09e60bf8...
- The Controller can now exchange the authorization code for the bearer
token, by sending the authorization code and the
code_verifier
to the Authorization Server.
Example request to exchange authorization code for bearer token (in this request, the code
is the authorization code):
POST /token HTTP/1.1
Host: authorization-server.example.com
Content-Type: application/x-www-form-urlencoded
client_id=30baf617-1744-4c24-9baf-22351bec1a73
&redirect_uri=https://controller.example.com/auth/callback
&code=2b7488e0-0682-42bb-893c-9d09e60bf8...
&grant_type=authorization_code
&code_verifier=ricgtUUXODcOzifiJDnOw25rZ8wTZCxUxf...
&scope=channelmapping connection events node query
Example token response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "eyJhbGciOiJSUzUxMiIsInR5cCIgOiAiSl...",
"expires_in": 180,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia...",
"scope": "channelmapping connection events node query",
"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 Controller needs to refresh the token before it exceeds its half life (for example if the token lifetime is 30 seconds, then refresh it at least 15 seconds before token expiry).
Because refresh tokens can have a long lifetime, it is important that they are stored securely to prevent them from being leaked.
Example request to refresh bearer token:
POST /token HTTP/1.1
Host: authorization-server.example.com
Content-Type: application/x-www-form-urlencoded
client_id=30baf617-1744-4c24-9baf-22351bec1a73
&grant_type=refresh_token
&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia...
In this request the refresh_token
was previously obtained from the bearer token.
Example token response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "eyJhbGciOiJSUzUxMiIsInR5cCIgOiAiSl...",
"expires_in": 180,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia...",
"scope": "channelmapping connection events node query",
"token_type": "bearer"
}
Note that when a Controller is unable to contact an Authorization Server, it needs to try to contact another Authorization Server from the discovered list until this either succeeds or the list is exhausted.
←Node to Registry Interactions (IS-04) · Index↑ · Controller to Registry (IS-04) and Node Interactions (IS-05, IS-08)→