I recently posted about consuming SQL Server Reporting Services, and how you may need to use the XmlUrlResolver in order to access the external source. Additionally, you may have need to get behind a credentialed page.

There is a lot of material out there on how you can accomplish this using C#, but one factor that gets looked over is the fact that many ASP.NET MVC sites use request verification tokens to curtail cross-site request forgeries. This is a design pattern added on to the Web.Mvc API by Microsoft, and if we are to gain access to our desired site, it needs to be taken into consideration.

Fortunately, if we have a legitimate set of user credentials, this becomes a trivial matter for most basic installations once you have a general idea of what you need to do.

#1 – Set Up a Cookie Class

To get started, we need a class that can manage our cookies. It will essentially establish a CookieContainer, and can make basic WebRequests.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

publicclassCookieAwareWebClient:WebClient

{

publicCookieAwareWebClient(CookieContainer container)

{

CookieContainer=container;

}

publicCookieAwareWebClient()

:this(newCookieContainer())

{}

publicCookieContainerCookieContainer{get;privateset;}

protectedoverride WebRequest GetWebRequest(Uri address)

{

varrequest=(HttpWebRequest)base.GetWebRequest(address);

request.CookieContainer=CookieContainer;

returnrequest;

}

}

#2 – Establish a Get Request

Personally, I found it easier to next think about what I would need for my final GET request, when I would repeatedly be calling on my access-restricted pages. Essentially, to first build out how I would use the solution and then go about figuring out how to build up to that need.

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

publicHtmlDocument GetPage(stringurl,CookieContainer CookieContainer)

{

Uri absoluteUri=newUri(a_url_string);

varcookies=CookieContainer.GetCookies(absoluteUri);

HttpWebRequest request=(HttpWebRequest)WebRequest.Create(url);

request.CookieContainer=newCookieContainer();

foreach(Cookie cookie incookies)

{

request.CookieContainer.Add(cookie);

}

request.Method="GET";

HttpWebResponse response=(HttpWebResponse)request.GetResponse();

varstream=response.GetResponseStream();

using(varreader=newStreamReader(stream))

{

stringhtml=reader.ReadToEnd();

vardoc=newHtmlDocument();

doc.LoadHtml(html);

returndoc;

}

}

What this does beyond a standard GET request is that it will receive a
CookieContainer from a previous request, iterating through the contents and adding them to the
CookieContainer of the current request. The function will return an
HTMLDocument of your requested page, which is exactly what it sounds like.

#3 – Create the Login Procedure

This leaves us with the code required to actually manipulate the login form.

To understand how to make it all work, you have to understand how the anti-CSRF feature works with ASP MVC. When you make a standard render request to the URL, MVC generates a
RequestVerificationToken which can perform a handshake with the server – think of it as a short-term and auto-generated private key/public key interaction. In order to make this feature seamless, the token is added to the form as a hidden input value and submitted along with the rest of the form information without the user ever being the wiser. You probably have used this feature hundreds of times without ever noticing, unless you were so inclined to look at the DOM.

That being said, we then need to first perform a GET request on the page with the login form, enabling
CookieContainer for that request. For functional reasons, I have set things up to receive the form values as a
NameValueCollection. We then need to add the
__RequestVerificationToken to that collection, and that can be found from the form on the page itself.

Once that is fixed, you can reliably target the input node of
__RequestVerificationToken and get its value. Once you have it, you can add it to your
NameValueCollection that contains the rest of your form input values.

We now have everything we need, including the token. But this token has been assigned to the previous request, which is fortunately synced with the
CookieContainer that you created earlier. Similarly to
GetPage(), if we iterate through the cookies from the previous request and add them to the current request, this will keep our available token matching with its header information for the server, thus passing the requirements for the MVC anti-CSRF system. This all needs to get packaged into a POST request that includes your
NameValueCollection, and returns that request’s
CookieContainer for future consumption by
GetPage().