none
ASMX with MASSL RRS feed

  • Question

  • We have a legacy ASMX service which we want to implement MASSL. I have experience configuring WCF with MASSL, but not with ASMX. This is a very large service and did not get migrate to WCF. I wanted to know if anyone has configured MASSL with ASMX, if yes, can you provide some configuration samples? Or show how you configured the system.servicemodel section of your web config file. Thanks in advance.



    • Edited by tonyvang612 Friday, January 8, 2016 3:35 AM
    Friday, January 8, 2016 1:14 AM

Answers

  • The above cannot be the answer since the OP is requesting a solution using the legacy ASMX web service infrastructure.

    If you are using .NET 4.0 or above, I recommend you try creating a trivial WCF service using the out of the box "WCF Service Application" template. You will find it is nearly as easy to use as an ASMX service. You can then use the answer provided by Wanjun Dong.

    I do not believe it will be possible to do this with ASMX. One of the reasons why ASMX has been replaced by WCF is the lack of flexibility. It can basically only do SOAP (or a little JSON) over http or https. It knows nothing about MASSL.

    If you can get http://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication to work with the WebRequest class, then you may be able to override the GetWebRequest and GetWebResponse methods of your proxy class to return custom implementations.

    IMHO by the time you have to resort to that, you have lost the ease of use of ASMX and you had just as well go learn WCF, which is made to be customized.


    John Saunders

    Friday, January 22, 2016 10:55 PM
    Moderator

All replies

  • Hi,

    Could you explain to me what is MASSL?

    For how  to configured the WCF service in web.config file,

    you can refer to the following article:

    https://msdn.microsoft.com/en-us/library/ee530014%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

    Best Regards,

    Vince

    Saturday, January 9, 2016 1:26 AM
  • Hi tonyvang612,

    According to this case,  here is my web.config file that shown how to configured the

    system.servicemodel section.

    I hope that will be helpful to you.

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" />
      </system.web>
      <!-- When deploying the service library project, the content of the config file must be added to the host's 
      app.config file. System.Configuration does not support config files for libraries. -->
      <system.serviceModel>
        <services>
          <service name="WcfServiceLibrary1.Service1">
            <host>
              <baseAddresses>
                <add baseAddress = "http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/" />
              </baseAddresses>
            </host>
            <!-- Service Endpoints -->
            <!-- Unless fully qualified, address is relative to base address supplied above -->
            <endpoint address="" binding="basicHttpBinding" contract="WcfServiceLibrary1.IService1">
              <!-- 
                  Upon deployment, the following identity element should be removed or replaced to reflect the 
                  identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
                  automatically.
              -->
              <identity>
                <dns value="localhost"/>
              </identity>
            </endpoint>
            <!-- Metadata Endpoints -->
            <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
            <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, 
              set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
              <!-- To receive exception details in faults for debugging purposes, 
              set the value below to true.  Set to false before deployment 
              to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="False" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    
    </configuration>
    

    You can create a WCF service via visual studio, then you can config the system.servciemodel section

    in web.config file.

    Best Regards,

    Wanjun Dong


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place. Click HERE to participate the survey.

    Monday, January 11, 2016 1:45 AM
    Moderator
  • The above cannot be the answer since the OP is requesting a solution using the legacy ASMX web service infrastructure.

    If you are using .NET 4.0 or above, I recommend you try creating a trivial WCF service using the out of the box "WCF Service Application" template. You will find it is nearly as easy to use as an ASMX service. You can then use the answer provided by Wanjun Dong.

    I do not believe it will be possible to do this with ASMX. One of the reasons why ASMX has been replaced by WCF is the lack of flexibility. It can basically only do SOAP (or a little JSON) over http or https. It knows nothing about MASSL.

    If you can get http://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication to work with the WebRequest class, then you may be able to override the GetWebRequest and GetWebResponse methods of your proxy class to return custom implementations.

    IMHO by the time you have to resort to that, you have lost the ease of use of ASMX and you had just as well go learn WCF, which is made to be customized.


    John Saunders

    Friday, January 22, 2016 10:55 PM
    Moderator
  • Contrary to John Saunders' answer custom authentication is totally achievable with ASMX web services. ASMX is just ASP.NET with mixins, after all.

    As with ASP.NET, custom authentication is achieved by implementing IHttpModules and registering them in your web.config file.

    First, start by turning off the default authentication schemes in your web.config file:

    <configuration>
      <system.web>
        <authentication mode="None" />
      </system.web>
    </configuration>

    Second, implement your custom IHttpModule classes.

    Finally, add your custom authentication IHttpModules to your web.config file (note that I've chained three together here):

    <configuration>
      <system.webServer>
        <modules>
          <add name="HttpClientCertificateAuthenticator" type="Example.Web.Modules.HttpClientCertificateAuthenticator, CustomApplicationAuthentication, Version=1.0.0.0, Culture=neutral" />
          <add name="HttpBasicAuthenticator" type="Example.Web.Modules.HttpBasicAuthenticator, CustomApplicationAuthentication, Version=1.0.0.0, Culture=neutral" />
          <add name="UnauthorizedAuthenticatorModule" type="Example.Web.Modules.UnauthorizedAuthenticator, CustomApplicationAuthentication, Version=1.0.0.0, Culture=neutral" />
        </modules>
      </system.webServer>
    </configuration>

    The last IHttpModule in the chain, UnauthorizedAuthenticator, might look like this (simplified):
    using System;
    using System.Net;
    using System.Web;
    
    namespace Example.Web.Modules
    {
    	public class UnauthorizedAuthenticator : IHttpModule
    	{
    		#region Implementation of IHttpModule
    
    		public void Dispose() { }
    
    		public void Init(HttpApplication context)
    		{
    			context.AuthenticateRequest += OnAuthenticateRequest;
    			context.EndRequest += OnEndRequest;
    		}
    
    		#endregion
    
    		internal void OnAuthenticateRequest(object sender, EventArgs e)
    		{
    			try
    			{
    				var application = (HttpApplication)sender;
    				var context = application.Context;
    				var isAuthenticated = context.User != null && context.User.Identity.IsAuthenticated;
    				if (!isAuthenticated && context.Response != null)
    				{
    					context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    				}
    			}
    			catch (Exception exception)
    			{
    				var message = "Internal Server Error";
    				throw new HttpException((int)HttpStatusCode.InternalServerError, message, exception);
    			}
    		}
    
    		internal void OnEndRequest(object sender, EventArgs e)
    		{
    			try
    			{
    				var application = (HttpApplication)sender;
    				var context = application.Context;
    				if (context.Response != null && context.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
    				{
    					//For correct quoting consult:
    					//RFC 7235 Hypertext Transfer Protocol (HTTP/1.1): Authentication
    					//especially 2.2. Protection Space (Realm)
    					string realmValue = "Basic realm=\"My Application Realm\"";
    					const string WwwAuthenticateHeader = "WWW-Authenticate";
    					application.Context.Response.Headers[WwwAuthenticateHeader] = realmValue;
    				}
    			}
    			catch (Exception exception)
    			{
    				var message = "Internal Server Error";
    				throw new HttpException((int)HttpStatusCode.InternalServerError, message, exception);
    			}
    		}
    
    	}
    }

    And a highly simplified Mutual SSL Authentication (aka. 2-way SSL Authentication, aka. Client Certificate authentication) authenticator might look like this:
    using System;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Principal;
    using System.Web;
    
    namespace Example.Web.Modules
    {
    	//REFs:
    	//
    	//HttpRequest.ClientCertificate Property
    	//https://msdn.microsoft.com/en-us/library/system.web.httprequest.clientcertificate(v=vs.110).aspx
    	//
    	//HttpClientCertificate Class
    	//https://msdn.microsoft.com/en-us/library/system.web.httpclientcertificate(v=vs.110).aspx
    	//
    	//Implementing PKI Authentication 
    	//http://aspnet.wikidot.com/asp-net-webforms:implementing-pki-authentication
    
    	public class HttpClientCertificateAuthenticator : IHttpModule
    	{
    		#region Implementation of IHttpModule
    
    		public void Dispose() { }
    
    		public void Init(HttpApplication context)
    		{
    			context.AuthenticateRequest += OnAuthenticateRequest;
    		}
    
    		#endregion
    
    		internal GenericPrincipal AuthenticateClientCertificate(X509Certificate2 clientCertificate)
    		{
    
    			//Do something more secure, e.g.:
    			//1. Confirm certificate in Active Directory, or
    			//2. Confirm certificate in (Local Machine) Certificate Store, or
    			//3. Confirm certificate in database store
    
    			//We're just matching a particular SHA1 Thumbprint here...
    			if ("e9799e7e...39a1d134".Equals(clientCertificate.Thumbprint.ToLower()))
    			{
    				//TODO: Lookup user details for GenericIdentity.Claims.
    				//TODO: Lookup user roles for GenericPrincipal.Roles
    				var name = clientCertificate.Subject;
    				var identityType = this.GetType().FullName;
    				var identity = new GenericIdentity(name, identityType);
    				var roles = new string[] { "User", "Admin" };
    				var principal = new GenericPrincipal(identity, roles);
    				return principal;
    			}
    			return null;
    		}
    
    		internal GenericPrincipal AuthenticateHttpClientCertificate(HttpClientCertificate httpClientCertificate)
    		{
    			var clientCertificate = new X509Certificate2(httpClientCertificate.Certificate);
    			return AuthenticateClientCertificate(clientCertificate);
    		}
    
    		internal void OnAuthenticateRequest(object sender, EventArgs e)
    		{
    			try
    			{
    				var application = (HttpApplication)sender;
    				var context = application.Context;
    				// This check allows you to chain Authentication IHttpModules together...
    				var isAuthenticated = context.User != null && context.User.Identity.IsAuthenticated;
    				if (!isAuthenticated && context.Request != null)
    				{
    					var clientCert = context.Request.ClientCertificate;
    					if (clientCert != null && clientCert.IsPresent && clientCert.IsValid)
    					{
    						var principal = AuthenticateHttpClientCertificate(clientCert);
    						if (principal != null)
    						{
    							application.Context.User = principal;
    						}
    					}
    				}
    				//IIS will test Context.User.Identity.IsAuthenticated
    			}
    			catch (Exception exception)
    			{
    				const string message = "Internal Server Error";
    				throw new HttpException((int)HttpStatusCode.InternalServerError, message, exception);
    			}
    		}
    
    	}
    }

    Your ASMX methods can directly query HttpContext.Current.User to utilize authentication details, e.g.:
    using System.Security.Principal;
    using System.Web;
    using System.Web.Services;
    
    namespace ExampleService
    {
    	[WebService(Namespace = "http://tempuri.org/")]
    	[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    	[System.ComponentModel.ToolboxItem(false)]
    	public class Service1 : System.Web.Services.WebService
    	{
    		[WebMethod]
    		public string HelloWorld()
    		{
    			var principal = (GenericPrincipal)HttpContext.Current.User;
    			if (principal.Identity.IsAuthenticated)
    			{
    				var name = principal.Identity.Name;
    				return string.Format("Hello, {0}", name);
    			}
    			return "Hello World";
    		}
    	}
    }

    Or you can decorate your methods with custom [WebMethod] attributes that perform the same checks. I'll leave custom WebMethodAttributes to the reader as this part is non-trivial in a web service environment.
    Friday, June 1, 2018 7:27 AM