Thursday, November 12, 2009
Q: There is a Windows Workflow Foundation (WF) workflow service which contains only one pair of Receive and SendReply. Data will be sent through the Receive activity and how do I get the workflow service to return the GUID of the workflow instance in SendReply activity.
A: Write a custom activity to retrieve it (See below). Bind that to a variable and bind that variable to the SendReply.Content
public sealed class GetWorkflowInstanceId : CodeActivity<Guid>
protected override Guid Execute(CodeActivityContext context)
Tuesday, May 05, 2009
Monday, May 04, 2009
Both references are good reads and would propbably be a good debate topic for many but lets not do the religious cult thing:
Abstraction, Componentization, Reusability, etc. They have all changed the world the developers live and breathe in, havent they ? No, I dont want to sauter transistors on a motherboard anymore. Give me a PC anytime. Give me solutions.
My personal opinion is that there is no end and you cannot find a answer that fits all. Question one has to ask is:
- Are you looking for a brick builder/manufacturer
- ... Or are you just interested in building a wall/house ?
Make no mistake, I think there is a market for both. However, chances are, no one single good person will fit both bills.
Monday, February 25, 2008
I remember back in 2005/2006 when I was still touring the APAC circuits such as Sydney (Australia) and Kuala Lumpur (Malaysia) doing training and consulting gigs for customers, partners about Windows Workflow Foundation (WF) and Windows Communication Foundation (WCF, previously - Indigo) and some of the initial Windows Workflow questions came up regarding the use of Parallel Activities. It came as a surprise to many people that parallel activities are not independently asynchronous.
I explained that a WF instance gets only one instance from the runtime. There are reasons for this single-threaded execution model so each activity have to work with this single thread efficiently. There are ways to spin off differents thread when real parallelism activities are reqquired but because documentation was scare at that time, I had some trouble articulating how to do so.
I just read "Multithreaded Parallelism in Windows Workflow Foundation" on MSDN and while it is a definite deep technical article, if you can grok it, you will understand how "MultiThreaded Parallelism" can be done in WF using both the (rather hard-to-use) "Call External Method Activity (CEMA)" and the "Handle External Event Activity (HEMA)". Not only that, the authors (whom actually implemented such a system for their own use) also shared how to pair those 2 activities up using correlation and how to create wrappers aoround them so that it can be reused and therefore "not require talented software developer use of call-external-method and handle-external-event activities along with the CLR thread-pool"
A gem of a read.
Saturday, October 13, 2007
I know I havent been posting deep technical stuff that I used to do. Contrary to what people think my current role entails, keeping abreast of the technology landscape is what I am supposed to do and what I enjoy and so when colleagues joked with me when was the last time I booted up Visual Studio, for example, I enjoyed seeing their shocked faces when I told them: "oh - just last night. why you asked ?" .
I dont dwell deep like I used to but I still code up decent projects which I implement within my own developmental testing environment (yes, I have one running latest versions of Active Directory, SharePoint, Exchange and all the other goodies), driving the houshold crazy when I think of new and different ways to document expenses, publish a Book or CD library, home automation projects using all sorts of different technologies (yes, that includes Ruby-on-Rails) or in my new Windows Mobile 6 Device. Of course, I admit I dont post topics deep like I used to. It is not so much the content but more so, the limiting factor of time.
Recently, I was involved in some internal technical discussions with regards to the issue of scale comparisions between Windows Communication Foundation (WCF, previously - Indigo) and ASMX. Below are some discussions:
If you have a web service that is going to be IO bound, you would definitely want it to be scalable and almost every resource in the world tells you to implement ASP.NET asynchronous pattern (BeginSomething/EndSomething, etc) on it so to go easy on the thread pool. ASP.NET uses an IAsyncHttpHandler to handle the request, which means the worker threads are not blocked while the IO-bound operation executes somewhere else. Sounds good so far.
If you make a WCF version of it with webHttpBinding (which actually means you can invoked it AJAX-style) following the same async pattern for the methods, you may find that each invocation of the WCF service eats up two threads – one for its ASP.NET HttpModule.ProcessRequest and the other for the actual IO. Ouch! You may think that this means your WCF implementation may end up eating all threads reserved for ASP.NET, which would indeed scale down the server
Is this true OR are we missing the complete picture ?
While the scenarios explained above are reasonable observations, it doesnt paint the complete picture. WCF does perform better scalability than ASMX.
For ASMX, when a request comes in, it would be queued up immediately for async ASMX. So the thread is released for that request and a new thread will pick up the work item later.
For WCF, when a request comes in, we queue it up in WCF and let an IO thread handle the request. At the same time, the request thread-pool thread is held to wait for the request to complete.
Yes, WCF uses more threads than async ASMX. But there is a reason for this. Using asynchronous ASMX is dangerous and not really a good practice (and I have hinted at this many times in the many Web Service/ASMX presentations I have done over the past few years). While it does well at what it is supposed to do, it does trick the developer into a "false sense of security". Essentially, if you dont know how the ASP.NET blackbox works, you may find yourself thrown against the car wall when you take a hidden, unsuspecting corner at high speeds. It does not provide enough throttling for client loads. Basically the server takes all items and queue them up for later processing. The server does not have a good throttling mechanism to control the number of work items. To everyone else, it seems that the server is quite friendly to all clients. However, if the number of clients is unbounded, this is really bad. First of all, the server working set would grow unlimited due to unlimited requests queued up. Secondly, many client requests would become obsolete when it’s picked up by the server from the queue. The latter accounts for a a good set of problematic scenarios I have come across in my past consulting gigs with regards to high-load and high-transactional ASMX asynchronous implementations before I joined the borg.
Think of it as a side of the brain (that tells you that you are about to be full) not functioning properly when you sit down at a buffet table. You eat and eat and eat without knowning when to stop and then your ingestion/digestion system starts kicking in, you actually hit the wall. Hard. Literally.
- Server Throughput
When you measure scalability, the most important measurement is the server throughput. That is, how many requests the server can handle per time unit? For async ASMX, it would be pretty fast at the initial phase. However, like the ingestion/digestion analogy I was referring to above - Once the server is in a steady phase (as when CPU is fully loaded), the throughput will go down because the server capacity has reached. You can compare the data between async ASMX and sync ASMX over the long run to see what I mean.
Also you would see higher memory usage of the async approach.
- ASP.NET Throttling
That said, ASP.NET does have a throttling mechanism that is used for sync ASMX, which is the threadpool thread limit. The number of threads used to handle requests are bounded (http://support.microsoft.com/kb/821268). WCF uses this fact to throttle incoming requests. You can always change the configuration settings to increase number of threads to be used to allow more work items to be queued up.
The max number of threads follows the following formula:
MaxWorkerThreads x #CPU – MinFreeThreads
This is 12 by default on a single-proc machine.
- Two-level Throttling for WCF
WCF leverages the ASP.NET threadpool throttling to throttle client requests. At the same time, WCF has its own item queue throttling. The former is throttled by the setting mentioned in the immediate above point, while the latter is controlled by WCF throttling settings (maxConcurrentCalls etc). ASP.NET can automatically adjust threads based on CPU loads so that you would always get full load of the server.
In this way, you may experience client failures because the requests are rejected at ASP.NET layer beforehand. So you can increase the ASP.NET throttling to get better experience. But eventually you would still be bounded by the physical server capacity, no matter whether you use async ASMX, sync ASMX, or WCF as mentioned above.
There is improvement work done in .NET 3.0 SP1 and of course, .NET 3.5 (beta 2 here), with the use of prioritized item queues. Do expect even-better WCF performance even in some of the common scenarios. Fine tuning minWorkerThreads will even give us even better results.
Thanks to Wenlong for helping out with the guidance and explanation. The complete scenario and the design principles for it will be published in greater detail in a MSDN whitepaper later. Do watch out for it.
Saturday, August 18, 2007
MSFT Corp has always talked about its ecosystem with regards to its developers and partners as one of its key value propositions which it offers through its platform to its customers.
Sometimes it is humbling to have customere call on you because its other systems can only work with yours and no one else. I have totally lost track of our ISV partners who are building great vertical solutions on top of our horizontal application stack, such as Microsoft Office SharePoint Server (MOSS) and others and that list is growing as I write this.
This is another take on it, albeit from another interesting perspective.
Wednesday, March 07, 2007
Friday, August 11, 2006
Many people have asked how we can retrieve and process a token sent by a subject or a Security Token Service. Just to showcase the non-intrusiveness of Microsoft Cardspace, in that we can easily incorporate a Cardspace "Sign-in with Cardspace" into your website today such as this or this, I have shown snippets of how we can do so via php here.
As an another example of non-intrusiveness, I have also got a simple working sample that you can use to integrate into your ASP.NET 2.0 page today.
Of course, this is a hack job and there are no try catch and the xml parsing code is hastily done. To summarize, I wont win the elegance award here ... but you can get it to work on .NET 2.0 (or maybe even 1.1) ...
Of course, this is a hack job and there are no try catch and the xml parsing code is hastily done. To summarize, I wont win the elegance award here ... but you can get it to work on .NET 2.0 (or maybe even 1.1) ...
'This will get you your encrypted token
Dim str As Stream
str = Request.InputStream
Dim sr As New StreamReader(str)
Dim s As String = sr.ReadToEnd
s = Server.HtmlDecode(Server.UrlDecode(s))
'the stream will be ASCII encoded
Dim u8 As System.Text.UTF8Encoding = New System.Text.UTF8Encoding
Dim fs As New FileStream("C:\temp\CardspaceXMLToken.xml", FileMode.Create)
'Remove the "xmlToken="
Dim i As Integer = s.IndexOf("<")
s = s.Substring(i)
fs.Write(u8.GetBytes(s), 0, u8.GetBytes(s).Length)
'The will decrypt that request token and return a Signed Security SAML Token
Dim encryptedDoc As New XmlDocument()
'Check for <EncryptedData> element
If encryptedDoc.GetElementsByTagName _
("EncryptedData", "http://www.w3.org/2001/04/xmlenc#").Count = 0 Then Return
Dim encryptedD As XmlElement = CType(encryptedDoc.GetElementsByTagName _
("EncryptedData", "http://www.w3.org/2001/04/xmlenc#")(0), XmlElement)
'Check for @Algorithm attribute and make sure its http://www.w3.org/2001/04/xmlenc#aes256-cbc
If encryptedD.ChildNodes(0).Attributes("Algorithm") Is Nothing Or _
encryptedD.ChildNodes(0).Attributes("Algorithm").Value <> _
"http://www.w3.org/2001/04/xmlenc#aes256-cbc" Then Return
Dim a As New RijndaelManaged
'Check for <KeyInfo> element
If encryptedD.ChildNodes(1).Name <> "KeyInfo" Then Return
'Check for <EncryptionMethod> element
Dim encryptedM As XmlElement = CType(encryptedDoc.GetElementsByTagName _
("EncryptionMethod", "http://www.w3.org/2001/04/xmlenc#")(1), XmlElement)
'Check for @Algorithm attribute and make sure its http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p
If encryptedM.Attributes("Algorithm") Is Nothing Or _
encryptedM.Attributes("Algorithm").Value <> _
"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" Then Return
'Check for <CipherData\CipherValue>
If encryptedD.GetElementsByTagName("CipherValue", _
"http://www.w3.org/2001/04/xmlenc#").Count = 0 Then Return
'Retrieving the Encrypted Symmetric Key and the Security Token
Dim e_SymmKey As String = encryptedDoc.GetElementsByTagName _
Dim e_SecurityToken As String = encryptedDoc.GetElementsByTagName _
Dim rsaCsp As New RSACryptoServiceProvider
Dim privatecert As New X509Certificates.X509Certificate2
privatecert.Import("Softwaremaker.NET.SSL.pfx", "Softwaremaker_NET_SSL_pfx_password", X509Certificates.X509KeyStorageFlags.Exportable)
'Now we have the Symmetric Key
Dim DecryptedStrAsByt() As Byte = _
'Moving on to use the Symmetric Key to decrypt Token
Dim rijndaelM As New RijndaelManaged
rijndaelM.Mode = CipherMode.CBC
Dim swmDecryptor As ICryptoTransform
swmDecryptor = rijndaelM.CreateDecryptor(DecryptedStrAsByt, Nothing)
'Define memory stream which will be used to hold encrypted data.
Dim cipherTextBytes As Byte()
cipherTextBytes = System.Convert.FromBase64String(e_SecurityToken)
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream(cipherTextBytes)
' Define memory stream which will be used to hold encrypted data.
Dim cryptoStream As CryptoStream
cryptoStream = New CryptoStream(memoryStream, swmDecryptor, CryptoStreamMode.Read)
' Since at this point we don't know what the size of decrypted data
' will be, allocate the buffer long enough to hold ciphertext;
' plaintext is never longer than ciphertext.
Dim plainTextBytes As Byte()
' Start decrypting.
Dim decryptedByteCount As Integer
decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
' Close both streams.
' Convert decrypted data into a string.
' Let us assume that the original plaintext string was UTF8-encoded.
Dim plainTextToken As String
plainTextToken = System.Text.Encoding.UTF8.GetString(plainTextBytes, 16, _
decryptedByteCount - 16)
Of course, you would have to verify the signed token yourself BUT this decryption process is definitely a step in the right direction
If you have benefitted from these sample snippets, maybe you can pay-it-forward by implementing and then sharing the signature-verification codes with me here? I am too lazy ... .
Wednesday, March 15, 2006
Ar - Arguments...It does make us move forward at times.
Richard Grimes has managed to kick up a storm again with his article here, again. While, I would not go very far in saying a kernel Operating System should be written in managed-code. God knows I will not use one if it is and you shouldnt to. As far as I can tell, .NET was not created for writing operating systems? It sits on top of the operating system and thats that
It is, however, very important to note, the investments MSFT Corp have on managed code. Instead of giving you the usual bullets and docs. How about this ?
Lines of Managed Code
And lets not forget that Microsoft CRM is the first Enterprise Business Solutions that is written on managed code from Microsoft. Read: Dogfood
And YES - Windows Communication Foundation (WCF, previously - Indigo) is written in C# as well.
Case Closed. <EOM>
Friday, January 20, 2006
Sounds like SPAM ? It is not.
This is a 100% ASP.NET 2.0 based CMS solution -- best of all it is free -- check out this blog post for some sites built with it.
All the info you need is here. Let me know your thoughts if you are using it. I will be embarking on it very soon.
Friday, November 11, 2005
What an awesome Translator !!!
Where was this a year ago when I had to port something from C# to VB.NET ?
The next enhancement should have something that translates business requirements to code. I would definitely buy that.
Tuesday, September 20, 2005
I remember while I was chatting about one of the article I was working on for MSDN with some folks from MSFT Corp during lunch at PDC 2005 and I said that most of my code snippets are written in Visual Basic and for once ever, no-one sniggered and laughed. That moment was priceless.
This was because we just came off a fantastic talk on Visual Basic 9: Future Directions in Language Innovations. In fact, someone echoed how cool Visual Basic 9 IS now. I dont know how long was it when "Cool" and "Visual Basic" got along together until today. WOW ! What can I say ? It is standing proud.
There is a piece here that gives a brief overview on Visual Basic 9. What do I love most ? Its built-in deep XML Support. I cannot wait. Give it to me now !!!
It was a great day.
Thursday, July 28, 2005
The WinFX Runtime Components Beta 1 is available here, and the WinFX SDK is available here. Also, check out the new Windows Vista Developer Center at http://msdn.microsoft.com/windowsvista.
With this release comes with the official names for many of the technologies that they've been talking with our developers about for several years. In particular, Windows Longhorn is now Windows Vista, Avalon is now the Windows Presentation Foundation, and Indigo is the Windows Communication Foundation.
“Former” code name
Windows Presentation Foundation
Windows Communication Foundation
XML Paper Specification (XPS)
Least-privileged User Access
User Account Protection
WinFX Runtime Components
Wednesday, July 27, 2005
Tuesday, July 26, 2005
The much anticipated download of a fully installed & configured Visual Studio 2005 Team System Beta 2 VPC is now available for download to MSDN Universal Subscribers. This is the same VPC that was distributed at TechEd USA and TechEd EMEA and represents a clean install of Windows Server 2003 w/ Visual Studio 2005 Team System Beta 2.
This VPC does not contain any sample projects or sample data.
Minimum System Requirements:
If you have some trouble locating this developer-Godsend --- I have done some snopping already and it is here:
Developer Tools > Visual Studio 2005 > Visual Studio 2005 Beta 2 > English > Visual Studio 2005 Team System Beta 2 VPC
Friday, July 22, 2005
Thursday, June 30, 2005
Saturday, June 11, 2005
I will be delivering Indigo Ascend in Asia Pacific in the coming months on behalf of the Indigo and Ascend team in MSFT Corp, Redmond, US.
It will start in Sydney, Australia later this month, then move upwards (northwards) to my own local backyard, Singapore. There are a few more countries Microsoft and I are interested to look at bringing this event as well.
This will be a good time for me to meet up with real customers from the enterprises who are using Microsoft distributed technologies or are planning to look into using it in the future. Drop me an email here if you would like to engage me for a discussion.
If you are reading this blog post and you work for an ISV or an enterprise that does a fair bit of distributed computing technology and you are interested in attending this Indigo Ascend in Singapore (I think we are a little bit late in nominations for Australia), do drop me a mail here and I will see what I can do to hook you up for this 3 day event.
If you are from anywhere else besides Australia or Singapore (in APAC) and would love to attend an event like this, do drop me an email as well and I will see what I can do to bring Indigo Ascend to your country.
I have been invited to deliver a few Ascends before such as Visual Studio 2005 and such. However, I have always turned it down because I dont consider myself to be a "professional" trainer since I have always been on the field working on real projects with real problems in distributed technologies for some time (and not some simulated fanciful classroom labs scenarios) ...
Indigo is an Ascend which I am proud and excited to deliver because it is a future facet of Windows Server 2003 that I have spent quite some time on and I believe it is something that real customers need in the field to solve real-world problems today.
There is really nothing quite like it out there at the moment or in the immediate future outside of Microsoft. It is really one of Microsoft's innovation at its best.
I have recently flashed some performance graphs between Java 1.5 and the .NET counterparts version 1.1 and 2.0 Beta2. This is where I got the statistics from.
You will see the outright disparity in performance gains when .NET 2.0 Beta2 is put through the same tests with its poorer 1.1 brother and its distant cousin Java 1.5.
...And we are still talking about .NET 2.0 BETA 2 ... Let us see what happens when we get to November 7 2005
Saturday, June 04, 2005
Wednesday, June 01, 2005
First Survey of U.S. Corporate Application Server and Scripting Deployments Reveals Microsoft® Ahead of Competing Web Platforms.
Not really a surprise to me but good to know nonetheless.
Saturday, April 30, 2005
With reference to my earlier post here, more details on the conference (SDA.NET 2005) are now publicly available here. This is a paid event and it is rarity in Singapore as technological conferences are usually presented free. BUT I am sure attendees can find a lot of value here as top notch speakers from all over the world will be flying over here to share their industry experience and knowledge.
Who are these speakers, you ask ? There is the famous Ingo Rammer and Clemens Vasters and of course, moi .
I will be making 2 presentations in the VIP Tracks, namely
Demystifying WSDL (26 May 2005 1045 hours)
While developers rely on the many powerful features of today's IDEs, inner technical plumbings are often ignored and worst yet - misrepresented and misunderstood. This ignorance of inner workings can lead developers to choose the wrong technologies and solutions for solving specific problems. Nevertheless, when it comes to troubleshooting the nooks, crannies and crevices at crunch time with no extra help, nothing beats a dirty pair of hands, a hammer and screwdriver. William Tay attempts to get everyone's hands dirty with a detailed look at WSDL, one of the most core and mature XML service technologies of today.
Topics to be covered include: what is WSDL, WSDL's critical role in service-orientated architecture (SOA), and WSDL's core elements and definitions. He will also survey WSDL best practices (eg. interoperability, extensibility, versioning, etc.) and the application of WSDL concepts in Indigo. The new features and enhanced functionality incorporated into the upcoming release of WSDL 2.0 are explained and compared with the current WSDL version.
NOTE: This is a (Level 400) deep technical session that is not for the faint-hearted. However, it will be a angle-bracket fest.
SOAP Message-based Security: Today and Tomorrow (26 May 2005 1415 hours)
One of the three key pillars of critical importance in the adoption of SOAP messaging-based services in an enterprise is security. In fact, the security aspect of standards-based messaging system has been singled out by worldwide CXOs as the most inhibiting factor in the mainstream-wide adoption within an enterprise. The ratification of WS-Security 1.0 by OASIS on 6 April 2004 has gone into great lengths to change that perception. William will show how and what you can do to secure your SOAP messaging-based services today. You will also learn how the same standards-based WS-Security Specifications can be used to secure the next generation of distributed web services with Indigo.
All 3 of us are presenting on Indigo as well. This will be a good time to catch a preview of Indigo and have a feel of what it is all about. I really hope to see a good turnout there and it will be a good time to catch up with Ingo, Clemens and the rest of the folks.
See you there.
Friday, January 28, 2005
Some of the folks in the Spore DotNet Usergroup got together one night to run a practical project. The idea behind the link is to build a bridge to access Visual SourceSafe over the internet. It was built successfully with the help of SCCBridge.
Incidentally, SCCBridge relies heavily on SOAP and DIME for its purpose and it is therefore no surprise that Web Services Enhancements (WSE) 2.0 was heavily involved in use here.
"Both the server and the client are written in C# in Microsoft Visual Studio .NET. In the project is used library SharpZipLib created by Mike Krueger (for more info see http://www.icsharpcode.net/ ). The algorithm for text files comparing was taken from The Code Porject site, and was written by Shankar Pratap."
This has been floating around for some time BUT MSFT Corp has released an official statement here
Since XQuery is expected to reach W3C recommendation only in 2006, it won't be shipped in the upcoming .NET Framework 2.0
I guess people like me will have to live with XSLT and XPATH for now.
Sunday, December 19, 2004
Having been developing for a number of years since the late 80s, I have been very used to the programming practice of using hungarian notation. I not only used it in variables, but in the database naming as well. Yes, I used tbl and fld prefixes for my Tablenames and Fieldnames respectively.
Of course, recent recommendations is to dump hungarian notation in your programming style and opt to use meaningfull, descriptive words instead. I have also been poked fun at for using hungarian notation while doing some testing work for Paladin by its author.
So there I decided to adopt a new developing and programming lifestyle and was happily humming along when I got hit face-first by a (JET Engine) ADO.NET Exception Syntax error in UPDATE (0x80040E14). Having been doing the same UPDATE statement style and using the same Data Access Layer blocks for so long, the ego-monster in me looked for a system bug right away. Running this same query within MS Access itself would be fine but if I used JET as the Data Provider, the same exception would occur. Try as I have to google'd it, I cannot seem to find out what was wrong. Most of them poined to the use of JET's keywords such as [PASSWORD] which I have learnt from previous experience to just use PWD. Here is my “post-hungarian notation” UPDATE Statement:
"UPDATE LibraryItems SET Title = '" & psTitle & _
"', AuthorArtist = '" & psAuthorArtist & "' , ItemTypeID = " & piItemTypeID & _
" , GenreID = " & piItemTypeID & " , ContentFormatID = " & piContentFormatID & _
" , Qty = " & piQty & " , DateBought = #" & pdDateBought & "# , PriceBought = " & _
pcPriceBought & " , DateSold = #" & pdDateSold & "# , PriceSold = " & _
pcPriceSold & " , StatusID = " & piStatusID & " , References = '" & psReferences & _
"' , Remarks = '" & psRemarks & "' WHERE ID = " & CommonUtil.ValidateSQLSafeString(mRecID)
Can you spot my mistake ? I didnt until I stumbled across this MS Support article about JET's reserved keywords...
AARRGH !!! So, REFERENCES is a JET's reserved keyword as well. In the past, I would have used fldReferences and therefore would NOT have encountered such an exception.
The FIX: Wrap Square brackets around the column name [References]. In fact, I recommend to wrap it around all column names, not just suspect ones. OR just use the CommandBuilder QuotePrefix and QuoteSuffix command to bypass the reserved keyword error.
- CommandBuilder.QuotePrefix = "["
- CommandBuilder.QuoteSuffix = "]"
Saturday, November 20, 2004
Please take note that X.509 Digital Certs generated this way are for testing and development purposes only.
Thursday, November 04, 2004
With reference to my previous posted here on Real World UsernameToken Authentication Scenarios with WSE 2.0
I have received some very good responses and feedback based on that and the questions tend to continue:
Some of the feedback I have received asked about the Encryption of the UsernameToken in the ResponseStream in the example given above. Here is a sample question:
Encrypting the username token using the public key of the server ensures
that the password is encrypted in the request to the server. What happens
when the response from the server is sent to the client ? I have looked at the
the trace the output tace at the client has no password in clear text. But
the input trace on the client has a clear text password. Why ?
The username credentials returned will follow that of the request method. So, if you send a SendPlainText mode of the PasswordOption in a request [even though you encrypt the UsernameToken afterwards], the UsernameToken in the response will be sent back in PlainText as well. This happens, of course, if you added the mutable UsernameToken back into the response stream
'Add Mutable Token into the Token Collection of the Response
We cannot re-do the process we did earlier in the RequestStream by encrypting the UsernameToken again. If you remember, that was done because we had to do some Hash-Digest comparision with the Hash value stored in the user db against the Hash value generated from the Password sent in the RequestStream. Thus, the Password send have to be in PlainText mode. However, we will encrypt the UsernameToken so that it doesnt get seen on the wire. We encrypt it with the Recipient's PublicKey for the Recipient's perusal. At least, an encrypted token CAN be decrypted, a Hashed one CANNOT.
However, we cannot do the same in the reverse ResponseStream. This is because we cannot encrypt the Recipient's SecurityToken with the Recipient's key. The Recipient machine would not know how to decrypt it.
ResponseSoapContext.Security.Elements.Add(New EncryptedData(eTok, "#" & eTok.Id))
doesnt make any sense and would be invalid and the Recipient would respond with a SOAP Client error:
ApplicationException: WSE507: The order of security elements and security tokens
will cause a processing failure on the receiving end, and they must be reordered
to create a valid message.
To hack around this constraint in WSE 2.0, the best alternative I could think of and tried is to intercept the process and force the UsernameToken to be sent back with a SendHashed or better, with a SendNone Option. This can be done by typeCasting the SecurityToken that is retrieved from the earlier RequestStream to that of a UsernameToken. Then retrieve all the necessary credentials of the casted UsernameToken (eg. Username, Password) and send that details into a new instantiated UsernameToken. Then, add this newly created mutable UsernameToken into the ResponseSoapContext Stream.
'Retrieve the Signing Token from the Request Message
Dim eTok As SecurityToken = GetBodySigningToken(RequestStream)
'Retrieve the Encrypting X509Security Token from the Request Message
Dim sTok As X509SecurityToken = GetBodyEncryptingToken(RequestStream)
'CAST the SecurityToken into a UsernameToken type
eTok = CType(eTok, UsernameToken)
'Force the process to send back a Hashed or NO Password
Dim ut As UsernameToken = New UsernameToken _CType(eTok, UsernameToken).Username, CType(eTok, UsernameToken).Password, PasswordOption.SendHashed)
'Retrieve the same Cert from the Local Machine store and Check if it supports Digital Signing
Dim sX509KeyID As String = Convert.ToBase64String(sTok.Certificate.GetKeyIdentifier)
sTok = Helpers.GetSigningX509Cert(sX509KeyID)
'Add Mutable Token into the Token Collection of the Response
'Add the Message Signature into the message
'Add the Encrypted data into the message
From the ResponseStream generated, you will be able to look at the UsernameToken sent back now to the Recipient. However, the Password will be Hashed or there may be NO Password at all (if you configured to be sent back with a PasswordNone Option). Below is the trace snippet sent back from the Server to the Recipient.
Of course, if the Service Consumer has their X.509 Digital Certs as well, we can always embed a binarySecurityToken representation of the client's Public Key into the SOAP Request stream and then, in the Service Response Stream, encrypt the Consumer's UsernameToken with his own Public Key taken from the binarySecurityToken representation and dispatches it. However, this is not an elegant solution as
- Most Service Consumers do not have their own X.509 Digital Certs and therefore, we have to cater for those who dont. This means extra processing power and code is needed to parse the SOAP Message to check for the binarySecurityToken and extra logic is required to hash it back using the above method if the binarySecurityToken is not found.
- Message Payload will increase with any type of encryption as compared to hash digest and with the attachment of the binarySecurityToken as well.
Do let me know if this works for any of you or, if you have better suggestions.
It sure is great to see many people beginning to experiment and use Web Services Enhancements (WSE) 2.0. Many people I speak to and come across today are still trying to grasp the security features of WSE.
I had blogged about this earlier in my old weblog host here. However, I will just summed it up for interested parties in this post.
...While the Documentation of WSE 2.0 teaches on how to authenticate a usernameToken from a client request against a database query [I print it here for your benefit]:
Protected Overrides Function AuthenticateToken(userName As UsernameToken) As String
'BLAH BLAH BLAH
'You are supposed to be reading from a returned Database query based on the UsernameToken.userName property.
'Then you are supposed to return the Password that is returned from the DB Query here
However, it doesnt touch on one of the best practices of Security of storing passwords into a database which is to hash userpasswords and then store it in the DB. So the question is how do we compare then ?
Bearing in mind the constraints of
- Passwords must be sent from the client in PlainText Form so the service can hash it and compare against the database
- Passwords cannot be sent in Hash Digest form as the service would have NO idea on how to re-engineer the actual password from the Hash Digest
I suggest a couple of alternatives to solve this problem....Most of what you choose will depend on very much how much control you have over the client
- SSL it [The ugliest, expensive and least scalable way...but requires the least coding work]
- Send the username, password in ClearText Via the usernameToken. However, encrypt this entire usernameToken before sending it over. The pipelines of WSE will handle the decryption for you. Once it reaches your service application, you will know what the ClearText password is. Hash it and then do a straight comparison of the Hash Digest against the one returned from the Database. This method assumes that the server has the Private Key portion of an asymmetric token such as a X509 Digital Certificate or even the service has a X509 Digital Certificate to begin with and it also assumes the knowledge of the Hash Algorithm method employed by the user DB.
While the documentation may be poor, the extensibility of the UsernameTokenManager is great ! I will reproduce snippets of option  for your benefit
Dim a As localhost.IndexWse = New localhost.IndexWse
'Send PlainText Password across so that the Service can hash Digest
'this value for comparison later
Dim ut As UsernameToken = New UsernameToken _
("TestAccount", "TestPassword", PasswordOption.SendPlainText)
'Include the usernameToken in the message so the Server can verify that
'this usernameToken actually came from you
'Blah - Find the Service Public Key of its X509 Cert so only the Service
'can decrypt and read this Token
Dim store As X509CertificateStore = _
Dim cert As X509Certificate = store.FindCertificateByKeyIdentifier _
Dim tok As X509SecurityToken = New X509SecurityToken(cert)
'Sign and Encrypt everything in the message. Beware of the Payload !
a.RequestSoapContext.Security.Elements.Add(New EncryptedData(tok, "#" & ut.Id))
Public Class CustomUsernameTokenManager
Protected Overrides Function AuthenticateToken(ByVal token As UsernameToken) As String
Dim pw As String = token.Password
'Employ the same Hash function on the password that you deployed saving the passwords
'into the User DB
Dim hpw as string = userDBHash(pw)
'Compare the hpw result with the one returned from the oledbReader from the Database
'with the username as the Reference
'If it matches, return the same password from the Token
Return "A Password that is impossible to GUESS"
End Function 'AuthenticateToken
End Class 'CustomUsernameTokenManager
If you check your diagnostics and the SOAP Message Tracing Files, you will notice that the entire usernameToken is encrypted and nothing is sent over in ClearText even tho the passwordOption is set to SendPlainText.
Friday, October 29, 2004