Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populating the PrimaryIdentity in WCF

Tags:

.net

security

wcf

I'm using simple HTTP headers to pass a token to a WCF service for authentication (The WCF service is required to use the basicHTTPBinding, so I unfortunately cannot use the canned ws-security implementation). I would like to populate the PrimaryIdentity object so the WCF services can examine it to determine the authenticated user.

The issue is that the OperationContext.Current.ServiceSecurityContext.PrimaryIdentity property is read-only at the time I'm trying to populate it. I've tried using SecurityTokenAuthenticators and IAuthorizationPolicy objects to set the identity info, but that route seems to require the use of message-level security (such as always sending in a username and password), which isn't what I want.

Can anyone shed light on how I could set the PrimaryIdentity field?

like image 242
Will Avatar asked Nov 29 '22 18:11

Will


2 Answers

You can create a class that implments IAuthorizationPolicy. WCF parses all the identity tokens (X509, WS-Security Username/pass, etc.) and puts them in the evaluationContext.Properties["Identities"] which you get in the Evaluate function. This will return a List to you. If you replace this list with a list containing your own class that implements IIdentity then WCF will read that into ServiceSecurityContext.Current.PrimaryIdentity. please ensure that the list only contains one item otherwise you will confuse WCF and PrimaryIdentity.Name will be the empty string.

var myIdentity = new MyIdentity("MyId", otherstuff);
evaluationContext.Properties["Identities"] = new List<IIdentity> {myIdentity};

Also, you may want to process/read any of the tokens before you replace them.

var identities = evaluationContext.Properties.ContainsKey("Identities")
                                 ? (List<IIdentity>) evaluationContext.Properties["Identities"]
                                 : new List<IIdentity>();

var genericIdentity = identities.Find(x => x.AuthenticationType == "MyUserNamePasswordValidator");

genericIdentity.Name --> contains the username from WSS username token.

You would need a UsernamePasswordValidator (http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.usernamepasswordvalidator.aspx) if you are using WS-Security Username token and do not want any default WCF validation. Since, we have a DataPower device that validates the token before the message gets to our service, we don't need to validate the username and password. In our case it just returns true.

like image 179
Nabheet Avatar answered Dec 02 '22 06:12

Nabheet


PrimaryIdentity is not intended to be populated by you - it's the WCF runtime's job to determine who's calling, and set the PrimaryIdentity accordingly.

So if you're calling with Windows credentials, then you'll get a WindowsIdentity stored there; if you're using ASP.NET membership providers, you'll get that caller stored into the PrimaryIdentity.

The only way you could actually set this is by creating your own custom server-side authentication mechanism and plug that into WCF.

See:

  • WCF Authentication Service Overview
  • Fundamentals of WCF Security - Authentication, Authorization, Identities
  • WCF Custom Authentication and Impersonation
like image 23
marc_s Avatar answered Dec 02 '22 06:12

marc_s