How to authenticate in an ASP.NET MVC application from a console application

Go To StackoverFlow.com

4

I have a console application that sends a XML to a MVC application and receive another XML as a response. It works perfectly, but I want to add authorization (for obvious reasons).

Here is the code from the console application:

using (var wc = new WebClient())
{
    return GetXmlFromBytes(
        wc.UploadData("URL", GetBytesFromXml(xmlToSend))
    );
}

And here is the code from the MVC application:

public ActionResult DoSomething()
{
    XElement xml = XElement.Load(new System.IO.StreamReader(Request.InputStream));
    var response = InsertDataFromXml(xml);
    return File(GenerateFileFromResponse, "text/xml", "result.xml");
}

And it works. So, to implement the authorization, I added the following code:

Console (added the wc.Credentials):

using (var wc = new WebClient())
{
    wc.Credentials = new NetworkCredential("user", "password");
    return GetXmlFromBytes(
        wc.UploadData("URL", GetBytesFromXml(xmlToSend))
    );
}

MVC application (added the [Authorize]):

[Authorize]
public ActionResult DoSomething()
{
    XElement xml = XElement.Load(new System.IO.StreamReader(Request.InputStream));
    var response = InsertDataFromXml(xml);
    return File(GenerateFileFromResponse, "text/xml", "result.xml");
}

And it doesn't work. I don't know if this information is needed to solve this, but my web.config has the following item:

<authentication mode="Forms">
  <forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication> 

In fact, the file that the MVC application sends back is the HTML of the LogOn page!

What do I have to do to solve this? Is any parameter missing in the NetworkCredentials? I know it can be instantiated with a domain, but I don't know what is the domain of the users in the MVC application.

And, just to make sure: I assured "user" and "password" are valid.

2012-04-05 21:31
by Lucas Reis
Forms Authentication doesn't work that way - it relies on HTTP cookies. You need Windows Integrated Authentication, or you need to perform a "login" first using your console application - bzlm 2012-04-05 21:36


3

You're mixing credential types;

wc.Credentials = new NetworkCredential("user", "password");

is for HTTP authentication.

<authentication mode="Forms">
  <forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication> 

is forms authentication.

These are entirely different, and not compatible. Using forms authentication from a command line app is challenging, you'd need to go to the login page with a request, POST the username and password, then take the authentication cookie that is return and attach it to subsequent requests.

2012-04-05 21:40
by blowdart
It is an option to change the auth mode - but I can't loose the ability to use a LogOn form. If I change it to HTTP auth will I loose this ability? (sorry, I'm really a "noob" in this subject! - Lucas Reis 2012-04-05 21:52
Yes, if you switch to HTTP auth you loose forms auth - blowdart 2012-04-06 01:13
How about creating a custom Authorize attribute for this action and check the http headers for the credentials - ZippyV 2012-04-06 10:43
Nice, Zippy! This is the idea I'll implement.. - Lucas Reis 2012-04-09 13:00


1

You need to Authenticate first of all as you are using Forms Authentication.

  1. Invoke the Logon Web Method and capture the Auth Cookie from the Http Response
  2. Set the Auth Cookie on the second Http Request to the DoSomething Method

Or Set the Auhentication Mode="Windows" if you are on a local intranet!

2012-04-05 21:38
by Shay
It's not a local intranet; the MVC application will be in another server. Any ideas on how to have a simple authentication that works both from distance and with a LogOn form - Lucas Reis 2012-04-05 21:53
I know how to set the cookie in number 2 ( wc.Headers.Add(HttpRequestHeader.Cookie, "somecookie");, right? ), but I still don't know how to do numer 1. Any ideas - Lucas Reis 2012-04-05 22:07


1

Create an AuthenticationService which can be used to do forms authentication. With the ClientBaseExtensions class you can get the cookie out of your WCF service client. Inject this cookie into the other call...

String cookies = null;
var auth = new AuthenticationServiceClient();
using (new OperationContextScope(auth.InnerChannel))
{
    auth.Login("user", "password", null, true);
    cookies = auth.GetIncomingCookies();
}

Now inject the cookie data into your data service or your HTTP call.

See http://mytoolkit.codeplex.com/wikipage?title=ClientBaseExtensions

2012-04-05 22:47
by Rico Suter
Ads