Using HTTP Referer to prevent deep linking to a WMS server

For a number of years now I've had customers ask me about how to prevent deep linking from random people directly to their Windows Media server. Deep linking is described on https://en.wikipedia.org/wiki/Deep_linking. Often this occurs when a web site owner does not ask for permission to point an embedded media player on their own site to a stream on someone else’s Windows Media server. The web site owners who host their own Windows Media servers may want to allow only those clients that visit their web site access to the WMS server. They may also want to have their client authenticate with a user name and password to be able to stream the video content.

Let me stop right here and say that the sample code that I’m providing is just that. It’s sample code. No warranty expressed or implied. You’re on your own. Let me also say that this is not going to keep your content 100% double extra secure. It is just an easy *somewhat* secure way of preventing deep linking. If you want high security, look into the Windows Media Rights Manager SDK.

Typically what I have recommended in the past is using an authorization plug-in running in WMS. Essentially you would generate a query string on your web server that contains some unique value on the end (example: mms://streaming.contoso.com/video.wmv?authorization=6883af2234jjji8). In this example the authorization code of 6883af2234jjji8 would be unique for the session while browsing the web site. You could then drop that value and a time/date stamp onto a SQL server. You would write an authorization plug-in for WMS that would take the client request, look up the authorization ID in the SQL server and then allow or disallow the connection. There are a number of variations on this theme, but typically it’s usually done somewhat like this.

I wanted to do something easier that required much less programming and didn’t have to have special web code or a third server (like SQL) to handle a deep linking issue. The code example below is an Active Script sample. Copy the code (or download it from the link below) and save it as a .vbs file in your C:\WMPub folder. This folder has the appropriate NTFS permissions for WMS to be able to read from the .vbs and write the log file. Then locate the WMS Active Script Event Handler in the WMS admin under Windows Media Services\<machine name>\Properties\Event notification. In the Active Script plug-in, browse to the script sample in the WMPub folder. Note, you will need to make one change to the third line in the script as noted in the comment in the code. Enable the plug-in and you’re ALMOST done. The way this script works is by reading the HTTP REFERER header value from the HTTP protocol from the user's GET request. This GET request is made when you link to the content on your Windows Media server from the HTML page on your web server. The HTTP REFERER is automatically included in the request. If the user is not making a request from a web page on your web site, they will be denied access.

NOTE: This value is not available with RTSP. That means that you must turn off RTSP for this to work properly.

Here’s the code:

 Dim strMyServer
'Change the www.contoso.com value to the DNS name of your site.
strMyServer = "www.contoso.com"

Dim LogFile

Sub CreateLog
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Set LogFile = fso.CreateTextFile("c:\wmpub\wmroot\AuthorizationLog.txt", True)
End Sub

Sub TraceInformation( strTraceText )
LogFile.WriteLine( strTraceText )
End Sub

Sub OnWMSPluginInitialize ( ServerCtx )
CreateLog
tempStr = "OnWMSPluginInitialize " & Now
TraceInformation( tempStr )
End sub

Sub OnWMSPluginShutdown ()
tempStr = "OnWMSPluginShutdown " & Now
TraceInformation( tempStr )
LogFile.Close
End sub

Function OnWMSEAuthorizeOpen (UserCtx, PresCtx, CmdCtx)
Dim strReferer
'Turning off error checking temporarily while getting the user context. If there is no
'referer context value then we do not want to end here with an error. If there is no
'referer context value we will fail at the first if statement and return the access denied.
On Error Resume Next
strReferer = UserCtx("WMS_USER_REFERER").Value
On Error Goto 0

tempStr = "Validating " & strReferer & " on " & Now
Dim DomainName
DomainName = GetLowerFQDN (strReferer)

    if DomainName = LCase(strMyServer) then
OnWMSEAuthorizeOpen = &H00000000
tempStr = tempStr & " - Access Granted"
else
OnWMSEAuthorizeOpen = &H80070005
tempStr = tempStr & " - Access Denied"
end if
TraceInformation( tempStr )
End Function

Function GetLowerFQDN(strURL)
'Strips off the initial https:// or https://
tempDNS = Mid(strURL, InStr(strURL, "://") + 3)

    'Checks to see if a port number is used after the DNS name and strips that off.
if Mid(tempDNS, 1, InStr(tempDNS, ":")) <> "" then
tempDNS = Mid(tempDNS, 1, InStr(tempDNS, ":")-1)
end if

    'Removes everything after and including the first slash. What remains should be
'the DNS name.
if Mid(tempDNS, 1, InStr(tempDNS, "/")) <> "" then
tempDNS = Mid(tempDNS, 1, InStr(tempDNS, "/")-1)
end if
GetLowerFQDN = LCase(tempDNS)
End Function

 

EventAuthorizationCallbackSample.zip