asp.netweb-servicesiisisapi

Securing Legacy Web-Service site using anonymous authentication for local access


I have a legacy WebForms application that consumes (ASP.net) Web-Services (using anonymous access) that reside on the same IIS server (same domain, different apps each with their own dedicated app pool). This application was hosted in a secured VPN but now there is a request to host it publicly.

What is the expedient (yet secure) method to secure the web services site without doing a substantial re-coding (on the application level). I have tried configuring the Web-Service site in IIS so that it enables only the Service account (Identity) under which the Web Applications App Pool runs but the current request mode coming from the application is always using Anonymous access. I need to restrict access to allow only the this specific web application. I am thinking of an ISAPI filter, but it is not recommended for IIS 7+ ?

ADDENDUM: I would love to find an IIS based solution. Currently I am trying to restrict access based to just the Web Application source. Problem is (as stated) is those request are all "Anonymous" if I could make those requests use "Network Service" or some other local Identity then I would be set.


Solution

  • After more research I have settled on an http Module Solution, as it has the following benefits:

    • Minimal Coding

    • No need to modify existing code base

    • Easy deployment

    • Follows existing ASP.Net security models for (Local access)

    The Module (VS:DLL Project)

    using System;
    using System.Web;
    using System.Threading;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace FilterModule
    {
        class AuthorizeLocal : IHttpModule
        {
            public void Init(HttpApplication app)
            {
                app.BeginRequest += new EventHandler(OnBeginRequest);
            }
    
    
            private void OnBeginRequest(Object s, EventArgs e)
            {
                HttpApplication app = s as HttpApplication;
                HttpRequest req = app.Request;
                HttpContext context = app.Context;
    
                if (!req.IsLocal)    // Is the request from a Local Source?
                {
                    context.Response.Close(); // close the response: ends request
                }
    
                /* Optional Test Code - to view locally create an html page TestModule.html in target site */
                string Identity = Thread.CurrentPrincipal.Identity.Name;
                string filePath = context.Request.FilePath;
                string fileExtension = VirtualPathUtility.GetExtension(filePath);
                string fileName = VirtualPathUtility.GetFileName(filePath);
    
                if (fileName.ToLower().Equals("testmodule.html"))
                {
                    try
                    {
                        app.Context.Response.Write("app: " + app.ToString());
                        context.Response.Write("<br/>server: " + app.Server.ToString());
                        context.Response.Write("<br/>Thread.CurrentPrincipal.Identity.Name: " + Thread.CurrentPrincipal.Identity.Name);
                        context.Response.Write("<br/>HttpRequest: " + req.Url.ToString());
                        context.Response.Write("<br/>req.UserHostName: " + req.UserHostName);
                        context.Response.Write("<br/>req.UserHostAddress: " + req.UserHostAddress);
                        context.Response.Write("<br/>filePath: " + filePath);
                        context.Response.Write("<br/>fileName: " + fileName);
                        context.Response.Write("<br/>fileExtension: " + fileExtension);
                        context.Response.Write("<br/>req.IsLocal: " + req.IsLocal.ToString());
                        context.Response.Write("<br/>req.LogonUserIdentity: " + req.LogonUserIdentity);
                        context.Response.Write("<br/>req.UserHostName : " + req.UserHostName);
                        context.Response.Write("<br/>req.AnonymousID " + req.AnonymousID);
                        context.Response.Write("<br/>req.IsAuthenticated : " + req.IsAuthenticated);
                    }
                    catch (Exception Ex)
                    {
                        context.Response.Write("<br/> " + Ex.ToString());
                    }
                }
    
                //if (_eventHandler != null)
                //    _eventHandler(this, null);
            }
    
            public void Dispose()
            {
    
            }
    
        }
    }
    

    Implementation

    1. Add the compiled DLL (FilterModule.dll) to the Web Service (site) bin Directory.

    2. Add the following to module definition in the Web Service (or site) configuration file (web.config)

    in the <system.webServer> section under <modules>
    add the following:

    <add name ="FilterModule" type="FilterModule.AuthorizeLocal" />