Tuesday, June 7, 2011

Authenticating Web Services

I find this one to be a bit painful every time I come to it, so it's time to make some notes.

  • You have a web service.
  • You would like to make sure that only people who supply correct credentials can use it.

Here's my approach:

1. Create the Login

In the web server, create a standard windows login and password that will be used for authentication.

2. Create the Security Group

Create a Local Group that the new User is a member of. This group is the name that we will be checking for membership of. That way you can create additional users as required.

3. Set the site up for SSL

This is to ensure that passwords are securely passed.

4. Configure the site's Authentication

Double click the Authentication feature on the site in IIS7. Enable Basic Authentication and Windows Authentication, and disable everything else.

5. Configure the site's Authorization Rules

Double click the Authorization Rules feature on the site in IIS7. Allow All Users and Deny Anonymous Users.

6. Demand the role in your code

In your code, put the PrincipalPermission attribute onto all web methods in order to demand the role that you have created.

In VB.Net, this looks something like this:

<PrincipalPermission(SecurityAction.Demand, Authenticated:=True, Role:="MyRole")> _

7. When calling your service, wrap the client class in another class that provides the correct credentials.

Public Class MyServiceWrapper
Inherits MyServiceNamespace.MyService

Public Sub New()
MyBase.New()

Dim credCache As CredentialCache = New CredentialCache()
Dim netCred As NetworkCredential = New NetworkCredential("MyUserName", "MyPassword")
credCache.Add(New Uri(Url), "Basic", netCred)
Credentials = credCache
End Sub

End Class

8. Try it out - and check for the dreaded 401.1 error

Many times, I've banged my head against the above settings still giving me a 401.1 error. The solution, apparently, is a security issue in Windows which blocks Windows Authentication if the domain name used doesn't match the name of the server (which is about 99.9% of cases).

Here is an article on the problem, but the short answer is to create the DWORD value "DisableLoopbackCheck" in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa and set it to 1.