If your users are in a custom store, consider using username authentication with a custom validator

J.D. Meier, Jason Taylor, Prashant Bansode, Carlos Farre, Madhu Sundararajan, Steve Gregersen.

If you need to use a custom authentication store, consider using user name authentication with a custom username and password validator.

The custom validator is be configured in a service behavior and implemented in a class library. The username and password validator is be used by your service to authenticate your users’ based on your custom user store.

The following configuration snippet shows how to configure a custom validator for your WCF service:
<serviceCredentials>
   <userNameAuthentication  
    userNamePasswordValidationMode="Custom"
   customUserNamePasswordValidatorType="MyUserNamePasswordValidator,Host"/>
</serviceCredentials>

The following code snippet shows how to implement a custom username and password validator:
using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Text;

namespace DerivativesCalculator
{
    public class MyUserNamePasswordValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            Console.Write("\nValidating username, {0}, and password, {1} ... ", userName, password);
            if ((string.Compare(userName, "don", true) != 0) || (string.Compare(password, "hall", false) != 0))
            {
                throw new SecurityTokenException("Unknown user.");
            }
            Console.Write("Done: Credentials accepted. \n");
        }
    }
}

Last edited Apr 24, 2008 at 12:23 AM by prashantbansode, version 2

Comments

rprimrose May 5, 2008 at 12:18 AM 
If you need the password in the identity then see http://neovolve.com/archive/2008/04/07/wcf-security-getting-the-password-of-the-user.aspx for more information.

carlpf2 Apr 25, 2008 at 7:16 PM 
You can take care of this by caching the principal in the authenticator and retrieving from the cache in evaluate from your class that derives from IauthorizationPolicy. If the cache has expired then you will have to create the custom principal from thread currenprincipal or from http. context if you are running asp.net compatible mode. Once you have the principal you assign to the context.

public class Yourclass : IAuthorizationPolicy
{
public bool Evaluate(EvaluationContext context, ref object state)
{
// get the identities list from the context
object obj;
if (!context.Properties.TryGetValue("Identities", out obj))
return false;
IList<IIdentity> identities = obj as IList<IIdentity>;

// make sure there is already a default identity
if (identities == null || identities.Count <= 0)
return false;

string username = identities[0].Name;
IPrincipal = ReturnFromcache(username)
if (principal==null)
}

if (HttpContext.Current == null)
principal= Thread.CurrentPrincipal;
else
principal = HttpContext.Current.User;
}
string username = identities[0].Name;

context.Properties["Principal"] = principal;


identities[0] = principal.Identity;

return true;
}
}
}

chandmk Apr 19, 2008 at 1:51 AM 
I this validator method, I can easily create a Custom Principal object (IPrincipal/IIdentity) with the passed in UserName and Password. I would like to use that Principal as my current thread's principal. In Asp.Net scenario HttpContext takes care of transferring the Principal to all the executing threads. Is there any context in WCF I can use to do the same?