Round-Trip Authentication Validator
ABOUT
The Red5 Pro RoundTrip Authentication validator implemented by the class RoundTripAuthValidator
, is a remote server authorization mediator. As the name suggests, it implements a secure and robust authentication mechanism using the server to server validation.
A Red5 pro webapp seeks validation for publish
and subscribe
actions requested on a stream from a remote service through the RoundTripAuthValidator
implementation. The authentication is carried out on the remote server using the appropriate business logic implemented and the result is returned as a JSON
object back to the RoundTripAuthValidator
implementation.
One of the main feature of this validator implementation is being able to authenticate clients distinctively by their role
(publishers
and subscribers
). Authentication does not occur when a client merely connects to the server. It is triggered when the client clarifies its intent through an actual publish
or subscribe
request for a stream. The validator uses Red5 pro’s security hooks to determine the requested stream action type (publish
or subscribe
).
MECHANISM
![RoundTripAuthValidatorFlow](/_images/installation/server/red5proroundtripauthvalidator/red5proroundtripauthvalidator.png?)
As the application starts up, the validator is initialized with the configuration parameters and validation/invalidation endpoint hooks.
The client needs to directly login into the business application server to receive a unique secure token
. The token can be seen as a mark of identity (as a session) which indicates that the client is authentic
and can access services.
When a client attempts to connect to the application, it must provide the username, password, and optional token
parameters during the connection attempt. The simple auth checks to see if the parameters have been provided or not. If one or more parameters are missing the client is immediately rejected.
If credentials are provided, the validator allows connection to the client and waits for a stream action. When the client attempts to publish or subscribe to a stream, the validator determines the intent (publish or subscribe
) and the stream name for which the action is requested. The validator sends the credentials, the stream name, the client type (publisher/subscriber
) and the optional token parameter.
The remote server (typically a business application server), validates the credentials along with validating whether the client type has permission for the intended stream action or not. the server then returns its answer back to the validator, which then determines whether to allow or deny the stream action request based on the response data from the remote server.
The token
parameter is added for additional security alongside the username
and password
. The passing of the parameter can be made mandatory using the validator configuration boolean
param clientTokenRequired
.
PREREQUISITES FOR SETTING UP AUTHENTICATION
The round trip authentication consists of three components mainly:
- the
simple-auth-plugin
jar, - the
validator instantiation
in the webapp’sred5-web.xml
file, and - the
remote authentication
service.
You need to have the authentication service running for the system to work. A sample of the authentication server implementation, . Once the server is available you can configure necessary endpoint parameters as explained in the next section.
Make sure to double-check your server endpoints for errors and expected responses before you configure it on your instance.
PREPARING THE MOCK NODE.JS REMOTE AUTHENTICATION SERVER
As mentioned earlier, you can set up your validation server in any technology as long as you keep the endpoints
and response JSON
format the same. You can use the provided code as a starting point for your own auth server as a Node.js
service.
The steps below explain the various components of the Node.js mock server and how to set it up to work with the RoundTripAuthenticator
.
This Node.js service simulates the business application server’s API. It has some exposed endpoints to validate and invalidate the username and password supplied. The mock service does not do any actual validation on the inputs that it receives, just that it is receiving something. This means, for example, that username/passwords validity are not checked.
Prerequisites
Copy and unzip the zipped file nodejs-mock-service.zip
onto the server where you want to run the mock service. You will need to install Node.js on the server:
sudo apt-get install nodejs-legacy
Configuration
In the nodejs-mock-service directory, edit the index.js
file. In the top rows of the file, locate the comment BEGINNING OF CONFIGURATION
. After that, there will be two variables which need to be updated with your custom values:
host
: The host where the Node.js service is deployed. Replace “localhost” with the private IP address of the Node.js server.port
: The port that you opened for the service. Default example:3000
(make sure this port is opened on your inbound firewall rules).
There is also an optional value, optionalURLResource
, which can be used to pass in a URL to a connecting client.
How to run
Start the server with the command:
node index.js
If you open in a browser http://<host>:<port>
you will get a few forms to test the API. The server’s console will output the values received. The browser will show you the responses from the node server.
What to expect
The console will show you three possible outputs:
- Validate credentials: called by the webapp to verify the username/password supplied by a publisher or subscriber
validate credentials called
type: publisher
username: testuser
password: testpass
streamID: stream1
- Invalidate credentials: called by the webapp after a publisher stops publishing. It will invalidate the credentials that the publisher used to publish.
invalidate credentials called
username: testuser
streamID: stream1
API CALLS AND RESPONSES FOR REMOTE AUTHENTICATION SERVER
The following API calls should be able to be run agains your remote authentication server, as their logic is used by the Round Trip Authentication Validator process.
Validate Credentials
Description
Invoked by the RoundTripValidator
to validate
a client of a given type (publisher/subscriber
) for a specified stream name.
REQUEST
- ENDPOINT:
validateCredentials
- METHOD:
POST
- DATA:
{
"username": "<username>",
"password": "<password>",
"token": "<token>",
"type": "<type>",
"streamID": "<stream-id>"
}
RESPONSE
- Success: HTTP CODE
200
- Data:
{
"result": "<boolean>",
"url": "<optional-arbitrary-url>"
}
result
contains a boolean value indicating whether client action is permitted or deniedurl
can be used to pass back an arbitrary URL to the authenticated client. The value fo theurl
attribute is stored on theIConnection
object by property namesignedURL
. The parameter can be accessed by the server-side code using the getStringAttribute method on theIConnection
object.
IConnection conn = Red5.getConnectionLocal();
String url = conn.getStringAttribute("signedURL");
Invalidate Credentials
Description
Invoked by the RoundTripValidator
to invalidate
a client of a given type (publisher/subscriber
) for a specified stream name. Invalidate can be used to revoke a user permission
or expire a token
.
REQUEST
- ENDPOINT:
invalidateCredentials
- METHOD:
POST
- DATA:
{
"username": "<username>",
"password": "<password>",
"token": "<token>",
"type": "<type>",
"streamID": "<stream-id>"
}
RESPONSE
- Success: HTTP CODE
200
- Data:
{
"result": "<boolean>"
}
result
contains a boolean value indicating whether client action is permitted or denied
ENABLING SECURITY ON YOUR WEBAPP
To enable security on your web application, you need to add and configure the Simple Auth Plugin
security bean along with the validator
bean to your web application’s context file, red5-web.xml
, as explained below.
APPLICATION LEVEL CONFIGURATION
To attach simple auth plugin to a webapp using the RoundTripAuthValidator
validator, you need to specify the core plugin configuration bean along with the validator bean to use for authentication, in the application’s context, red5-web.xml
, file.
Example 1: Attaching plugin security to the live
webapp using RoundTripAuthValidator
for authentication with standard configuration settings.
STEP 1
To apply security to the live
application, add the security configuration to {red5pro}/webapps/live/WEB-INF/red5-web.xml
as shown below. Note that in the following example the value <property name="clientTokenRequired" value="false"/>
Set this to true
if you want to enforce sending a token with your request:
<bean id="roundTripValidator" class="com.red5pro.server.plugin.simpleauth.datasource.impl.roundtrip.RoundTripAuthValidator" init-method="initialize">
<property name="adapter" ref="web.handler" />
<property name="context" ref="web.context" />
<property name="protocol" value="${server.protocol}" />
<property name="host" value="${server.host}" />
<property name="port" value="${server.port}" />
<property name="validateCredentialsEndPoint" value="${server.validateCredentialsEndPoint}"/>
<property name="invalidateCredentialsEndPoint" value="${server.invalidateCredentialsEndPoint}"/>
<property name="clientTokenRequired" value="false"/>
</bean>
<bean id="simpleAuthSecurity" class="com.red5pro.server.plugin.simpleauth.Configuration" >
<property name="active" value="true" />
<property name="rtmp" value="true" />
<property name="rtsp" value="true" />
<property name="rtc" value="true" />
<property name="rtmpAllowQueryParamsEnabled" value="true" />
<property name="allowedRtmpAgents" value="*" />
<property name="validator" ref="roundTripValidator" />
</bean>
STEP 2
In the {red5pro}/webapps/live/WEB-INF/red5-web.properties
file, add the following section:
server.validateCredentialsEndPoint=/validateCredentials
server.invalidateCredentialsEndPoint=/invalidateCredentials
server.host=<serverIP>
server.port=3000
server.protocol=http://
The property values are substituted from the red5-web.properties
file into the red5-web.xml
file at runtime. If you are running the mock auth service on the same instance as your Red5 Pro Server, the server.host
value should be the private IP address of your instance (same as in the Node.js index.js file).
With the following configuration applied, the server will be expecting client validation requests at http://<serverIP>:3000/validateCredentials
and invalidate requests at http://<serverIP>:3000/invalidateCredentials
. The plugin configuration is set to force authentication on RTMP
, RTSP
and WebRTC
connections.
APPLICATION LEVEL CONFIGURATION BEAN PROPERTIES
The following parameters are allowed in a bean configuration at the application level (configured in application’s red5-web.xml
):
CORE
Property | Type | Description |
---|---|---|
active | Boolean | Sets the state of security for the application |
rtmp | Boolean | Sets the state of RTMP security for the application |
rtsp | Boolean | Sets the state of RTSP security for the application |
rtc | Boolean | Sets the state of WebRTC security for the application |
rtmpAllowQueryParamsEnabled | Boolean | Sets the state of query string based authentication for RTMP clients |
allowedRtmpAgents | String | Sets the list of allowed RTMP agent strings separated by semicolons. By default, all agent string is allowed. |
VALIDATOR
Property | Type | Description |
---|---|---|
context | Reference | The reference to the web.context bean |
adapter | Reference | The reference to thr web.handler bean, which indicates the Application |
protocol | String | The remote validation server protocol (HTTP or HTTPS ) to use |
host | String | The remote validation server host (hostname or IP ) |
port | String | The remote validation server port (80 or 443 or other ) |
validateCredentialsEndPoint | String | The remote server-client validation endpoint URI relative to the server root |
invalidateCredentialsEndPoint | String | The remote server-client invalidation endpoint URI relative to the server root |
clientTokenRequired | Boolean | Specifies whether token parameter is a required or optional param in client request |
CLIENT AUTHENTICATION
RTMP, RTSP and WebRTC clients must provide the required connection parameters when attempting to establish a connection with the server. The plugin will extract expected parameters and validate their presence locally first, before transmitting them to the remote server.
Given below are some snippets, explaining how authentication can be achieved for different client types.
Authenticating RTMP Clients
RTMP clients must pass authentication parameters (username and password) using the connection arguments in [NetConnection.connect](http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetConnection.html#connect())
Example A
var nc:NetConnection = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
nc.connect("rtmp://localhost/myapp", "testuser", "testpass", "mytoken");
function onStatus(ns:NetStatusEvent):void
{
trace(ns.info.code);
}
Username and password should be the first two parameters in the arguments array being sent to Red5 Pro.
With the simpleauth.default.rtmp.queryparams=true
in the plugin configuration file or using the rtmpAllowQueryParamsEnabled
property of configuration bean set to true
, RTMP clients can also pass parameters in the query string.
Example B
var nc:NetConnection = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
nc.connect("rtmp://localhost/myapp?username=testuser&password=testpass&token=mytoken");
function onStatus(ns:NetStatusEvent):void
{
trace(ns.info.code);
}
Authenticating RTSP Clients
RTSP clients (Android and IOS) must pass authentication parameters (username and password) using the R5Configuration
object in the Red5 Pro Mobile SDK.
Android Example
R5Configuration config = new R5Configuration(R5StreamProtocol.RTSP,
TestContent.GetPropertyString("host"),
TestContent.GetPropertyInt("port"),
TestContent.GetPropertyString("context"),
TestContent.GetPropertyFloat("buffer_time"));
config.setParameters("username=testuser;password=testpass;token=mytoken;");
R5Connection connection = new R5Connection(config);
IOS Example
Swift
func getConfig()->R5Configuration{
// Set up the configuration
let config = R5Configuration()
config.host = Testbed.getParameter("host") as! String
config.port = Int32(Testbed.getParameter("port") as! Int)
config.contextName = Testbed.getParameter("context") as! String
config.parameters = @"username=testuser;password=testpass;token=mytoken";
config.`protocol` = 1;
config.buffer_time = Testbed.getParameter("buffer_time") as! Float
return config
}
Authenticating WebRTC Clients
WebRTC clients (Using Red5 Pro HTML5 SDK) must pass authentication parameters using the connectionParams
property of the baseConfiguration
object.
Example:
var baseConfiguration = {
host: window.targetHost,
app: 'myapp',
iceServers: iceServers,
bandwidth: desiredBandwidth,
connectionParams: {username: "testuser", password: "testpass", token: "mytoken"}
};
TESTING
You can use the HTML5 Publish – Round Trip Authentication and Subscribe – Round Trip Authentication tests to validate round-trip security.
USE CASES
While there are some best-suited conditions for using the RoundTripAuthValidator
implementation, it is possible to adapt or extend it to meet almost any kind of security requirement.
The primary difference in usage and extensibility of this validator depends on what type of traffic you expect for the application. You will need to consider, whether your traffic consists of registered users having an account with the business or anonymous users or a mix of both. Owing to its implementation, the RoundTripAuthValidator
can be flexibly used in one-to-one
, one-to-many
& many-to-many
streaming patterns involving both registered
and anonymous
users.
PERFECT FITS
- When you have users holding an account on your business server.
- When you need to know who is using it. (hence the username/password parameters)
- One – many applications (1 broadcaster => N subscribers), where you need to distinguish between publishers and subscribers.
- Two-way chat where every user is both publisher and subscriber.
ADAPTABLE FITS
- When you need anonymous usage of your application (no fixed credentials for users).
- When you have custom authentication parameters to pass along with standard credentials.
Understanding different types of user access
Registered Users
Registered users are clients having an account with the business system and hence having a set of standard credentials to validate against. Authenticating registered users works out of the box since the simple auth plugin expects a minimum of two
parameters – username
& password
. For business systems that implement credentials using these parameters, round trip authentication will work out of the box, apart from standard plugin configurations.
Anonymous Users
Some times a system might not have the ideal username
, password
pair for client authentication or might want to use the username
parameters with a password alias
or a set of completely custom parameters
to identify the client session. In the context of this document & consuming services, a client that does not require strict identification using the username
& password
parameters is termed as an anonymous
user.
Anonymous usage is more flexible and desirable than strict account-based access because of its universal acceptance and widespread application possibilities. Systems can support and implement complete or partial anonymous access in different ways.
- Some of these systems will want to support the
username
parameter while substituting thepassword
with a customhash
that acts as analias
for the actual password. - Some systems may want to support the
username
parameter coupled with othercustom
parameters while skipping thepassword
parameter altogether. - Some systems might want to skip both
username
andpassword
and use othercustom
parameters that suit their business requirements better.
Custom parameter support
If you have a need to support custom
parameters in the roundtrip authentication mechanism other than the supported parameters (username
, password
& token
) such as a hash
or a collection of multiple parameters to identify the user access or session, you can use the token
parameter to pass in a complex string
which can contain multiple parameters formatted together.
The roundtrip authentication mechanism is built on top of the simple auth plugin core which requires that the client must pass username
and password
parameters. If these params are not provided the connection to the server will be rejected. Therefore if you wish to pass custom parameters you will also need to pass in dummy
values for the required
parameters.
WebRTC Parameters Example:
var baseConfiguration = {
host: window.targetHost,
app: 'live',
iceServers: iceServers, // will override the rtcConfiguration.iceServers
bandwidth: desiredBandwidth,
mediaConstraints: forceQuality,
connectionParams: {username: "anonymous", password: "anonymous", token: "token=mytoken¶m1=value1¶m2=value2"}
};
In the above snippet, we pass username
& password
parameters with a value of anonymous
. This ensures that the min required parameters are fulfilled. Then we overload the token
parameter to carry multiple parameters as a query string. This will ensure that the server accepts out parameters.
On the server side, the username
, password
& token
are extracted in a standard manner. On subsequent publish
or subscribe
request the parameters are sent to the configured remote endpoint for authentication. The /validateCredentials
handler on the remote endpoint logic should then extract the necessary parameters and decode the content of the token
parameter to unload the additional custom parameters.
You can create a complex string of parameters for the
token
parameter in any suitable format such as simple query string, stringified JSON, etc. Your validation endpoint should accordingly know how to decode and extract custom parameters from the complex string.
Usage in different application patterns
One-to-one Streaming
One-to-one
pattern-based applications such as live video chats, often require both parties to have equal level access to the application. In this pattern, each participant is a publisher as well as a subscriber. Thus is there no need for differentiation by roles. In such a use case you can either have the users use system with their username
& password
credentials or using username
and a temporary hash token
as an alias to the password.
-
If you have registered users on your system, you can either have them use their existing
username
&password
or theusername
with apassword
alias for authentication. -
In case you want to implement a public conference system without binding users to account creation, you can capture the
username
parameter from the user’s unique identifier (such as email Id) or generate an identifier for the intended session and then generate a custom value to be used as anpassword alias
or anone time password
. To prevent hotlinking/leeching a custom parameter containing a special signaturehash
can be relayed to the remote validation service.
It is important to note that, for such patterns, the
RoundTripAuthValidator
will be authenticating the client twice per session. First as a publisher (publishing own stream) and then as a subscriber (viewing the other participant’s stream).
If you wish to authenticate only once then you can use IConnection->setAttribute
to store track the state of authentication. After the publish
request has been authenticated, you can skip authenticating again on subscribe
request.
Many-to-many Streaming
Many to many streaming, commonly seen in conference applications, is a variation of the one-to-one
pattern and thus will follow the same principles for implementation of security.
One-to-many Streaming
The one-to-many
streaming pattern is common in applications like live auctions
, sports broadcasts
etc. Here the publisher client requires access authorization while the subscribers may or may not require it.
One-to-many
streaming usually requires identification & authorization on the publisher side and either complete partial anonymous access on the subscriber side. Identity of the subscriber is not of utter importance.
- Complete anonymous access: For complete anonymous access to stream playback,
username
&password
can be anything and actual subscriber authorization can be skipped at the remote application server. A good example of such systems is apublic video streaming channel
.
Such systems can include a special signature or secure hash to prevent hotlinking/leeching. Signature/secure hash can be generated using basic client info, session expiry information, etc.
- Session-based access: Session-based access lies between
anonymous
&identity-driven
access. In such a system we grant access to users based on their relationship with the system, but without directly involving any credentials. That is to state that only business customers have access to the stream but without having to provide actual credentials (username
&password
) as parameters.
For such an access, the username
& password
parameters can hold dummy values (to satisfy the required parameters
constraint) and additional custom parameters can be introduced to represent the user’s identity and access permissions indirectly such as a signed access token
, token creation time
, token expiry time
and other relevant information. The remote service should be able to decrypt the access token and validate the access by identifying the user and relevant permissions as necessary.
NOTE: It is also possible to mix
anonymous
access withsession
-based access to provide free and premium type services depending on the requirements of the system being designed.