An Alexa Skill for Unlocking Channel Content on my Roku

At home my young kids consume their favorite TV programs from the Disney and Nick Jr. channels on our Roku. We have a subscription to DIRECTV NOW that gives us access to the content on these channels. One annoyance of this setup is that every month these channels require us to manually re-affirm our DIRECTV NOW subscription. The process involves taking an activation code displayed by the channel on TV and manually entering it into an activation web site online. Then I need to enter my DIRECTTV NOW credentials to unlock the channel content again.

This minor inconvenience started grating on me over time, and I was curious to see if I could simplify things using our Echo Dot. After all, Robert Heinlein once said, “Progress isn’t made by early risers. It’s made by lazy men trying to find easier ways to do something.” I wanted to simply be able to tell Alexa the channel that needed to be unlocked and the activation code, and then have it perform the unlock automatically. This would also enable my wife and kids to unlock channels when I wasn’t around.

Here’s how I created a skill to do just this…

Green Eggs and SAML?

I started by digging into the activation process, using Google Chrome’s Developer Tools and curl.

To start with, a user receives an activation code from his or her TV. Something like this, an example from the Disney Channel:

Both the Disney and Nick Jr. channels make use of a service provider called Adobe Primetime (formerly known as Adobe Pass) for managing user access to their content. The activation code that’s displayed on TV is generated by Adobe Primetime.

When the user goes to the activation web site (e.g. http://www.disney.com/activate), he or she enters the activation code and also chooses a TV provider. In my case, that’s DIRECTV NOW.

The activation code and TV provider selection are sent by the user’s browser to Adobe Primetime. Adobe Primetime then returns a response to the browser that redirects it to a login screen for the TV provider. The redirect doesn’t go directly to the web site of the TV provider though. It redirects to an identity provider that acts on behalf of the TV provider. In the case of DIRECTV NOW, the identity provider is a site called Evergent.

When Adobe Primetime redirects the user to Evergent, it passes some information to Evergent in the redirect URL in the form of a SAML authentication request. SAML stands for “Security Assertion Markup Language.” It’s a standard for two entities, a service provider and an identity provider, to exchange authentication and authorization information about users. The SAML request includes identifiers for the service provider and the identity provider, a request ID, timestamp, and a callback URL that the identity provider uses to send a response back to the service provider after the user has authenticated.

After log in, Evergent sends a SAML response back to the callback URL provided by Adobe Primetime. The SAML response asserts that the user actually has an account with the TV provider and the time period for which the authentication can be considered valid. In my case, with DIRECTV NOW, the validity period is one month – this explains why I need to go through this process every month. The SAML response is also signed by Evergent and includes the original request ID.

Adobe Primetime validates the SAML response from Evergent, and if validation is successful, it knows who the user is. But it still doesn’t know if the user has a plan with DIRECTV NOW that authorizes him or her to view the channel’s content. To check whether user is in fact authorized, Adobe Primetime communicates over a back-channel (no pun intended) with Evergent. If all goes well, Adobe Primetime then signals back to the user’s browser and device (e.g. my Roku) that the channel content is unlocked.

At a high level, the SAML interchange between the service provider and identity provider looks like this:

Client-side and server-side redirects are used to make the process appear smooth to the end-user. If you’re curious to know more, the flow is described above is discussed in much more detail here on the OASIS standards site.

The Alexa Skill: Channel Unlocker

After figuring out the above flow, I used the handy Python requests library to code it up. Then I wrapped it in an Alexa skill, called Channel Unlocker, to invoke it automatically. I used the Alexa Skills Kit Python SDK to develop the skill and hosted it on AWS Lambda. The flow for the skill looks like this:

The most interesting part of building this skill was structuring the interaction model in such a way that Alexa could reliably understand the activation code. At first, I used a single variable (i.e. slot in Alexa parlance) to represent an activation code. That didn’t work very well. I then broke up the activation code into seven different slots, one for each digit of the code. I created a custom slot type to represent a code digit, and the slot type was defined to cover all possible alphanumeric characters. A quirk of Alexa is that a number sound must be represented in word form, and a letter sound must be represented as the letter followed by the period character, ., as shown below:

                {
                   "name": "CodeDigit",
                   "values": [
                        {
                            "name": {
                                "value": "nine"
                            }
                        },
                        {
                            "name": {
                                "value": "eight"
                            }
                        },
                        {
                            "name": {
                                "value": "seven"
                            }
                        },

                        ...

                        {
                            "name": {
                                "value": "z."
                            }
                        },
                        {
                            "name": {
                                "value": "y."
                            }
                        },
                        {
                            "name": {
                                "value": "x."
                            }
                        },

                        ...

                    ]
                }

This worked pretty well, but I found that Alexa sometimes got confused when certain letters sounded like words. For instance, ‘u’ and ‘you’, or ‘y’ and ‘why’, or ‘r’ and ‘are’. To improve Alexa’s character recognition, I defined synonyms for each of the letters, like this:

                {
                    "name": "CodeDigit",
                    "values": [
                        {
                            "name": {
                                "value": "nine"
                            }
                        },
                        {
                            "name": {
                                "value": "eight"
                            }
                        },
                        {
                            "name": {
                                "value": "seven"
                            }
                        },

                        ...

                        {
                            "name": {
                                "value": "z.",
                                "synonyms": [
                                    "zee"
                                ]
                            }
                        },
                        {
                            "name": {
                                "value": "y.",
                                "synonyms": [
                                    "why"
                                ]
                            }
                        },
                        {
                            "name": {
                                "value": "x."
                            }
                        },

                        ...

                    ]
                }

This did the trick, and I now have a working skill that does what I want and lets me be a little bit extra lazy in life.

Putting It Altogether

If you want to be lazy too, check out the complete source code here. When deploying the Lambda function, make sure to attach it to a VPC with external network access, and set the USERNAME and PASSWORD environment variables to your TV provider credentials. You can optionally encrypt your credentials using AWS’s Key Management Service. Fork it if you’d like to support your own TV provider, channel(s), or device!

Leave a Reply

Your email address will not be published.