views:

1256

answers:

6

I have a C# .net webservice that I need to restrict access to. I already require my consumers to use a username and password to call the service. But, is there a way to restrict access to the actual asmx page and the WSDL? I would need to restrict access to the webservice by username/password and IP address. If a user did not have the correct credentials, I would not want them to know what webmethods exist in the webservice.

Can this be done though IIS? I know that I can restrict IP addresses through IIS, but can I also use usernames/passwords?

Is there any other way to do this outside of IIS, maybe using C#.net?

A: 

You can stop WSDL being shown by removing the Documentation protocol from the element in Machine.config

Update: http://stackoverflow.com/questions/162376/web-services-authentication-best-practices If your users have usernames/passwords you can use HTTP basic authentication via HTTPS.

You can also implement it in a slightly differnt way. The first call to your web service should be the authentication method. Client authenticates and receives an authentication token. This token should be presented to all other methods exposed by your web service.

DmitryK
But if I did that then no one would be able to see the WSDL.
Jon
True. But this might be a good thing depending whether you need your legitimate users to see WSDL or not.
DmitryK
How do I remove the Documentation from an asmx based web service?
flalar
Adding <remove name="Documentation"/> to the <system.web> <webservices><protocols> did the trickSe the link below for more optionshttp://msdn.microsoft.com/en-us/library/4yx7be39(VS.71).aspx
flalar
A: 

Will http://www.iistools.com/en/iispassword.html help?

queen3
-1: Please provide more than a link. Say what the product does, give an example of protecting the ASMX from users without the password, show how a user who has the password can access it. Then I'll remove the -1.
John Saunders
+1  A: 

I don't know how practical this is for you, but you could consider upgrading to WCF. WCF is fully backward compatible with ASMX web services, and lets you control whether or not the WSDL is exposed by defining a MEX (metadata exchange) endpoint. No MEX endpoint, no WSDL.

Christian Hayter
I wish I could upgrade... But unfortunately, that is just not an option right now.
Jon
A: 

Two options: Create an entirely different site on a different port with locked down permissions. This has the advantage of providing some amount of "security through obscurity" (half joking...) Or you can add a new Application under your site(same port, different path), on a different app pool and assign permissions that way.

In either case, your web service isn't going to be able to talk with the various ASP.NET "things" like the application object (well it will, but it won't be the same one). Deployment is only slightly harder: deploy the same binaries, but only include the one web service file.

popester
A: 

You can authenticate using an HttpModule. SSL + BasicAuthentication should yield the best interop with other tool chains.

In the HttpModule, you have access to the request and can deny unauthenticated users access to just .asmx requests. And even then you might let them access the WSDL.

Robert Giesecke
Could you give me a little more info on this? Maybe an example of how to do this? It sounds promising..
Jon
Sure, but atm, I am nowhere near a machine with VS on it until monday.It is pretty straight forward, but I don't have all of it available in my head. *g*
Robert Giesecke
+8  A: 

Well, since it's ASMX you have the entire ASP.NET runtime stack at your disposal.

Step #1 - managing the resource through .config

Apply a <location> tag for the resources you want secured. Assuming it's a single ASMX file you can simply do the following in your web.config:

<location path="MyWebService.asmx">
    <sytem.web>
        <!-- resource specific options will go here -->
    </system.web>
</location>

Step #2 - authenticating your users

You need to decide how you're actually going to authenticate users. There are several ways to do this and several authentication standards you could leverage. You need to pick the approach that's the right fit for you.

If you're on an intranet and are using Windows authentication I would highly suggest leveraging that because it's truly the simplest option to get setup. However, if your services are being accessed over the internet then Windows authenticatio is not really an option and you need to choose from a web standard. The simplest of those is Basic Authentication, but you should only use this over SSL since the username/password are not encrypted (only base64 encoded). The next step up from that is Digest authentication which doesn't require SSL because the username/password are sent using an MD5 hash. For the ultimate you can go with SSL v3 where you issue a specific client certificate to each user of your API.

Now, which option you select for security dictates what else needs to be done. If you choose Windows security, it's as easy as adding the following element to the <system.web> element we started with in Step #1:

<authentication mode="Windows" />

The remainder of the security protocols are going to require a little more work. ASP.NET doesn't provide intrinsic support for Basic, Digest or SSL v3. Technically you can leverage IIS to do this type of authentication for you, but it's always going to map to a Windows user. If that's an option for you, then simply leave the <authentication mode="Windows" /> element and configure IIS accordingly. If, however, that is not an option, either because you simply have no control over IIS/ActiveDirectory or you need to authenticate against a custom user database, then that means that you need to hook up a custom HttpModule to provide support for these security protocols.

Step #3 - securing the resource

The simplest approach to securing the resource is to basically say: "don't let anyone who hasn't successfully authenticated in some way into this resource". This is done using the following authorization configuration:

<authorization>
    <deny users="?" />
</authorization>

If you wanted to only allow certain users you could change to do the following instead:

<authorization>
    <deny users="*" />
    <allow users="jdoe, msmith" />
</authorization>

Another approach is to define roles (groups) and simply lock the resource down to a special role which you put the users who you want to access the resource into.

<authorization>
    <deny users="*" />
    <allow roles="My Service Users" />
</authorization>

This maps well to Windows authentication because you can just setup a Windows group and let your MIS team manage which users are in that group using ActiveDirectory. However, the feature also works just fine for non-Windows authentication assuming the security implementation you've used exposes roles via its IPrincipal implementation.

Drew Marsh