• English
  • Français

Token-based security - XML Message format

This document describes the XML format used to create security tokens in Apideo. If you are not confortable with the notion of token-based security, you should start by reading the "Token-based security principles".

A sample XML message

The XML messages sent to Apideo match the XSD you can find at http://www.apideo.com/security/security_token.xsd

Below is a sample XML message containing all possible tags.

<?xml version="1.0" encoding="utf-8"?>
<account xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://www.apideo.com/api/security/security-token.xsd"
	apideoKey="123456789123456789">
	<default>
		<defaultRoom access="reject">
			<userlist access="reject" />
			<userprofile access="reject" />
			<sendEvents defaultAccess="reject" />
			<startCameras defaultAccess="reject" />
			<viewStreams defaultAccess="reject" />
		</defaultRoom>
		<room name="mainroom" access="allow">
			<userlist access="allow" filter="obj.type == 'manager'" />
			<userprofile access="allow" filter="obj.type == 'user'" />
 
			<sendEvents defaultAccess="reject">
				<sendEvent category="chat" access="allow" 
					filter="obj.msg != ''" />
				<sendEvent categoryregex="chat_[0-9]*" access="allow" />
			</sendEvents>
			<startCameras defaultAccess="reject">
				<startCamera regex="mystream_[0-9]*" access="allow" />
			</startCameras>
			<viewStreams defaultAccess="reject">
				<viewStream regex="manager_[0-9]*" access="allow" />
			</viewStreams>
		</room>
	</default>
	<token name="AFFGTR45789DSF456D9Z0" ttl="3600">
		<defaultRoom access="reject">
 
		</defaultRoom>
		<room name="mainroom" access="allow">
			<userlist access="allow" />
			<userprofile access="allow" filter="obj.type == 'manager'" />
 
			<sendEvents defaultAccess="allow" />
			<startCameras defaultAccess="allow" />
			<viewStreams defaultAccess="allow" />
		</room>
	</token>
	<token name="Q4E6F6ID125SDFE487SCEZ" ttl="60">
		<defaultRoom access="reject"></defaultRoom>
		<room regex="room_[0-9]*" access="allow">
			<userlist access="allow" />
			<userprofile access="allow" />
		</room>
	</token>
</account>

Let's have a look at the XML tags available.

The <account> tag (root tag)

This tag contains your Apideo key:

<?xml version="1.0" encoding="utf-8"?>
<account xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://www.apideo.com/api/security/security-token.xsd"
	apideoKey="123456789123456789">
	<default>
	</default>
	<token name="xxx" ttl="60">
		...
	</token>
	<token name="yyy" ttl="60">
		...
	</token>
</account>

The account tag is the root of the XML message. It contains your Apideo key, as an attribute. In the account tag, you can put one default tag and several token tags. The default tag contains the default rule that will be applied if no tokens are passed by the user. Each token tag contains the rules to apply for a token.

More details are provided in the XSD reference for the <account> element.

The <default> tag and the <token>

The <default> tag contains the security rules to be applied by default. If the user does provide a token inside joinRoom or if the token passed in parameter does not exist or if the token rules do not specify anything meaningful, the default rule will be used instead.

Please note that if the default rule does not explicitly forbid an action, it will be allowed. For instance, if you do not specifically specify that sending events is not allowed, all users who do not provide a token will be able to send events.

More details are provided in the XSD reference for the <default> element.

The <token> tag contains the security rules to be applied for one token. The <token> tag has 2 attributes: "name" (the name of the token) and "ttl" (the time to live, in seconds for the token).

For instance:

<token name="AFFGTR45789DSF456D9Z0" ttl="3600">
	...	
</token>

Both <default> tag and <token> tag contain the same set of rules. An exemple is shown below:

<token name="AFFGTR45789DSF456D9Z0" ttl="3600">
	<defaultRoom access="reject">
		...
	</defaultRoom>
	<room name="mainroom" access="allow">
		...
	</room>
	<room regex="room_[.]*" access="allow">
		...
	</room>
</token>

The <defaultRoom> tag and <room> tag

The "room" tag contains rules to be applied for a specific room or a set of rules.

The "room" tag has a "name" attribute to tell the name of the room. Alternatively, you can use the "regex" attribute to use a regular expression. Finally, the "access" attribute can have 2 values:

  • "allow" to allow access to the room
  • "reject" to deny access to the room

The "defaultroom" tag contains the list of rules to be applied by default, if no rules are found for a specific room. First, Apideo will check the "room" tags, and if no room matches the room joined, then the "defaultroom" tag applies.

Here is an example:

<token name="AFFGTR45789DSF456D9Z0" ttl="3600">
	<defaultRoom access="reject">
		...
	</defaultRoom>
	<room name="mainroom" access="allow">
		...
	</room>
	<room regex="room_[.]*" access="allow">
		...
	</room>
</token>

This token denies by default access to any room, but will authorize access to the room whose name is "mainroom" and to any room starting with "room_".

So for instance, this code will succeed:

myConnection = Apideo.connect("123456789123456789");
// Access to "mainroom" is allowed.
myRoom = myConnection.joinRoom("mainroom", null, "AFFGTR45789DSF456D9Z0");

while this code will throw an error.

myConnection = Apideo.connect("123456789123456789");
// Access to "forbiddenroom" is denied because the defaultRoom settings apply for this room.
myRoom = myConnection.joinRoom("forbiddenroom", null, "AFFGTR45789DSF456D9Z0");

Finally, if inside your <token> tag, there are several <room> tags, you must know that <room> tags will be applied from top to bottom. Apideo will stop on the first room match. Here is an exemple:

<token name="AFFGTR45789DSF456D9Z0" ttl="3600">
	<defaultRoom access="reject">
		...
	</defaultRoom>
	<room regex="room_[0-9]*" access="allow">
		...
	</room>
	<room name="room_42" access="reject">
		...
	</room>
</token>

At first sight, you read that access rooms is denied by default, except for rooms starting with "room_" which are allow, except again for room_42 which is denied. This is not exact.

Let's see what happens if the user wants to join "room_42":

myConnection = Apideo.connect("123456789123456789");
// Access to "room_42" is allowed!
myRoom = myConnection.joinRoom("room_42", null, "AFFGTR45789DSF456D9Z0");

Access to room_42 will be allowed! Indeed, Apideo looks at the first <room> tag. The regex used does apply: "room_[0-9]*" is matched by "room_42". Therefore, Apideo will apply this rule and will not look into next rules. Actually, the second rule is useless. The XML message should be written this way:

<token name="AFFGTR45789DSF456D9Z0" ttl="3600">
	<defaultRoom access="reject">
		...
	</defaultRoom>
	<room name="room_42" access="reject">
		...
	</room>
	<room regex="room_[0-9]*" access="allow">
		...
	</room>
</token>

Inside the <defaultRoom> tag and the <room> tag, you can put a number of specific rights to allow or reject access to specific resources. The list of tags supported is listed below:

<room access="allow" name="myroom">
	<userlist access="allow" />
	<userprofile access="allow" />
 
	<sendEvents defaultAccess="reject">
		...
	</sendEvents>
 
	<startCameras defaultAccess="allow">
		...
	</startCameras>
	<viewStreams defaultAccess="reject">
		...
	</viewStreams>
</room>

Each tag is described below.

The <userlist> tag

The userlist tag is used to decide whether the user is by default allowed to view the list of users that are part of the room he is in.

It has an "access" attribute that can be either "allow" or "reject".

If access to the user list is rejected by the token, a call to the "forEachUser" method will return an error:

// Triggers a security error:
myroom.forEachUser(function(userId, userObj) { ... });

Finally, the userlist tag contains a "filter" attribute. You can only use this attribute if "access" is set to "allow".

Using the filter, you can decide that your user will be able to see only a part of the users that are connected to the room.

The filter is a one-line Javascript code that must matched the users profiles.

In the Javascript code, you can access the user profiles using the "obj" variable. Below is an example:

<userlist defaultAccess="accept" filter="obj.type=='manager'" />
In this sample; by default, the user cannot only see the users who have a profile with type=='manager'.
So if another user connects with this profile, he will be visible to the first user:
conn.joinRoom('myRoom', {type:'manager'});

However, the user below would not be visible to the first user:
room.joinRoom('myRoom', {type:'user'});

The <userprofile> tag

The userprofile tag is used to decide whether the user is by default allowed to submit a user profile to the list of users that are part of the room he is in.

It has an "access" attribute that can be either "allow" or "reject".

If access to the user profile is rejected by the token, any call to "joinRoom" must pass "null" as the second argument:

// The second parameter (the user profile) must be null if &lt;userprofile access='reject'&gt;:
myroom.joinRoom('myroom', null, 'AJVFDSOISDLDSKLDSF');

Finally, the userprofile tag contains a "filter" attribute. You can only use this attribute if "access" is set to "allow".

Using the filter, you can decide that your user will be able to submit a profile only if it respects a number of conditions.

The filter is a one-line Javascript code that must matched the users profiles.

In the Javascript code, you can access the user profiles using the "obj" variable. Below is an example:

<userprofile defaultAccess="accept" filter="obj.type=='user'" />

In this sample, the user cannot only join the room if he sets his type to "user".

So this will be ok:
conn.joinRoom('myRoom', {type:'user'}, 'AJVFDSOISDLDSKLDSF');

And this will be denied access:
room.joinRoom('myRoom', {type:'manager'}, 'AJVFDSOISDLDSKLDSF');

The <sendEvents> tag

The <sendEvents> tag is used to decide whether the user is by default allowed to send events or not.

It has a "defaultAccess" attribute that can be either "allow" or "reject".

The default behaviour can be overloaded by individual "sendEvent" tags.

The "sendEvents" tag can contain any number of "sendEvent" tag.

The "sendEvent" tags are applied from top to bottom. Apideo will stop going through tags after one tag is matched, so the order is important. Here is an example:

<sendEvents defaultAccess="reject">
	<sendEvent regex="event_[.]*" access="allow" />
	<sendEvent name="event_42" access="reject" />
</sendEvents>

In the example above, the second "sendEvent" rule will never be applied, because the first regex will always be matched first. So this code will result in an access allowed:

// Access  will be denied
room.sendEvent({}, "event_42")

However, access will be denied if you put the rules in the other way.

<sendEvents defaultAccess="reject">
	<sendEvent name="event_42" access="reject" />
	<sendEvent regex="event_[.]*" access="allow" />
</sendEvents>

The <sendEvent> tag

The "sendEvent" tag is used to decide whether a user can send a kind of events or not.

The "category" attribute contains the listener name that is allowed or denied.

Alternatively, you can use the "categoryregex" attribute to pass a regex in parameter.

The "access" attribute decides whether the rule will allow or deny access.

Finally, the "filter" attribute contains Javascript code that must be matched for the filter to be applied.

In the Javascript code, you can access the object sent using the "obj" variable. Below is an example:

<sendEvents defaultAccess="reject">
	<sendEvent name="mylistener" filter="obj.type=='manager'" access="allow" />
</sendEvents>

In this sample, by default, the user cannot send events. However, he can send events if the event listener is "mylistener" and if the object passed in parameter contains type == 'manager'.

So this code would be correct:
room.sendEvent({type:'manager', text:'Hello!'},"mylistener");

This code would be denied by Apideo:
room.sendEvent({type:'administrator', text:'Hello!'},"mylistener");

The <listeners> tag

The listeners tag is used to decide whether the user is by default allowed to listen to events or not.

It has a "defaultAccess" attribute that can be either "allow" or "reject".

The default behaviour can be overloaded by individual "listener" tags.

The "listeners" tag can contain any number of "listener" tag.

The "listener" tags are applied from top to bottom. Apideo will stop going through tags after one tag is matched, so the order is important. Here is an example:

<listeners defaultAccess="reject">
	<listener regex="event_[.]*" access="allow" />
	<listener name="event_42" access="reject" />
</listeners>

In the example above, the second "listener" rule will never be applied, because the first regex will always be matched first. So this code will result in an access allowed:

// Access  will be allowed
room.registerListener(myListener, "event_42")

However, access to the listener will be denied if you put the rules in the other way.

<listeners defaultAccess="reject">
	<listener name="event_42" access="reject" />
	<listener regex="event_[.]*" access="allow" />
</listeners>

The <listener> tag

The "listener" tag is used to decide whether a user can listen to a kind of events or not.

The "category" attribute contains the listener name that is allowed or denied.

Alternatively, you can use the "categoryregex" attribute to pass a regex in parameter.

The "access" attribute decides whether the rule will allow or deny access.

The <startCameras> tag

The startCameras tag is used to decide whether the user is by default allowed to send a stream or not.

It has a "defaultAccess" attribute that can be either "allow" or "reject".

The default behaviour can be overloaded by individual "startCamera" tags.

The startCameras" tag can contain any number of "startCamera" tag.

The "startCamera" tags are applied from top to bottom. Apideo will stop going through tags after one tag is matched, so the order is important. Here is an example:

<startCameras defaultAccess="reject">
	<startCamera regex="stream_[.]*" access="allow" />
	<startCamera name="stream_42" access="reject" />
</startCameras>

In the example above, the second "startCamera" rule will never be applied, because the first regex will always be matched first. So this code will result in an access allowed:

// Access  will be denied
room.startCamera("cameraDiv", "stream_42")

However, access will be denied if you put the rules in the other way.

<startCameras defaultAccess="reject">
	<startCamera name="stream_42" access="reject" />
	<startCamera regex="stream_[.]*" access="allow" />
</startCameras>

The <startCamera> tag

The "startCamera" tag is used to decide whether a user can send a stream or not.

The "name" attribute contains the name of the stream that is allowed or denied.

Alternatively, you can use the "regex" attribute to pass a regex in parameter.

The "access" attribute decides whether the rule will allow or deny access (can be "allow" or "reject").

The <viewStreams> tag

The "viewStreams" tag is used to decide whether the user is by default allowed to view a stream or not.

It has a "defaultAccess" attribute that can be either "allow" or "reject".

The default behaviour can be overloaded by individual "viewStream" tags.

The "viewStreams" tag can contain any number of "viewStream" tag.

The "viewStream" tags are applied from top to bottom. Apideo will stop going through tags after one tag is matched, so the order is important. Here is an example:

<viewStreams defaultAccess="reject">
	<viewStream regex="stream_[.]*" access="allow" />
	<viewStream name="stream_42" access="reject" />
</viewStreams>

In the example above, the second "viewStream" rule will never be applied, because the first regex will always be matched first. So this code will result in an access allowed:

// Access  will be denied
room.viewStream("cameraDiv", "stream_42")

However, access will be denied if you put the rules in the other way.

<viewStreams defaultAccess="reject">
	<viewStream name="stream_42" access="reject" />
	<viewStream regex="stream_[.]*" access="allow" />
</viewStreams>

The <viewStream> tag

The "viewStream" tag is used to decide whether a user can send a stream or not.

The "name" attribute contains the name of the stream that is allowed or denied.

Alternatively, you can use the "regex" attribute to pass a regex in parameter.

The "access" attribute decides whether the rule will allow or deny access (can be "allow" or "reject").