Marc Wittke
Marc Wittke

Reputation: 3154

How to call a WCF service from a unit test as an anonymous identity?

I've a SecurityService that has a AutoLogin method, that uses the ServiceSecurityContext to find out which windows identity is calling and then tries to find the related user account in the database. This is working fine when it is called from a web site that uses impersonation and requires integrated security in IIS. The call is using the stock NetPipeBinding.

I'd like to test the service as follows:

[TestMethod]
public void AutoLoginAsAnonymousFails()
{
    using (var anonymousContext = WindowsIdentity.Impersonate(WindowsIdentity.GetAnonymous().Token))
    {
        ISecurityService securityService = ClientChannelManager.CreateSecurityServiceChannel();
        var loginResponse = securityService.AutoLogin();
        ((ICommunicationObject)securityService).Close();
        Assert.IsFalse(loginResponse.IsSuccessful);             
    }
}

On the service side the user in the securitycontext is always me - how to make it an anonymous user? I've already tried to impersonate the IntPtr.Zero but without success.

For reference the relevant part of the service method:

public ResponseMessage AutoLogin()
{
    if (ServiceSecurityContext.Current.WindowsIdentity != null
        && !ServiceSecurityContext.Current.WindowsIdentity.IsAnonymous
        && !ServiceSecurityContext.Current.WindowsIdentity.IsGuest
        && ServiceSecurityContext.Current.WindowsIdentity.IsAuthenticated)
    {
        // find the user based on his windows identity and return success = true message
    }

    // return success = false message
}

Upvotes: 1

Views: 2033

Answers (1)

Mark Seemann
Mark Seemann

Reputation: 233125

This is a classic example of how separation of concerns could help you. Instead of relying directly on ServiceSecurityContext (something that one should, IMO, never do), make sure to configure your service so that security information is instead encapsulated in Thread.CurrentPrincipal.

IIRC, when you use Windows authentication and impersonation, it may even set this up for you automatically, but otherwise, you can always write a custom ServiceAuthorizationManager, that does this for you.

This will allow you to vary your security concerns independently of your domain logic. If you stick with the IPrincipal interface and resist the temptation of downcasting to WindowsPrincipal, your code will even be ready for the future of identity: Claims-based Identity, as implemented by the Windows Identity Foundation (WIF).

This also helps tremenduously with unit testing, because you can then just assign a GenericPrincipal to Thread.CurrentPrincipal before invoking your System Under Test (SUT).

Upvotes: 2

Related Questions