Posted by zamd on February 8, 2011
This would hopefully be a multi-part series showing some tricks to enable claims-based-security in Silverlight 4.0. Silverlight 5.0 would have a much better story around claim-based-security as mentioned here.
In this first post, I’ll give you a high level overview of the solution. The main idea is to use the ‘WCF Routing Service’ in the DMZ to route both token issuance requests & business requests to the actual backend services.
1. Routing Service looks for a token issuing request and forwards it to the STS where the actual authentication is performed. After the successful authentication, STS issues a SAML token which goes back to Silverlight client via the routing service. Routing Service also terminates the SSL and backend is called using straight HTTP. This model offers strong security on the internet while keeping the internal deployment simpler & efficient. This model also resembles with the standard SSL offloading setup where a hardware load-balancer is used to terminate the SSL.
1: Token Issuance Path
2. Once the Silverlight client got a SAML token, it can attach it to all subsequent message sent to business service(s). Routing Services forwards al the business messages (messages which doesn’t match the token issuance filter) to the actual backend services again doing the protocol transitioning from HTTPS to HTTP. Please note, here you can use the rich filtering mechanism provided by the Routing services to decide which messages should to which services. I used a very simple MatchAll filter which forwards all the non-token-issuance messages to the business service.
2: Web Service Call Containing a SAML Token
To implement the 1st part of solution I have used the WSTrustClient class & the associated bindings from the identity training kit.
vm = this
.DataContext as MainPageViewModel
var stsBinding = new WSTrustBindingUsernameMixed();
var stsCreds = new UsernameCredentials(vm.UserId, vm.Password);
var client = new WSTrustClient(
var rst = new RequestSecurityToken(WSTrust13Constants.KeyTypes.Bearer);
rst.AppliesTo = new EndpointAddress(vm.AppliesTo);
client.IssueCompleted += new System.EventHandler<IssueCompletedEventArgs>(client_IssueCompleted);
For the 2nd part I have implemented a message inspector along with an extension method which makes it super easy to attach the SAML with outgoing messages.
vm = this
.DataContext as MainPageViewModel
client = new
client.GetDataCompleted += new EventHandler<ServiceReference1.GetDataCompletedEventArgs>(client_GetDataCompleted);
Posted in Security, WCF, WIF | 11 Comments »
Posted by zamd on July 12, 2010
WS-Security UsernameToken Profile describes how a client can authenticate to a web service using a "username" and a password. Two variations of the password are defined as part of the specification which includes "PasswordText" and "PasswordDigest". Neither WCF nor WIF out of box support "PasswordDigest" however there are some interop scenarios which might require "PasswordDigest". For example, WSE 3.0 supports "PasswordDigest" and if you have to interop your WSE 3.0 clients with WCF services you might need PasswordDigest functionality. In this post I’ll show you a basic implementation of PasswordDigest closely integrated with WCF API. Please note, this could be much easier to implement using the SecurityTokenHandler based API shipped with WIF.
I have created a new assembly and added all the security extensions in this new assembly named Microsoft.ServiceModel.SecurityExtensions.dll.
Microsoft.ServiceModel.SecurityExtensions.dll extends WCF to support Password Digest authentication while retaining WCF’s public programming model. You need to reference this assembly in all your web service projects where you want to enable PasswordDigest authentication. The security extensions are very closely aligned to the standard WCF model of userName/Password validation so you should be able to leverage all of your existing knowledge.
Please note this is a trivial implementation primarily focused on WCF integration rather than spec implementation. This example doesn’t contain any countermeasure code against replay attacks. You can add such functionality by maintaining a cache of used nonces on the server side and then checking against the replay.
To use these extensions in your web service(s), you need to do following:
Specify the type attribute of serviceCredentials to Microsoft.ServiceModel.SecurityExtensions.ServiceCredentialsEx for the extensions to kick in.
Specify your custom validator using the standard WCF syntax. Your custom validator MUST inherit from Microsoft.ServiceModel.SecurityExtensions.UserNamePasswordDigestValidator
<serviceCredentials type="Microsoft.ServiceModel.SecurityExtensions.ServiceCredentialsEx, Microsoft.ServiceModel.SecurityExtensions, Version=184.108.40.206, Culture=neutral, PublicKeyToken=null">
customUserNamePasswordValidatorType="PasswordDigest.MyValidator, PasswordDigest, Version=220.127.116.11, Culture=neutral, PublicKeyToken=null"/>
I have attached the source code and sample project with this post.
Posted in Extensibility, Security, WCF | 3 Comments »
Posted by zamd on May 14, 2010
When requesting a SAML token from an STS you can also request a proof token, which you can use to proof your ownership (by signing the primary signature with the proof token) of the token to the relying party when sending a SOAP message to it. In Identity terms, this is known as Holder-Of-Key subject confirmation method.
When using Holder-Of-Key confirmation method, there are three options for proof token:
- Symmetric key (based proof tokens)
- Asymmetric key
- Bearer key
See this post from Vittorio on the details of proof token.
Asymmetric key based proof tokens can come in following two forms:
- Requestor can generate an ephemeral RSA key pair and submit the public key to the IP/STS as part of the RST request. Requestor then signs the RST request with its private key to demonstrate the knowledge of the private key.
- Requestor can use an existing X509 public key cert as the proof token and use the corresponding private key cert to create the supporting signature.
wsFederationHttpBinding out of box (as in .NET 4.0) only supports an ephemeral RSA key pair while certain interop scenarios require X509 based asymmetric proof keys. For example, Apache Rampart 1.4 doesn’t seem to like ephemeral RSA key pair and forces you to use X509 based asymmetric proof keys. Unfortunately today this scenario is not possible out of box with wsFederationHttBinding. WSTrustChannelFactory API in WIF however supports both RSA key pair & X509 certs and you can choose your desired key type when requesting a token but WIF is not supported on XP.
So If you are on Windows XP or can’t use WIF for some other reason, you would have to extend wsFederationHttpBinding to enable X509 based proof keys. Probably a custom endpoint behaviour and inside it you would have to tweak IssuedSecurityTokenProvider to force it to use X509 key. See this post on how to work with IssuedSecurityTokenProvider directly. In the next post, I will talk more about extending wsFederationHttpBinding to support X509 based proof keys.
Posted in Security, WCF | 1 Comment »
Posted by zamd on March 5, 2009
Client Application Services enables the use of Authentication and other ASP.net services outside of ASP.net applications. Here I will show how you can configure WCF to flow Forms authentication cookie (acquired after successful authentication) to a WCF service (running in ASP.net compatibility mode).
static void Main(string args)
//Authenticate using membership API.
var valid = Membership.ValidateUser("Zul", "G!");
var identity = Thread.CurrentPrincipal.Identity as ClientFormsIdentity;
ServiceReference1.Service1Client sc = new FormsAuClient.ServiceReference1.Service1Client();
using (var ocs = new OperationContextScope(sc.InnerChannel as IContextChannel))
var ch = identity.AuthenticationCookies.GetCookieHeader(sc.Endpoint.ListenUri);
HttpRequestMessageProperty rmp = new HttpRequestMessageProperty();
rmp.Headers[HttpRequestHeader.Cookie] = ch;
// enable cookie flow for WCF Http Transport Channel.
var col = sc.Endpoint.Binding.CreateBindingElements();
var transport = col.Find<HttpTransportBindingElement>();
transport.AllowCookies = true;
sc.Endpoint.Binding = new CustomBinding(col);
// Add Forms Authentication Cookie to outgoing message.
On the server side, WCF service is running under ASP.net compatibality mode along with Forms Authentication configured in web.config
Note, for this configuration to work – both apps (sharing the cookie) MUST use the same/explicit machine key.
PS: There is a general misunderstanding that WCF doesn’t allow control over HTTP headers/body which lead few people think that this is not possible in WCF.
Posted in Security, WCF | 4 Comments »
Posted by zamd on November 17, 2008
Frequently I use following command to create self signed certs so I’m adding here for future reference.
makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=MySrvCert -sky exchange -pe
Posted in Security, WCF | 2 Comments »