User Authentication for Wowza Streaming Engine®

This article shows a simple way to authenticate the players of your Wowza streams using Wrench module. Authentication means here to associate an identity with the clients, most typically a user name or login name. Knowing the identity of your player allows you to do further authorization checks (has the user the role / permisssion to watch my stream? has the user payed for the service? etc).

This Wowza user authentication tutorial assumes that you have already set up your Wowza application and you have some means to authenticate your users on your website before showing the stream. This can be easily achieved if you are using a CMS like Drupal.

Update: since this article was written, a new out-of-the-box example with detailed instruction video has been created. While you can still use this article as a reference, I suggest you to check out Streamtoolbox Examples on GitHub and watch the below YouTube video.

Install the Wrench module from the toolbox

The Wrench module is a single jar file that you can download from the toolbox. Copy the wrench-xxx.jar file under the lib directory of your Wowza installation (e.g. c:\wowza-x.x\lib) where you can find all the other jar files. Putting this file there will automatically include in on the classpath where Wowza Streaming Engine® can load the module if any application refers to it.

If you copied the jar file to the right place and added it to your Application.xml, you should see this line in your logs:

Starting Wrench 2015.03.26, licensed to ...
Using database url ..., user ....

If you did not put it to the right place, you should see this in the logs:

Module class not found or could not be loaded. Check [install-dir]/conf/live/Application.xml to be sure all Modules/Module/Class paths are correct: name:Wrench class:com.streamtoolbox.Wrench

Caution: you need to restart the OS level process of Wowza to get the jar file loaded. Using the "Restart" button on the web interface is unfortunately not enough.

Add required libraries

Wrench requires the JDBC driver of the database that you are using for storing tokens. Copy this jar file under the lib directory of your Wowza installation. In the FAQ section you can find a table with details for the most common databases.

Set up the table in your database to hold hashed tokens

You need to create a table a database which stores hashed tokens and associated user information. You can create this table in the database that your website uses, e.g. into your Drupal installation's database. The table has to be able to store the hashed token, the username and optionally the IP address of the user. Reason for storing hashed token is that it is a one time password actually, that is not nice to store in cleartext anywhere. An example for MySQL is below:

 CREATE TABLE wtb_tokens (
   ID int(12) NOT NULL AUTO_INCREMENT,
   USER varchar(128) NOT NULL COMMENT 'User name',
   TS timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
   IP varchar(64) NOT NULL,
   TOKEN varchar(128) NOT NULL COMMENT 'Hashed tokens',
   PRIMARY KEY (`ID`) 
)

Generate tokens

Whenever you want to show the stream link or your embedded player on your website, you have to first generate a random token. This acts as a one-time-password, so be careful to make it random in cryptographical sense. A simple example to generate this in PHP is as follows:

  <?php $token = uniqid(); ?>

Having generated the token, you have to store its hash in the above mentioned table together with the username that you should be able to determine from your web application's session information. An example in PHP that can be used in a typical Drupal 7.x node using the PHP filter is as follows:

$ip = $_SERVER['REMOTE_ADDR'];
global $user;

$conn = mysql_connect("localhost:3306/mydb", "user", "pass");
mysql_select_db("mydb", $conn);
mysql_query("INSERT INTO wtb_tokens (IP, TOKEN, USER) VALUES ('$ip', md5('$token'),'$user->name')");
mysql_close ($conn);

The above snippet is just to give you the idea of what needs to be done, you can write it more elegantly in your code. Be careful to store the hashed token in your database.

Pass tokens to player

The unhashed token is passed from the client to Wowza in the connection url. An example setup for the popular JW Player:

jwplayer("cc").setup({ 
   flashplayer: "/player.swf",
   file: 'rtmp://myserver:1935/mystreamingapp/?token=<?php echo $token; ?>/myStream',
   bufferlength: 5
});

(For JW Player 5, there was an other pattern, see FAQ for details)

Or you can put the tokens into your HTTP stream link for iOS and Android devices:

<a href="<?php echo 'http://myserver/mystreamingapp/streamName/playlist.m3u8?token='.$token; ?>">Watch video</a>

Let me emphasize again that the clear token has to be passed to the player. Wrench will do the hasing on its side using the configured wrench.token.hashing algorithm and substitute the hash into the token resolver query's :hashedtoken placeholder.

Configure Wrench in your Wowza application

In Wowza terminology, an "application" is a unit of configuration that can serve multiple streams. You create a new application by creating an empty folder with the desired application name under Wowza's application directory. Create the same named directory under conf and copy the default conf/Applicaton.xml there, or if you already have your application configured, then just add the following module definition under <Modules>

<Modules>
  ...
  <!-- Make sure Wrench is the last configured module -->
  <Module>
    <Name>Wrench</Name>
    <Description>Wrench provides user authentication to your application</Description>
    <Class>com.streamtoolbox.Wrench</Class>
  </Module>
</Modules>

The above snippet enables the module on your application. You also need to specify the settings for Wrench as follows:

<Properties>
  <Property><Name>wrench.db.driver</Name><Value>com.mysql.jdbc.Driver</Value></Property>
  <Property><Name>wrench.db.url</Name><Value>jdbc:mysql://localhost:3306/somedatabase</Value></Property>
  <Property><Name>wrench.db.user</Name><Value>john</Value></Property>
  <Property><Name>wrench.db.pass</Name><Value>secret</Value></Property>

  <Property><Name>wrench.dbcp.initial.size</Name><Value>1</Value></Property>
  <Property><Name>wrench.dbcp.max.size</Name><Value>10</Value></Property>
  <Property><Name>wrench.dbcp.test.on.borrow</Name><Value>true</Value></Property>
  <Property><Name>wrench.dbcp.test.sql</Name><Value>select 1 from wtb_tokens</Value></Property>


  <Property><Name>wrench.encoder.token</Name><Value>ncoder</Value></Property> 
  <Property><Name>wrench.token.url.parameter</Name><Value>token</Value></Property>
  <Property><Name>wrench.token.hashing</Name><Value>md5</Value></Property>
  <Property><Name>wrench.token.resolver.sql</Name><Value>select user as username,ip from wtb_tokens where token=:hashedtoken</Value></Property>
  <Property><Name>wrench.connect.authorization.sql</Name><Value>select 1 from wtb_permissions where user=:username and allow=1</Value>
</Property>

The meaning of each property above is more or less self describing. In this article I skip defining them, just let me emphasize the main points:

  • When the client connects to Wowza, the token is parsed from the connection query string
  • The clear token is hashed and Wrench tries to identify the connection by executing the wrench.token.resolver.sql
  • The resoler query should return at least the username (and optionally IP and timestamp)
  • At this point we know who's coming
  • Wrench allows you to perform authorization checks with your custom wrench.connect.authorization.sql query. Based on the result set you can allow or reject the connection

The details and all the other features can be found in the reference documentation

Push your stream into your Wowza application

Download and install for example Flash Media Live Encoder from Adobe's website and set up your source as you like. When setting the FMS URL, point to your Wowza server and your application. Don't forget to add the token you have specified in the wrench.encoder.token property into the URL to bypass any authentication in Wowza. Of course you should use Wowza's other security settings besides this shared secret token to prevent others from pushing content into your application.

Settings in FMLE

If you are using ffmpeg to produce your stream, the way to construct the URL with the token inside is as follows:

ffmpeg ... -f flv rtmp://localhost:1935/live?token=ncoder/mystream

That's it. Having set up all the above, you can see not only the client id's, but the usernames in Wowza log and you can hook stream authorization into your system.

The full reference of Wrench configuration can be found here

Some better examples are being developed on GitHub, check them out!

Please feel free to leave your feedbacks and questions about this tutorial. I'll keep this updated as newer versions of the Wrench module are released.

Comments

Hello, my name is Erion Cuni. Actually i'm trying to implement your solution.Im interested for the advanced version,but i want to test it first with the free version and after than use dhe advanced solution. Actually im streaming 2 live channel using wowza.The problem is that i followed your tutorial in order to implement to my server.But the problem is that i try these sample and it seems that they dont work. Im sure ,that i have make some mistake.Let me describe my actual status of server configuration. Actually i installed wowza in my pc,and from another server i redirect the streaming to wowza media server installed on my pc,and succesfully i am able to generate 2 streaming instance. They are called: live mobile For live/mobile aplication im generating these type of stream. http://xx.xx.x.xx:1935/live/streamname1/playlist.m3u8 rtsp://xx.xx.x.xx:1935/live/streamname1 rtmp://xx.xx.x.xx:1935/live/streamname1 http://xx.xx.x.xx:1935/mobile/streamname1/playlist.m3u8 rtsp://xx.xx.x.xx:1935/mobile/streamname1 rtmp://xx.xx.x.xx:1935/mobile/streamname1 normally these stream links are only accecible on the intranet were i work,are not pubblished. My objective is to make these links user authentificable. I have tried to implement your module as follow. I have modified the Application.xml in conf/live/ as the sample. I have downloaded these jar: mysql-connector-java-5.1.12-bin wowza-wrench-2014.04.16 and put them on lib folder. also on localhost i have installed xampp and created db called "mobile_stream" . Created 2 tables: stream_tokens / wtb_permissions CREATE TABLE IF NOT EXISTS `wtb_permissions` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, `surname` varchar(45) NOT NULL, `allow` int(2) NOT NULL, `date` datetime NOT NULL, PRIMARY KEY (`id`) ) CREATE TABLE IF NOT EXISTS `stream_tokens` ( `ID` int(12) NOT NULL AUTO_INCREMENT, `USER` varchar(128) NOT NULL COMMENT 'User name', `TS` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `IP` varchar(64) NOT NULL, `TOKEN` varchar(128) NOT NULL, PRIMARY KEY (`ID`) ) This is the properties i set in one of my app xml cong (live) <Properties> <Property> <Name>wrench.db.driver</Name> <Value>com.mysql.jdbc.Driver</Value> </Property> <Property> <Name>wrench.db.url</Name> <Value>jdbc:mysql://localhost:3306/mobile_stream</Value> </Property> <Property> <Name>wrench.db.user</Name> <Value>devel</Value> </Property> <Property> <Name>wrench.db.pass</Name> <Value>deledevel34</Value> </Property> <Property> <Name>wrench.dbcp.initial.size</Name> <Value>1</Value> </Property> <Property> <Name>wrench.dbcp.max.size</Name> <Value>1</Value> </Property> <Property> <Name>wrench.dbcp.test.on.borrow</Name> <Value>true</Value> </Property> <Property> <Name>wrench.dbcp.test.sql</Name> <Value>select 1 from stream_tokens</Value> </Property> <Property> <Name>wrench.encoder.token</Name> <Value>alma</Value> </Property> <Property> <Name>wrench.token.url.parameter</Name> <Value>token</Value> </Property> <Property> <Name>wrench.token.hashing</Name> <Value>md5</Value> </Property> <Property> <Name>wrench.token.resolver.sql</Name> <Value>select user,ip from stream_tokens where token=?</Value> </Property> <Property> <Name>wrench.connect.authorization.sql</Name> <Value>select 1 from wtb_permissions where name=:username and allow=1</Value> </Property> </Properties> On localhost i have created a php file ,and created the player using the sample that you described on the web , $token="dd2638d2e166f63a5d37b5554f6e517c"; //i set a static token,generated and saved in db <div class="container"> <div class="starter-template"> <h4>ABCom Streaming TV <br><small>Coming soon Channel 1</small></h4> <div id="myElement">Loading the player...</div> <?php //echo $token; ?> <script type="text/javascript"> var streamer; jwplayer("myElement").setup({ flashplayer: "js/jwplayer.flash.swf", streamer: "rtmpe://10.88.5.14:1935/live/streamname1?token=<?php echo $token; ?>", file: streamer, bufferlength: 5 }); </script> </div> </div><!-- /.container --> </script> <a href="<?php echo 'http://10.88.5.14:1935/live/streamname1/playlist.m3u8?token='.$token; ?>">Watch video</a> Even im using the token or not the link is playable. Am i missing something? Please give me some suggestion Thank you very much

Hi Erion! Having analyzed the logs you have sent me, the problem is that wowza-wrench-xxx.jar was not on the classpath. First you need to make sure you see the "Starting Wowza Wrench" in your logs.

Hi! This plugin is great but I'm having some trouble in debugging the configuration, everything seems to be good, the logs indicate that the wrench is starting correctly, anytime I don't include the token in the url, the video does not stream, but if I put ANY value on the token, the stream plays normally. Is there any way I can debug or see what's going wrong? And other thing, the stream seems to play normally with HDS, Smooth, etc. the security only works with RTMP? Regards

Hi Ricardo! Good news is that the latest version of Wowza Wrench supports all this with HTTP based streaming too.

All fixed with the new version, now everything is working just perfect! Thanks!

What are the chances that if we buy the unlimited license that you guys will be able to do the installation of the wrench with user authentication and required files and libraries. Also with required DB Files and necessary tables and a working setup

So, I am assuming that for every stream switch there would be an SQL query generated? Using JWPlayer and switching between four live streams.

What happens when a user in mid stream play has their DHCP lease expire and get assigned a new IP address? if they do a browser refresh to restart play or switch to a different stream will authentication fail?

Hi Glenn, yes, check mechanism is triggered on each stream switch in that case. If their IP changes meanwhile, their token becomes unusable. However in that case I think their session might also get broken and can't refresh the browser page without logging in again. If you want to handle this case, I think you need to switch off IP checking. Theoretically, following your thoughts, their IP could even change between token generation and first connection. Not too probable though.

Hi! Great plugin! I have a small problem with wrench.connect.authorization.sql. I meant for it to be the final validation, and it's supposed to make a simple query in another table. I get the response: Executing SQL select .... And the 0 rows returned from sql authorization query, authorization passed. May be I misunderstood but, I thought that if this query returns a empty result set, the connection will be refused. Thanks in advance!

Hi Dan! Thanks for pointing this out, it was a bug in the code. I have released a fix for that starting from version 2014.06.24

Hello, I remarked that with a wrong token you can read a wowza streaming protect with wrench, with vlc without problem Do you have an explanation for this issue? Kind regards Guy

hi dear developer i have the some problem with this parameter " <Property><Name>wrench.encoder.token</Name><Value>ncoder</Value></Property> " my problem is that : i want to know how to configure the filter ip adress " <Name>wrench.token.ip.check</Name>" with this parameter or i must not use it because i have the serious problem to authentified the user

Great module ! How to use with nDVR an VOD? thank you

Hi voip! The setup is pretty much identical in VOD case. If you use nDVR, please contact me via email to check the details.

In Guy's case the issue was that Wrench was not able to make DB connection. In that case the fallback mechanism is accepting connections. After fixing that it started working. anguemo2000x: the encoder token is a way around other checks, so it can' be used with ip checking. That is for the scenario when there is a single and trusted encoder, so no need to check the IP of that. In all other cases encoders can use regular generated tokens and then IP check and all other checks will be applied to them as well.

We have tested on Windows Wowza server and it worked, when we ported it to Linux version, the database it seems like the database connection in not establishing, removing the JDBC driver from the Lib directory is not giving any errors in logs. The Wrench is starting, we can send a stream with ffmpeg using token, but the users from database not authenticating - we get 2014-11-04 11:36:47 PST connect-pending session INFO 100 10.110.11.16 - _defaultVHost_ vodsecure _definst_ 0.046 [any] 10000 rtmp://204.174.xxx.xx:10000/vodsecure 10.110.11.16 rtmp http://204.174.xxx.xx:8088/e nginemanager/applications/test/vod/FlashRTMPPlayer/vod.swf/[[DYNAMIC]]/3 WIN 15,0,0,189 1769136852 3544 3073 - - - - - - - - - - - - - rtmp://204.174.xxx.xxx:10000/vodsecur e - 2014-11-04 11:36:47 PST comment server INFO 200 - Client connecting with id 1769136852 and query strin g [caller: onConnect] _defaultVHost_ vodsecure _definst_ 856.182 - - - - - - - - - - - - - - - - - - - - - - - - - 2014-11-04 11:36:47 PST comment server INFO 200 - Refusing client with id 1769136852 because token was not present in the query string. Query was: _defaultVHost_ vodsecure _definst_ 856.182 - But we send token with VLC and the same command works on windows server. Any ideas whey would JDBC driver not be used with Wrench and how do fix it?

wowzatoolbox, actually i found the problem: with: http://204.xxx.xxx.xxx:10000/vodsecure/mp4:sample.mp4/playlist.m3u8?token=12345 OK problem with : rtmp://204.xxx.xxx.xxx:10000/vodsecure/mp4:sample.mp4?token=12345

That's good news, thanks for sharing the solution!

:) Any way, why i cant play rtmp://204.xxx.xxx.xxx:10000/vodsecure/mp4:sample.mp4?token=12345 ?

Good question, I admit that the URL format is not too nice, but this is how Wowza works and Wrench being a plugin can't really change this behaviour.

I have developed and application for Wowza to record the stream - using HTTPDvrStreamRecord when I am not using Wrench it works When I record a secure stream it fail error: HTTPDvrStreamRecord.start: DVR Recorder not found for stream 'channel11'. Do you know how to pass the token to the HTTPDvrStreamRecord , and after recording how to pass token to the nDVR to view the recorded stream?

I'm testing the plugin and it's working great. I saw that the same SQL querry (wrench.disconnect.log.time.sql) it's executed when a user close the stream or the same user qot disconnected because of wrench.duplicate.limit is reached. Can we have a second SQL query that it's executed if the user got disconnected with reason duplicate-limit? I'm using the SQL query (wrench.connect.accept.sql) to hook the user connected, online and (wrench.disconnect.log.time.sql) for user disconnect but i got the same SQL query executed on disconnet even if user got disconnected because of duplicate limit.

Hi kodo, thanks for the feedback. Actually I was wondering if you need a second query or just an extra parameter in the disconnect query to differentiate between the two cases..? Both is feasible, I'll get in touch with you via email to discuss it.

Hey, I'm trying to configure rtmp streaming and in the same time I want to be able to activate the authorization (wtb_permissions) in the wrench module, I'm able to do this with the HLS streaming over http and it seems to be performing both queries for authentication (wtb_token) and authorization (wtb_permissions). but when I try the same configuration over rtmp it obly perform the hash token authentication step and cannot seem to do any sql queries to the wtb_permissions. your help is highly appreciated

Hi, can you send me over your config Application.xml and the logs for the RTMP case via email? I need to take a closer look to help you.

Its working with Wowza Media Server 2-2-4 ? i tried but not working for me

I am struggling to understand the fundamental security protection. If I supply the token into the url for jw player as you suggest: jwplayer("cc").setup({ flashplayer: "/player.swf", file: 'rtmp://myserver:1935/mystreamingapp/?token=<?php echo $token; ?>/myStream', bufferlength: 5 }); then what will prevent a very modestly technical person to view the source of the page and copy the above code (along with the token) and pass it to a friend, who has not been authorized to see the content? If I understand correctly, the token will still resolve into a valid user name and the second person can see unauthorized content. My recollection about token-based authentication is that the token is actually getting passed in the request header, not in the body and not in the url. In your article, you are saying that the token is a one-time password. That's nice - I assume the web application will need to update wtb_tokens table upon each user's request. So, I assume that once the web application authenticates (assuming web service is used), it is also responsible for deleting the corresponding row for the user from the table. Is this correct? Also, I see that the IP address is used as an additional mechanism, but that overall is a weak security mechanism - people on the same network will share IP address. Some of them will be valid and some of them - invalid users. Can you please help me with my naive questions. I suppose, I am missing something very basic.

Before I give Wrench a try, can you tell me if videojs supports the token passing scheme that you use for user stream playing authentication? Thanks... Glenn

Hi Glenn, yes, videojs also should work. Wrench only requires the player to be able to handle query parameters in the video url, which basically all of them do.

Hello, you note that Wrench is free just for 25 clients, did you mean 25 Concurrent Client Or 25 Total Clients ?

It's 25 concurrent users.

Hello , I set the "wrench.publish.authorization.sql" , and I see the document says I can use the parameter: :username, :stream, but I don't know how to set the username parameter from the xsplit. Please help me thanks.

Hi Jason, I have replied to you via e-mail, hope you received it. I asked for clarification about "xsplit".

Hi, I'm getting "Refusing client with id 1518806293 because token was not present in the query string. Query was: null" log in wowza logs when i try to play stream with your demo web page. Any suggestion?

Hold on, let me check the expected token parameter..

Hi there, We are developing mobile application from where user can stream through mobile camera. We want to use wrench token while user viewing the stream on another mobile but problem is that, user streaming to wowza from camera stream (we are using ffmpeg to encode stream to wowza) is refused by Wowza even though we are passing token in given format. rtmp://HOST:PORT/live?t=TOKEN/STREAMNAME rtmp://HOST:PORT/live/STREAMNAME?t=TOKEN We are getting error, "Refusing client with id 896718290 because token was not present in the query string. Query was:" Please suggest, what is the correct way to pass token while streaming to Wowza (mobile to wowza) Best Regards