Deny Access With URL Rewrite Based On Custom Header

Adrian Jenkins
6 min readFeb 4, 2022

What do we want to achieve?

Given a Site, we usually want users to access all resources, but in this case, we need to deny access to all resources living in a specific folder for those clients who do not send a specific header and value in their requests.

We will have:

A) “http://localhost:90/vars.aspx

B) “http://localhost:90/Only-Header/vars.aspx

For URL “B”, only clients with the following header will be allow:

  • DogName: Luka

Prerequisites:

  • A site created and hosted in IIS.
  • URL Rewrite module installed

Setting up our Environment

  1. Create a folder. Mine is called “MyURLPractice”
  2. Create a “vars.aspx” file.
  3. Create a child folder. Mine is called “Only-Header”.
  4. Inside this child folder create another “vars.aspx” file.

Inside these files we are going to place a “for-each” to display all Server Variables:

<%
For Each var as String in Request.ServerVariables
Response.Write(var & “ “ & Request(var) & “<br>”)
Next
%>

This is the structure of my site:

5. Now we will open IIS Manager and create an Application Pool for this site.

6. Create the actual site in IIS Manager

Let us see a request to both URL’s:

The issue right now is that the “Private” resource (on the right side of the image), should only be allow for clients who send a specific header in the request.

We are not sending any headers and I am still able to get both resources.

This is a problem.

URL Rewrite deny access based on custom header

This will be our approach:

  • First, we will create a rule to flag a request based on if it has that specific header or not.
  • Second, we will create another rule to block access based on that flag.
  1. Open IIS Manager.
  2. Select your site and open URL Rewrite module.
  3. Click “View Rewrite Maps” (in here, we will create a static listing).
  4. Add a Rewrite Map and name it as you wish. I named mine “Authorized Clients” (We will need this name later)

5. Add Mapping Entry.

In here is where we will create our “white-list”. In this case, the only value that we are going to accept is “Luka”. I know we have not specified that this value is for a specific header. We will do that later.

We are saying that we expect the value “Luka”, if this is true, the new value is going to be 1. So, we are going to compare based on this new value later.

6. Go back to Rules.

7. Create an inbound blank rule. The purpose of this rule is to flag the request.

In “Conditions” section is where the magic happens.

Remember the Rewrite Map that we created?

Well, we called it “Authorized Clients”.

And remember that our original value was “Luka”?

So, the flow of the condition, if true, will be somewhat the following:

If “Luka” (value stored in Authorized Clients) == “Luka” (value in Header)

“Luka” = 1

If 1 (Luka’s new value) == 1 (Pattern)

True (Condition Passed)

In order to recognize custom headers, you will have to preceded with eighter “HTTP_” or “HEADER_”. But keep in mind there is a difference:

“HTTP_”: The server will interpret any underscore “_” characters as dashes “-” in the actual header.

“HEADER_”: The server will interpret all characters as-is.

Now, we are going to take advantage of this server variable: “HTTP_X_AUTHORIZED_ADMIN”.

So, if it passes the condition, the value of this variable will be set to “yes”.

For “Action” section, we select “None”. We just want to flag our requests.

Let us test what we have for now:

Hmmm… A bit disappointed actually. But nothing to worry about, we just have to add this variable to the “Server Variables” in order to change its value.

Now let us make the same request:

Noticed we managed to flag the request!

Now let us make the same request but without the header:

As it does not contain the header and value that we are looking for, it was not flag. This is great news, but we still have to deny access to those clients that do not present this header.

8. Create a new inbound blank rule to block access.

For the “Pattern” we will use the regular expression that means that the path has to start with “Only-Header/<whatever comes next>”.

So, the client that do send the specified header and value, will have access to everything withing this folder.

For “Conditions” sections we can simply use our flag: “HTTP_X_AUTHORIZED_ADMIN”.

If this variable is not “yes”, we are going to respond with a custom error.

We are all done, and it is time to test this!’

Test 1:

Request to: “http://localhost:90/vars.aspx”

Is Header Present: no

Should Allow: yes

Test 2:

Request to: “http://localhost:90/vars.aspx”

Is Header Present: yes

Should Allow: yes

Test 3:

Request to: “http://localhost:90/Only-Header/vars.aspx”

Is Header Present: no.

Should Allow: no.

Test 4:

Request to: “http://localhost:90/Only-Header/vars.aspx”

Is Header Present: yes.

Is Header With Correct Value: no.

Should Allow: no.

Test 5:

Request to: “http://localhost:90/Only-Header/vars.aspx”

Is Header Present: yes.

Is Header With Correct Value: yes.

Should Allow: yes.

Resources

--

--