1. Authentication
Authentication is the act of
verifying that the caller of a service is indeed who that caller claims
to be. While authentication is typically referred to in the context of
verification of the caller, from the client perspective there is also a
need for service authentication; that is, assuring the client that the
service it calls really is the service it intends to call. This is
especially important with clients who call over the Internet, because if
a malicious party subverts the client’s DNS service, it could hijack the
client’s calls. WCF offers various authentication mechanisms:
No authentication
-
The service does not authenticate its callers, and virtually
all callers are allowed.
Windows authentication
-
The service typically uses Kerberos when a Windows Domain
Server is available, or NTLM when deployed in a workgroup
configuration. The caller provides the service with its Windows
credentials (such as a ticket or a token) and the service
authenticates that against Windows.
Username and password
-
The caller provides the service with a username and a
password. The service then uses these credentials against some
kind of credentials store, such as Windows accounts or a custom
credentials store (such as a dedicated database).
X509 certificate
-
The client identifies itself using a certificate.
Typically, that certificate is known in advance to the service.
The service looks up the certificate on the host side and
validates it, thus authenticating the client. Alternatively, the
service may implicitly trust the issuer of the certificate and
hence the client presenting it.
Custom mechanism
-
WCF allows developers to replace the built-in authentication
mechanisms with any protocol and credential type, such as using
biometrics.
Issued token
-
The caller and the service can both rely on a secure token
service to issue the client a token that the service recognizes
and trusts. Such a service is typically federated and encapsulates
the act of authenticating and securing the call. Windows CardSpace
is an example of such a secure token service.
2. Authorization
Authorization is concerned with what
the caller is allowed to do: typically, which operations the client is
allowed to invoke on the service. Authorizing of the caller is done
under the assumption that the caller is indeed who the caller claims to
be—in other words, authorization is meaningless without authentication.
For authorization, the service typically relies on some kind of
credentials store, where callers are mapped to logical roles. When
authorizing an operation, the operation declares or explicitly demands
that only certain roles can access it, and the service needs to look up
the caller’s role or roles from the store and verify that the caller is
a member of the requested roles. Out of the box, WCF supports two
credentials stores: the service can use Windows groups (and accounts)
for authorization, or it can use an ASP.NET provider (such as the SQL
Server provider) to store user accounts and roles. WCF also supports
custom role repositories, but I have found that the easiest option by
far for implementing a custom store is to implement a custom ASP.NET provider.
Note:
WCF offers an elaborate and extensible infrastructure for
authenticating and authorizing the caller based on a set of claims
contained in the message.
3. Transfer Security
Both authentication and authorization deal with two local
aspects of security—if (and to what extent) to grant access to the
caller once the service has received the message. In this respect, WCF
services are not much different from traditional client/server classes.
However, both authentication and authorization are predicated on secure
delivery of the message itself. The transfer of the
message from the client to the service has to be secure, or both
authentication and authorization are moot. There are three essential
aspects to transfer security, and all three aspects must be enforced to
provide for secure services. Message integrity
deals with how to ensure that the message itself is not tampered with en
route from the client to the service. A malicious party or intermediary
could, in practice, intercept the message and modify its content; for
example, altering the account numbers in the case of a transfer
operation in a banking service. Message privacy
deals with ensuring the confidentiality of the message, so that no third
party can even read the contents of the message. Privacy complements
integrity. Without it, even if the malicious party does not tamper with
the message, that party can still cause harm by gleaning sensitive
information (again, such as account numbers) from the message content.
Finally, transfer security must provide for mutual authentication, which deals
with assuring the client that only the proper service is able to read
the content of its message—in other words, that the client connects to
the correct service. Once the credentials in the message are received,
the service must authenticate those credentials locally. The mutual
authentication mechanism also needs to detect and eliminate replay
attacks and denial of service (DOS) attacks. In a replay attack, a
malicious party records a valid message from the wire and later sends
that valid message back to the service. With a DOS attack, a malicious
party floods the service with messages (either valid messages or bogus
invalid messages) at such a frequency as to degrade the service’s
availability.
3.1. Transfer Security Modes
WCF supports five different ways of accomplishing the three
aspects of transfer security. Choosing the correct transfer security
mode is perhaps the prime decision to be made in the context of
securing a service. The five transfer security modes are None,
Transport security, Message security, Mixed, and Both.
3.1.1. None transfer security mode
As its name implies, the None transfer
security mode has transfer security completely turned off—in fact,
all aspects of WCF security are turned off. No client credentials
are provided to the service, and the message itself is wide open to
any malicious party to do with it as it pleases. Obviously, setting
transfer security to None is highly inadvisable.
3.1.2. Transport transfer security mode
When configured for Transport security,
WCF uses a secure communication protocol. The available secure
transports are HTTPS, TCP, IPC, and MSMQ. Transport security encrypts all communication on
the channel and thus provides for integrity, privacy, and mutual
authentication. Integrity is provided because without knowing the
encryption key, any attempt to modify the message will corrupt it so
that it will become useless. Privacy is provided because no party
other than the recipient can see the content of the message. Mutual
authentication is supported because only the intended recipient of
the message can read it; the client need not be concerned with
message rerouting to malicious endpoints, as those will not be able
to use the message. Once the message is decrypted, the service can
read the client’s credentials and authenticate the client.
Transport security requires the client and the service to
negotiate the details of the encryption, but that is done
automatically as part of the communication protocol in the
respective binding. Transport security can benefit from hardware
acceleration done on the network card so as to avoid burdening the
host machine’s CPU with the encryption and decryption of the
messages. Hardware acceleration obviously caters to high throughput,
and it may even make the security overhead unnoticeable. Transport
security is the simplest way of achieving transfer security, and the
most performant option. Its main downside is that it can only
guarantee transfer security point-to-point, meaning when the client
connects directly to the service. Having multiple intermediaries
between the client and the service renders Transport security
questionable, as those intermediaries may not be secure.
Consequently, Transport security is typically used only by intranet
applications, where you can ensure a single hop between the client
and the service in a controlled environment.
Note:
When configuring any of the HTTP bindings for Transport
security, WCF verifies at the service load time that the
corresponding address on the endpoint uses HTTPS rather than mere
HTTP.
3.1.3. Message transfer security mode
The Message transfer security mode simply
encrypts the message itself. By encrypting the message, you gain
integrity and privacy and enable mutual authentication, for the same
reason that Transport security provides these features when the
communication channel is encrypted. However, encrypting the message
rather than the transport enables the service to communicate
securely over nonsecure transports, such as HTTP. Because of that,
Message security provides for end-to-end security, regardless of the
number of intermediaries involved in transferring the message and
regardless of whether or not the transport is secure. In addition,
Message security is based on a set of industry standards designed
both for interoperability and for thwarting common attacks such as
replay and DOS attacks, and the support WCF offers for it is both
rich and extensible. The downside of Message security is that it may
introduce call latency due to its inherent overhead. Message
security is typically used by Internet applications, where the call
patterns are less chatty and the transport is not necessarily
secure.
3.1.4. Mixed transfer security mode
The Mixed transfer security mode uses
Transport security for message integrity and privacy as well as
service authentication, and it uses Message security for securing
the client’s credentials. The Mixed mode tries to combine the
advantages of both Transport and Message security by benefiting from
the secure transport and even hardware acceleration offered by Transport
security to cater to high throughput, and from the extensibility and richer types of
client credentials offered by Message security. The downside of the
Mixed mode is that it is only secure point-to-point, as a result of
the use of Transport security. Application developers rarely need to
use the Mixed mode, but it is available for advanced cases.
3.1.5. Both transfer security mode
As its name implies, the Both transfer
security mode uses both Transport security and Message security. The
message itself is secured using Message security, and then it is
transferred to the service over a secure transport. The Both mode
maximizes security, yet it may be overkill for most applications
(with the exception perhaps of disconnected applications, where the
additional latency it introduces will go unnoticed).
3.2. Transfer Security Mode Configuration
Configuring the transfer security mode is done in the binding,
and both the client and the service must use the same transfer
security mode and, of course, comply with its requirements. Like any
other binding configuration, you can configure transfer security
either programmatically or administratively, in a config file. All the
common bindings offer a construction parameter indicating the transfer
security mode, and all bindings offer a Security property with a Mode property identifying the configured
mode using a dedicated enumeration. As shown in Table 1, not all bindings
support all transfer security modes: the supported modes are driven by
the target scenarios for the binding.
Table 1. Bindings and transfer security modes
Name | None | Transport | Message | Mixed | Both |
---|
BasicHttpBinding | Yes
(default) | Yes | Yes | Yes | No |
NetTcpBinding | Yes | Yes
(default) | Yes | Yes | No |
NetNamedPipeBinding | Yes | Yes
(default) | No | No | No |
WSHttpBinding | Yes | Yes | Yes
(default) | Yes | No |
NetMsmqBinding | Yes | Yes
(default) | Yes | No | Yes |
The intranet bindings (NetTcpBinding,
NetNamedPipeBinding,
and NetMsmqBinding) all
default to Transport security. Thus, no special programming is
required on behalf of the service or client developer. The reason is
that on the intranet calls are typically point-to-point, and Transport
security yields the best performance. However, the intranet bindings
can also be configured for the None transfer mode; that is, they can
be used on the same transport protocol, only without security. The
NetNamedPipeBinding supports only
None and Transport security—there is no sense in using Message
security over IPC, since with IPC there is always exactly one hop from
the client to the service. Also note that only the NetMsmqBinding supports the Both
mode.
The Internet bindings all default to Message security, to enable
them to be used over nonsecure transports (that is, HTTP) and to
accommodate multiple hops and intermediaries.
With one noticeable exception, all of the WCF bindings are
configured with some kind of transfer security and are therefore
secure by default. Only the BasicHttpBinding
defaults to having no security. The reason is that the basic binding
is designed to make a WCF service look like a legacy ASMX service, and
ASMX is unsecured by default. That said, you can and should configure
the BasicHttpBinding to use a
different transfer security mode, such as Message security.
3.2.1. Specific binding configurations
The BasicHttpBinding uses
the BasicHttpSecurityMode enum
for transfer mode configuration. The enum is available via the
Mode property of the Security property of the binding:
public enum BasicHttpSecurityMode
{
None,
Transport,
Message,
TransportWithMessageCredential,
TransportCredentialOnly
}
public sealed class BasicHttpSecurity
{
public BasicHttpSecurityMode Mode
{get;set;}
//More members
}
public class BasicHttpBinding : Binding,...
{
public BasicHttpBinding();
public BasicHttpBinding(BasicHttpSecurityMode securityMode);
public BasicHttpSecurity Security
{get;}
//More members
}
Security is of the type BasicHttpSecurity. One of the constructors
of BasicHttpBinding takes the
BasicHttpSecurityMode enum as a
parameter. To secure the basic binding for Message security, you can
either construct it secured or set the security mode
post-construction. Consequently, in Example 1, binding1 and binding2 are equivalent.
Example 1. Programmatically securing the basic binding
BasicHttpBinding binding1 = new BasicHttpBinding(BasicHttpSecurityMode.Message);
BasicHttpBinding binding2 = new BasicHttpBinding(); binding2.Security.Mode = BasicHttpSecurityMode.Message;
|
Instead of programmatic settings, you can use a config file,
as in Example 2.
Example 2. Administratively securing the basic binding
<bindings> <basicHttpBinding> <binding name = "SecuredBasic"> <security mode = "Message"/> </binding> </basicHttpBinding> </bindings>
|
The rest of the bindings all use their own enumerations and
dedicated security classes, yet they are configured just as in Example 1 and Example 2. For example,
the NetTcpBinding and the
WSHttpBinding use the SecurityMode enum, defined as:
public enum SecurityMode
{
None,
Transport,
Message,
TransportWithMessageCredential //Mixed
}
These bindings offer a matching construction parameter and a
matching Security
property.
The NetNamedPipeBinding
uses the NetNamedPipeSecurityMode
enum, which supports only the None and Transport security
modes:
public enum NetNamedPipeSecurityMode
{
None,
Transport
}
The NetMsmqBinding uses the
NetMsmqSecurityMode enum:
public enum NetMsmqSecurityMode
{
None,
Transport,
Message,
Both
}
NetMsmqSecurityMode is the
only enum that offers the Both transfer mode.
The reason that almost every common binding has its own
dedicated enum for the security mode is that the designers of WCF
security opted for increased safety at the expense of overall complexity.
They could have defined just a single all-inclusive enum with values
corresponding to the five possible transfer security modes, but then
it would have been possible at compile time to assign invalid
values, such as Message security for the NetNamedPipeBinding. Opting for
specialized enums makes configuring security less error-prone, yet
there are more moving parts to come to terms with.
3.3. Transport Security and Credentials
WCF lets you select from a number of possible client
credential types. For example, the client can identify itself using a
classic username and password, or a Windows security token. Windows
credentials can then be authenticated using NTLM or Kerberos, when
available. Alternatively, the client can use an X509 certificate, or choose to provide no credentials at
all and be anonymous. When configuring transfer security for Transport
security, however, not all bindings support all client credential
types, as shown in Table 2.
Table 2. Bindings and Transport security client credentials
Name | None | Windows | Username | Certificate |
---|
BasicHttpBinding | Yes
(default) | Yes | Yes | Yes |
NetTcpBinding | Yes | Yes
(default) | No | Yes |
NetNamedPipeBinding | No | Yes
(default) | No | No |
WSHttpBinding | Yes | Yes
(default) | Yes | Yes |
NetMsmqBinding | Yes | Yes
(default) | No | Yes |
Which types of credentials a binding supports is largely a
product of the target scenario for which the binding is designed. For
example, all of the intranet bindings default to Windows credentials
since they are used in a Windows environment, and the BasicHttpBinding defaults to no credentials,
just like a classic ASMX web service. The odd default is that of the
WSHttpBinding, which defaults to
Windows credentials to enable the binding to be used over Transport
security with minimum effort out of the box.
3.4. Message Security and Credentials
When it comes to using Message transfer security, WCF
lets applications use the same types of credentials as with Transport
security, with the addition of the issued token credential type.
Again, when configured for Message security not all bindings support
all client credential types, as shown in Table 3.
Table 3. Bindings and Message security client credentials
Name | None | Windows | Username | Certificate | Issued
token |
---|
BasicHttpBinding | No | No | No | Yes | No |
NetTcpBinding | Yes | Yes
(default) | Yes | Yes | Yes |
NetNamedPipeBinding | N/A | N/A | N/A | N/A | N/A |
WSHttpBinding | Yes | Yes
(default) | Yes | Yes | Yes |
NetMsmqBinding | Yes | Yes
(default) | Yes | Yes | Yes |
While it makes sense that all intranet bindings that support
Message security default to Windows credentials, it is interesting to
note that the WSHttpBinding as
Internet binding also defaults to Windows credentials, even though (as
discussed later) Internet applications rarely use Windows credentials
over HTTP. The reason for this default is to enable developers to
securely use the WS binding out of the box, in its correct transfer
security mode without resorting first to custom credentials
stores.
Warning:
The BasicHttpBinding
supports username client credentials for Message security only when
configured for Mixed mode. This may be a source of runtime
validation errors, since the BasicHttpMessageCredentialType enum
contains the BasicHttpMessageCredentialType.UserName
value.