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.

1
  • 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. Commented Apr 5, 2012 at 21:36

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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!)
Yes, if you switch to HTTP auth you loose forms auth.
How about creating a custom Authorize attribute for this action and check the http headers for the credentials?
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!

2 Comments

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?
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?
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.