4

I have a WCF service that is using a custom ServiceAuthorizationManager. The custom auth manager is already set up to handle Windows and Forms authentication.

However, if I connect with a client that is set to UserName auth, I can't seem to find the username anywhere.

The client code looks like this:

this.ClientCredentials.UserName.UserName = "user";
this.ClientCredentials.UserName.Password = "pass";
this.Open();
this.MyMethod(); // my actual contract method
this.Close();

Then on the server, I have my custom auth manager:

public sealed class AppAuthorizationManager : ServiceAuthorizationManager
{
    public override bool CheckAccess(OperationContext operationContext, ref Message message)
    {
        // would like to check user/pwd here...
    }
}

Is this possible?

  • The Thread.CurrentPrincipal is not set,
  • operationContext.ServiceSecurityContext.PrimaryIdentity is not set.
  • operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets is empty.

Is the user/pwd supposed to be available anywhere? Or do I have to add a custom UsernamePasswordValidator too?


Update: So I added a custom UserNamePasswordValidator and an IAuthorizationPolicy. My updated WCF config looks like this:

<behavior name="Server2ServerBehavior">
  <serviceMetadata httpGetEnabled="true" />
  <serviceDebug includeExceptionDetailInFaults="true" />
  <serviceAuthorization principalPermissionMode="Custom" serviceAuthorizationManagerType="MyApp.AuthManager, MyApp">
    <authorizationPolicies>
      <add policyType="MyApp.TokenAuthorizationPolicy, MyApp" />
    </authorizationPolicies>
  </serviceAuthorization>
  <serviceCredentials>
    <userNameAuthentication customUserNamePasswordValidatorType="MyApp.PFUserNameValidator, MyApp" />
  </serviceCredentials>
</behavior>

If I set a breakpoint in all 3 of those classes, WCF throws the exception:

LogonUser failed for the 'username' user. Ensure that the user has a valid Windows account.
   at System.IdentityModel.Selectors.WindowsUserNameSecurityTokenAuthenticator.ValidateUserNamePasswordCore(String userName, String password)

Before any of them are run. Hmmm...

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
CodingWithSpike
  • 42,906
  • 18
  • 101
  • 138

1 Answers1

6

This is normally handled in the UsernamePasswordValidator - which is the only place you'll have access to the password. However, this isn't where you set the principal - that would be in the IAuthorizationPolicy's Evaluate method, which might look something like:

bool IAuthorizationPolicy.Evaluate(
    EvaluationContext evaluationContext, ref object state)
{           
    IList<IIdentity> idents;
    object identsObject;
    if (evaluationContext.Properties.TryGetValue(
        "Identities", out identsObject) && (idents =
        identsObject as IList<IIdentity>) != null)
    {
        foreach (IIdentity ident in idents)
        {
            if (ident.IsAuthenticated &&
                ident.AuthenticationType == TrustedAuthType)
            {                           
                evaluationContext.Properties["Principal"]
                    = //TODO our principal
                return true;
            }
        }
    }
    if (!evaluationContext.Properties.ContainsKey("Principal"))
    {
        evaluationContext.Properties["Principal"] = //TODO anon
    }                
    return false;
}

(where TrustedAuthType is the name of our password validator)

With this in place, the thread's principal will be set, and we can identify ourselves (and use roles-based security etc)

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks! For anyone who may need it later on, here is how to add a custom AuthorizationPolicy: http://msdn.microsoft.com/en-us/library/ms729794.aspx – CodingWithSpike Feb 09 '09 at 21:00
  • What could be the problem if the "Identities" is null? I'm having a "custom" principalPermissionMode too and an AuthorizationPolicy just like you have in your example – Juri Oct 26 '10 at 07:39
  • @Juri - then it sounds like they are anonymous... beyond that, hard to answer. – Marc Gravell Oct 26 '10 at 08:10
  • 2
    I solved the "Identities" problem, was an issue that locally on my workstation it didn't work properly. However, the problem I got afterwards was that I had to impersonate my identity which was not possibly at the stage of custom authorization policies. Therefore I went this approach which I documented in my blog post (if someone happens to have the same problem): http://blog.js-development.com/2010/11/intercepting-wcf-operation-calls-with.html – Juri Dec 03 '10 at 10:44
  • Could you please take a look at this:https://stackoverflow.com/questions/45770217/my-customauthorizationpolicy-evaluate-method-never-fires – Ehsan Akbar Aug 21 '17 at 07:42