Search code examples
c#asp.netweb-servicesauthenticationasmx

Basic authentication on a remote server


I need some help with ASMX web-services.

Let's suppose I have a ServerService which provides some data. Let's suppose it has a method GetRandomInteger which returns a random integer (obviously). It implements a custom basic authentication using IHttpModule.

public class BasicAuthHttpModule : IHttpModule
{
    private UserRepository _userRepository;

    public void Dispose()
    {
    }

    public void Init(HttpApplication application)
    {
        _userRepository = new UserRepository();
        application.AuthenticateRequest += OnAuthenticateRequest;
        application.EndRequest += OnEndRequest;
    }

    public void OnAuthenticateRequest(object source, EventArgs e)
    {
        var app = (HttpApplication)source;

        string authHeader = app.Request.Headers["Authorization"];
        if (!string.IsNullOrEmpty(authHeader))
        {
            // Here I successfully get credentials from header

            if (_userRepository.ValidateUser(username, password)) return;

            // Return 401 and CompleteRequest
        }
        else
        {
            // Return 401 and End
        }
    }

    public void OnEndRequest(object source, EventArgs eventArgs)
    {
        if (HttpContext.Current.Response.StatusCode == 401)
        {
               // Return 401 and require new authorization
        }
    }

Fortunately, it works. Now I can successfully open Service.asmx file, get basic authentication window and get access to it's GetRandomInteger method after successful authentication.

Now I have an ASP.NET MVC 4 application called ClientService. It must provide user interface with convenient and appropriate access to methods of ServerService. Now it has default controllers like Account and Home, default views etc.

  1. I need this ClientService to authenticate on a ServerService. I mean there will be a Home/Index page with button "Login". I enter login and password there and ClientService tries to authenticate at ServerService. It returns error on fail or authenticates on success providing access to some Home/RandomInt page which will show the integer requested from ServerService. What is the best and the easiest way to do this?

  2. How to implement registration on a ServerService? There is no AllowAnonymous attribute or something at ASMX, so I can't register user because he doesn't have access to any of methods due to 401 error.

Thank you in advance.

P.S. No. I can't use WCF or something else. I need to implement an ASMX web-service.

Update 1: OK, I have learned something new from here

http://www.aspsnippets.com/Articles/How-to-add-reference-of-Web-Service-ASMX-in-ASPNet-using-Visual-Studio.aspx

There is an old-style thing like "Web reference" and it's not an "Service reference". I have added this Web reference to my project and now I can call some methods from this ASMX page in this way:

        try
        {
            ServerService svc = new ServerService();
            svc.Credentials = new NetworkCredential("user", "password");
            int a = svc.GetRandomInteger();
        } catch (WebException e) {
            // Auth failed
        }

However, I don't understand how to link it with ASP.NET MVC ClientService authentication. So, both questions are still open. Hopefully, I will understand it or you will help me.


Solution

  • Here is a documentation for adding a Web reference to an ASMX Service.

    http://www.aspsnippets.com/Articles/How-to-add-reference-of-Web-Service-ASMX-in-ASPNet-using-Visual-Studio.aspx

    Using this information I can easily make requests to a web service.

    The only thing I left to do on the moment of question update is to create a custom authentication.

    1. When user logins, the client sends a request to a service. In case of successful basic authentication, it creates proper FormsAuthentication cookie ticket for a user. User logs in.

    2. On each request to a service, the client extracts login from FormsAuthentication cookie and his password from server cache and uses them to authenticate on a service. In case of basic auth failure (it can only occur if user's password has been changed on the service side) the cookie is cleared and session is aborted.

    3. Registration is implemented using another one ASMX service which is not using basic auth but is anonymous (because registration is supposed to be anonymous method).

    That's it. Finally, I have found a proper solution :)