The characteristics of the intranet application are that
both the clients and the service use WCF, and that they are deployed in
the same intranet. The clients reside behind the firewall, and you can
use Windows-based security for transfer security, authentication, and
authorization. You can rely on Windows accounts and groups to store the
client’s credentials. The intranet scenario addresses a wide range of
business applications, from finance to manufacturing to in-house IT
applications. The intranet scenario is also the richest scenario of all
in the options it offers developers for configuring security.
This section on the intranet scenario will define the terminology,
techniques, and types used in the other scenarios.
1. Securing the Intranet Bindings
For the intranet scenario, you should use the intranet
bindings: namely, NetTcpBinding, NetNamedPipeBinding, and NetMsmqBinding. You can rely on Transport
mode for transfer security because the calls are invariably
point-to-point. Conveniently, Transport security is the default
transfer mode of the intranet bindings (see Table 1). You can also use
the default for the client credentials type, which is Windows (see
Table 2). You need
to configure this on both the client and the service.
1.1. Transport security protection level
Each of the three intranet bindings has a configurable
protection level, which is the master switch for Transport
protection. The three protection levels are:
None
-
When configured for this protection level, WCF does not
protect the message on transfer from the client to the
service. Any malicious party can read the content of the
message, or even alter it.
Signed
-
When configured for this protection level, WCF ensures
that the message could have come only from an authenticated
sender and that the message integrity was not compromised
during transfer. To accomplish this, WCF appends an encrypted
checksum to the message. Upon receiving the message, the
service calculates the checksum and compares it to the
original. If the two do not match, the message is rejected. As
a result, the message is impervious to tampering. However, the
message content is still visible during the transfer.
Encrypted and Signed
-
When configured for this protection level, WCF both
signs the message and encrypts its content. The Encrypted and
Signed protection level provides integrity, privacy, and
authenticity.
The Signed protection level offers a clear trade-off between a
measured degree of security and performance. However, I consider
this to be a trade-off to avoid, and I recommend that you always opt
instead for the Encrypted and Signed protection level. WCF
represents the protection level with the ProtectionLevel enum, defined as:
public enum ProtectionLevel
{
None,
Sign,
EncryptAndSign
}
Not all Internet bindings default to the same protection
level. Both the NetTcpBinding
and the NetNamedPipeBinding default to Encrypted
and Signed, yet the NetMsmqBinding defaults to Signed.
1.2. NetTcpBinding configuration
NetTcpBinding takes
a construction parameter indicating the desired transfer security
mode:
public class NetTcpBinding : ...
{
public NetTcpBinding(SecurityMode securityMode);
public NetTcpSecurity Security
{get;}
//More members
}
The Security property of
the type NetTcpSecurity contains
the transfer mode (Transport or Message) and two respective
properties with their specific settings:
public sealed class NetTcpSecurity
{
public SecurityMode Mode
{get;set;}
public MessageSecurityOverTcp Message
{get;}
public TcpTransportSecurity Transport
{get;}
}
In the intranet security scenario, you should select Transport
security for the transfer security mode and set the values of the
Transport property of the type
TcpTransportSecurity:
public sealed class TcpTransportSecurity
{
public TcpClientCredentialType ClientCredentialType
{get;set;}
public ProtectionLevel ProtectionLevel
{get;set;}
}
The Transfer property
should be initialized with the client credential type set to Windows
using the TcpClientCredentialType
enum, defined as:
public enum TcpClientCredentialType
{
None,
Windows,
Certificate
}
The Transport property should also have the
protection level set to ProtectionLevel.EncryptAndSign. Since both of
those settings are the defaults for this binding, these two
declarations are equivalent:
NetTcpBinding binding1 = new NetTcpBinding();
NetTcpBinding binding2 = new NetTcpBinding(SecurityMode.Transport);
binding2.Security.Transport.ClientCredentialType =
TcpClientCredentialType.Windows;
binding2.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
Alternatively, you can configure the binding using a config
file:
<bindings>
<netTcpBinding>
<binding name = "TCPWindowsSecurity">
<security mode = "Transport">
<transport
clientCredentialType = "Windows"
protectionLevel = "EncryptAndSign"
/>
</security>
</binding>
</netTcpBinding>
</bindings>
Note:
The NetTcpContextBinding
and the WSHttpContextBinding
also offer the ContextProtectionLevel property of the
type ProtectionLevel, used to
indicate the desired protection level for the custom context.
ContextProtectionLevel defaults to ProtectionLevel.Sign. When using
Transport security, the value of ContextProtectionLevel
is ignored (since
the transport protects the whole message during transfer). Due to
a bug in WCF, it is also ignored when using Message security.
For the sake of completeness, although it’s not required by
the intranet scenario, here is how to configure NetTcpBinding for Message security with
username client credentials:
public enum MessageCredentialType
{
None,
Windows,
UserName,
Certificate,
IssuedToken
}
public sealed class MessageSecurityOverTcp
{
public MessageCredentialType ClientCredentialType
{get;set;}
//More members
}
NetTcpBinding binding = new NetTcpBinding(SecurityMode.Message);
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
NetTcpSecurity offers the
Message property of the type
MessageSecurityOverTcp. You’ll
need to set the credentials type using the MessageCredentialType enum. Most bindings
use the MessageCredentialType
enum for representing Message security client credentials.
Figure 1 shows the
security-related elements of the NetTcpBinding.
NetTcpBinding has a
reference to NetTcpSecurity,
which uses the SecurityMode enum
to indicate the transfer security mode. When Transport security is
used, NetTcpSecurity will use an
instance of TcpTransportSecurity
containing the client credentials type via the TcpClientCredentialType enum and the
configured protection level via the ProtectionLevel enum. When Message security is
used, NetTcpSecurity will use an
instance of MessageSecurityOverTcp containing the
client credentials type via the MessageCredentialType enum.
1.3. NetNamedPipeBinding configuration
NetNamedPipeBinding
takes a construction parameter indicating the desired transfer
security mode:
public class NetNamedPipeBinding : Binding,...
{
public NetNamedPipeBinding(NetNamedPipeSecurityMode securityMode);
public NetNamedPipeSecurity Security
{get;}
//More members
}
The Security property of the type NetNamedPipeSecurity contains the transfer
mode (Transport or None) and a single property with the specific
Transport settings:
public sealed class NetNamedPipeSecurity
{
public NetNamedPipeSecurityMode Mode
{get;set;}
public NamedPipeTransportSecurity Transport
{get;}
}
For the intranet security scenario, select Transport security
for the transfer security mode and set
the values of the Transport
property of the type NamedPipeTransportSecurity:
public sealed class NamedPipeTransportSecurity
{
public ProtectionLevel ProtectionLevel
{get;set;}
}
The Transfer property
should be initialized with the protection level set to ProtectionLevel.EncryptAndSign. Because
this is the default for the binding, these two declarations are
equivalent:
NetNamedPipeBinding binding1 = new NetNamedPipeBinding();
NetNamedPipeBinding binding2 = new NetNamedPipeBinding(
NetNamedPipeSecurityMode.Transport);
binding2.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
You can also configure the binding administratively, using a
config file:
<bindings>
<netNamedPipeBinding>
<binding name = "IPCWindowsSecurity">
<security mode = "Transport">
<transport protectionLevel = "EncryptAndSign"/>
</security>
</binding>
</netNamedPipeBinding>
</bindings>
There is no need (or option) to set the client credentials
type, since only Windows credentials are supported (see Table 2). Figure 2 shows the
security-related elements of
the NetNamedPipeBinding.
NetNamedPipeBinding has a
reference to NetNamedPipeSecurity, which uses the
NetNamedPipeSecurityMode enum to indicate
the transfer security mode. When Transport security is used,
NetTcpSecurity will use an
instance of NamedPipeTransportSecurity containing the
configured protection level via the ProtectionLevel enum.
1.4. NetMsmqBinding configuration
NetMsmqBinding
offers a construction parameter for the transfer security mode and a
Security property:
public class NetMsmqBinding : MsmqBindingBase
{
public NetMsmqBinding(NetMsmqSecurityMode securityMode);
public NetMsmqSecurity Security
{get;}
//More members
}
The Security property of
the type NetMsmqSecurity contains
the transfer mode (Transport or Message) and two respective
properties with their specific settings:
public sealed class NetMsmqSecurity
{
public NetMsmqSecurityMode Mode
{get;set;}
public MsmqTransportSecurity Transport
{get;}
public MessageSecurityOverMsmq Message
{get;}
}
For the intranet security scenario, select Transport security
for the transfer security mode and set the values of the Transport property of the type MsmqTransportSecurity:
public sealed class MsmqTransportSecurity
{
public MsmqAuthenticationMode MsmqAuthenticationMode
{get;set;}
public ProtectionLevel MsmqProtectionLevel
{get;set;}
//More members
}
The Transfer property
should be initialized with the client credential type set to Windows
domain using the MsmqAuthenticationMode enum, defined
as:
public enum MsmqAuthenticationMode
{
None,
WindowsDomain,
Certificate
}
Windows domain is the default credentials type. In addition,
you need to set the protection level to ProtectionLevel.EncryptAndSign because the
MSMQ binding defaults to ProtectionLevel.Signed. The following two
definitions are equivalent:
NetMsmqBinding binding1 = new NetMsmqBinding();
binding1.Security.Transport.MsmqProtectionLevel = ProtectionLevel.EncryptAndSign;
NetMsmqBinding binding2 = new NetMsmqBinding();
binding2.Security.Mode = NetMsmqSecurityMode.Transport;
binding2.Security.Transport.MsmqAuthenticationMode =
MsmqAuthenticationMode.WindowsDomain;
binding2.Security.Transport.MsmqProtectionLevel = ProtectionLevel.EncryptAndSign;
Alternatively, you can configure the binding using a config
file:
<bindings>
<netMsmqBinding>
<binding name = "MSMQWindowsSecurity">
<security mode = "Transport">
<transport
msmqAuthenticationMode = "WindowsDomain"
msmqProtectionLevel = "EncryptAndSign"
/>
</security>
</binding>
</netMsmqBinding>
</bindings>
Figure 3 shows the
security-related elements of the NetMsmqBinding.
NetMsmqBinding has a
reference to NetMsmqSecurity,
which uses the NetMsmqSecurityMode enum to indicate the
transfer security mode. When Transport security is used, NetMsmqSecurity will use an instance of
MsmqTransportSecurity containing
the client credentials type via the MsmqAuthenticationMode enum, and the
configured protection level via the ProtectionLevel enum. There are similar
references to types controlling Message security.