WCF Security
Security Modes
- Transport- eg SSL. basicHttpBinding is the only binding with no default security (to enable, configure the binding with security mode="Transport".). You also can't do transport security with wsDualHttpBinding (callback listeners).
- Message- eg WS-Security <security mode="Message">
message clientCredentialType="Windows" or "Certificate" or UserName ... - Transport with message credential - both, but it's not end-to-end security like Message
If using transport security, you can only use Certificate or Windows credential type. behavior/serviceCredentials configure where to find authentication (eg certificate)
Contexts
Like Asp.Net's HttpContext, WCF has OperationContext and also ServiceSecurityContext which works the same way for just security stuff.
//For windows authentication access the current user by
var name1 = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name;
//or
var name2 = ServiceSecurityContext.Current.PrimaryIdentity.Name;
In a json webHttp endpoint with [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] you can use HttpContext.Current.User.Identity.Name as normal.
Impersonation
You can use the securitycontext for impersonation (MSDN) ServiceSecurityContext.Current.Windowsldentity.ImpersonationLevel = TokenlmpersonationLevel.Impersonation (or to access remote systems) .Delegation
You can impersonate some operations (Allowed or Required) using the ServiceAuthorization behavior ImpersonateCallerForAllOperations=true
Custom authentication
For custom authentication, set the credentialType="UserName", and create a class that inherits from UserNamePasswordValidator (Validate doesn't return boolean- throw a SecurityTokenValidationException) For authorization, you can use OperationContext.Current.ServiceSecurityContext - you can get claimSets.
There's an IAuthorizationPolicy interface for custom authentication (reference System.IdentityModel). Implement the Evaluate method and assign a readonly list<IAuthorizationPolicy>
to host.Authorization.ExternalAuthorizationPolicies or in config <serviceAuthorization>
<authorizationPolicies>
<add policyType=""/>
Use ASP Membership with WCF
<serviceCredentials> has a <userNameAuthentication> element- set userNamePasswordValidationMode="MembershipProvider" for ASP.Net membership instead of windows.
Or use <serviceAuthorization
principalPermissionMode="UseAspNetRoles"
roleProviderName ="SqlProvider" />
Certificates
serviceCredentials has a clientCertificate and serviceCertificate.
clientCertificate/serviceCredentials/authentication has a certificateValidationMode can be Custom (a customCertificateValidatorType), ChainTrust (chain to root certificates) or PeerTrust (self-issued in Trusted People store).
ProtectionLevel
In code you can set ProtectionLevel [OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)] (if you're using Transport security, this has no effect; you can't use it with BasicHttpBinding as that has no default security)
Debugging Security
Add the serviceSecurityAudit element to the server, and check the audit log:
<serviceBehaviors>
<behavior name="defaultBehavior">
<serviceSecurityAudit
auditLogLocation="Application"
serviceAuthorizationAuditLevel="Failure"
messageAuthenticationAuditLevel="Failure" />
</behavior>
</serviceBehaviors>