Token authentication with "Azure Verizon Premium CDN"
This walkthrough demonstrates how to use "Azure CDN Premium from Verizon" in front of a private blob storage container as origin.
In this system, the client's browser should securely access an asset stored in a private container in blob storage, via CDN. Secure in this context means that access to the cached asset in CDN should only be granted to authorized clients, and access from the CDN to the origin should be authenticated as well. The term 'origin' usually refers to the service 'behind' the CDN, in our case an Azure Storage Account.
To implement this, the client signs in 'somehow' to the web application, using whatever is in place (step 1 below). The web application generates a 'CDN auth token', and tells the browser to fetch the asset from CDN (step 2 below). That CDN URL contains the CDN auth token in the URL's query string. The CDN endpoint (strictly speaking the CDN's point of presence (PoP) or edge node) validates the CDN auth token, and (when allowed) either serves the cached copy of the asset, or fetches the contents from the origin (step 3 below).
- Storage account name:
- Force HTTPS
- Enable storage account keys
- Inside the container, create an "Stored access policy"
- Policy identifier:
- Start time: Yesterday
- Expiry time: Something far in the future
- After creating the policy, go the the container's "Shared access tokens" tab
- Signing key: Key 1 or Key 2
- Stored access policy ==
- Click "Generate SAS token and URL"
- The Blob SAS token looks like this:
- The Blob SAS URL looks like
- Upload a sample file to the container
- After uploading the file, check that the SAS actually works, by putting the filename into the middle of the SAS URL, such as
- Select "Explore other offerings" (instead of the default "Azure Front Door")
- In "Choose other offerings", pick "Azure CDN Premium from Verizon"
- In Profile Details
Global, Pricing Tier:
- Tick the "Create a new CDN endpoint" box
- CDN Endpoint name:
- which means our public hostname will be
https://cdnchgeuer20230119.azureedge.net, unless we later enable a custom domain name.
- Origin type: "Storage"
- Origin hostname: Pick your storage account, in my case
Create, and take a cup of coffee.
- What now happens is that Azure in the back calls out to APIs of Edgecast/Verizon to provision a CDN profile for you. That can take a while, because Verizon under the hood will roll out your chosen hostname globally to all the various edge nodes (also called 'points of presence')
- Configure the endpoint: Once provisioning is finished, in the resource group you should see the Storage account, the CDN profile, and the CDN endpoint:
Azure Portal Resources
In the endpoint's "Origin" settings, you might consider disabling the
Azure Portal CDN Origin
All the rest of the fine-grained configuration happens by navigating to "Advanced Features" and clicking the "Manage" link at the top of the page:
Azure Portal Advanced CDN Features
You now are authenticated and redirected to
cdn.windowsazure.com/http/token/default.aspx, which is the place where we can configure token authentication:
Verizon Portal empty token auth configuration
- In the Linux shell (for example in a bash shell in WSL), we'll be using OpenSSL to generate to high-entropy cryptographic keys:
openssl rand -hex 160twice and note down the results. This command generates hexadecimal encoded cryptographically strong random numbers, and the number is the number of bytes. 160 bytes would be 1280 bit, encoded in 320 hex characters.
- Prefix the first value with
primaryand the second one with
backup, so it's easier to see which key you're looking at.
- You can also bump up the "Minimum Encryption Version" from
Verizon Portal populated token auth configuration
By clicking on the "HTTP Large" menu on the top, and selecting "Rules Engine V4.0", you come to the graphical rule editing experience.
Verizon Portal empty rules
+Newbutton, and type in a new name for the draft rule, such as
v1, and click "Continue"
- Click the
- Rule Description:
Require CDN Token
- Click the
+dropdown and select
Select Categorydropdown should be
- The second dropdown should be
URL Path Directory Wildcard
Resultdropdown should be
Valueis the path in the CDN URL, something like
Relative Todropdown should be
- Enforce token auth: Next, click the indented
Select Categorydropdown ==
Select Featuredropdown ==
- Name the token parameter:
- Add another
Feature, this time
Token Auth Parameter, and
- In the
Nametext box, pick the name under which your web app will convey CDN tokens to the CDN. That could be
Finally, save our first rule.
+Ruleto add a second rule, with a rule description of
Append SAS Tokenor similar
- Click the
+button and again select
Match, this time with
- On the indented
+button, add a
URLcategory, with feature being
Destinationtext boxes have a little resize handle in the bottom right, you might want to make these text boxes larger to see what you're putting here.
- Now we need to tell the CDN how incoming URLs should be re-written to the external origin server (Azure Blob storage in our case).
- To know the string we need to know, temporarily click the bottom
+button to add another
Match, and select
Customer Origin. In the Value dropdown, you should see something like this:
Verizon Portal customer ID
- In the dropdown (marked with a
1in the screenshot), you can see a customer origin identifier, in our case
/801A0567/cdnchgeuer20230119/. Please type this text into the
cdnchgeuer20230119part in this string is the name of the endpoint which you configured earlier in the Azure portal.
- However, the
/801A0567/looks slightly random. In practice, this is your Verizon customer ID, which you can see in the upper righthand corner of the portal (
1A0567), prefixed with the
80. So in theory, you could just look at your user account info on screen, but in case that
80prefix changes in the future, temporarily creating a customer origin rule makes it easy to lookup.
- Now please delete the temporarily created match, by clicking the little recycle bin icon (
Our screen should now look like this:
Verizon Portal Rule 2 creation step 2
- Now that our
Destinationtextboxes have the base information, we need to extend it with a mechanism to inject our shared access signature token.
- In the
Sourcetextbox, append the name of your container, and the regular expression
(.*)\?(.*)to the content, so it looks like this:
- The request coming on to the CDN looks something like this:
https://cdnchgeuer20230119.azureedge.net/cdnfiles/somefile.zip?cdntoken=xxx, i.e. the path prefix
/cdnfiles/, a file (
somefile.zip), and the query string containing our CDN token (
- The regular expression cracks up the path around the questionmark (
\?), into the file name (
somefile.zip) in the first regex capture group, and the query string (
cdntoken=xxx) in the second regex capture group.
- In the
Destinationtext box, we concatenate the following strings
- Our base
- Our storage account container name
- Then we put the file name, which is captured in the 1st capture group, by adding
?to start the query string again
- Our SAS string (
- An additional
&for additional parameters
- The second capture group
- So the overall result is
Verizon Portal Rule 2 finished
- Save the second rule, and click "Lock Draft as Policy"
- In the
Raw XMLwindow, you can also see an XML representation of the rules
<description>Require CDN Token</description>
value="/cdnfiles/" ignore-case="false" relative-to="origin">
<feature.access.token-auth-parameter name="cdntoken" enabled="true"/>
<description>Append SAS Token</description>
- Now, click the "Deploy Request" Button, select the "Production" environment, type in a deployment message (like "Deploying v1"), and "Create Deploy Request"
Lets push to prod
- Once submitted, the Verizon system will validate the rules, after a couple of seconds, you should be seeing an "Approved" mark in the Activity log. Overall, the deployment of the rules to the various edge / PoP nodes might take a few minutes.
- Finally, we can create a CDN token, to test our solution. We navigate back to the "HTTP Large / Token Auth" page. Further down on that page is an "Encrypt Tool" section, a small web-based UI to create a CDN token. For a simple test, we need two properties in the token, an expiration date (
ec_expire) and a part of the URL we're granting access to (
ec_expireheader must be an epoch value, an integer which you can create using web sites such as unixtimestamp.com or epochconverter.com. For example, the timestamp "Wed Dec 31 2025 23:59:59 UTC" corresponds to the epoch value
ec_url_ allowcan contain values such as
- Encrypting these two parameters under my primary key gives me a generated token of
In your solution, you (of course) won't visit the Verizon portal to generate a CDN token. You will be using your web application to (protected) generate web links pointing to CDN. So in your web solution, you need to generate these CDN tokens programatically, you certainly want to make these short-lived, limit them to a specific client, and use all the other good features.
On the .NET side, I created a small library Azure-Samples/edgecast-cdn-token-fsharp: A .NET sample to create tokens for Edgecast Azure CDN which can help you generating such tokens. In a C# solution for example, you could generate tokens like this:
var key = "primary4c5604fb8f76524cd99cf65700fd550a92f083d297c327a50cae5891f1f6fcb6965cadaaa56682e3998e376f1cb3db757348356f73a936bfdae12c4eab07e02e70d5108593a97f267cdb2c16c87c58832270a7cfd0199ecd0808169f54238be400e7950f44bce9f801395061cf741ac1f12ea2341b8887c2b6692b6074695854834047c8bff52b3a284a51290483a985f78ad0c548d98fe306c9be3cd12605b8";
var token1 =
year: 2025, month: 12, day: 31,
hour: 23, minute: 59, second: 59))
var token2 =
// more extension methods available
// Token1: sU5Hu8WjfvysnYVmy6i4nsdNbQGrlnc7snQN075VgHJAj_XVnehjA - xGohmvDwCdJHGFirgBVoAoUmSdrtajA76KwB_5Hsw3
// Token2: sU5Hu8WjfvysnYVmy6i4nsdNbQGrlnc7tHYI0bpZj3lAj_XVnehjA - xGohmvDwCdJHGFirgBVoD1w7xarONEKKhIGWp9nrT2
With all that information, we can now hit the CDN endpoint and access a file in our private blob storage container.
As a quick reminder, the direct URL to hit our origin server (blob storage) contained the shared access signature:
Instead of the SAS, the CDN URL contains our
When we hit the CDN without token, or a modified one, we get a
403 - Forbiddenpage.
Otherwise, you can enjoy this beautiful image: