It's 2008. Where's my flying car? RSS 2.0
 Wednesday, August 22, 2007

We're all sinners. Lots of the authentication mechanisms on the Web are not even "best effort", but rather just cleartext transmissions of usernames and passwords that are easily intercepted and not secure at all. We're security sinners by using them and even more so by allowing this. However, the reality is that there's very likely more authentication on the Web done in an insecure fashion and in cleartext than using any other mechanism. So if you are building WCF apps and you decide "that's good enough" what to do?

WCF is - rightfully - taking a pretty hard stance on these matters. If you try to use any of the more advanced in-message authN and authZ mechnanisms such as the integration with the ASP.NET membership/role provider models, you'll find yourself in security territory and our security designers took very good care that you are not creating a config that results in the cleartext transmission of credentials. And for that you'll need certificates and you'll also find that it requires full trust (even in 3.5) to use that level of robust on-wire security.

dasBlog has (we're sinners, too) a stance on authentication that's about as lax as everyone else's stance in blog-land. There are not many MetaWeblog API endpoints running over https (as they rather should) that I've seen. 

So what I need for a bare minimum dasBlog install where the user isn't willing to get an https certificate for their site is a very simple, consciously insecure, bare-bones authentication and authorization mechanism for WCF services that uses the ASP.NET membership/role model (dasBlog will use that model as we switch to the .NET Framework 3.5 later this year). The It also needs to get completely out of the way when the service is configured with any real AuthN/AuthZ mechanism.

So here's a behavior (some C# 3.0 syntax, but easy to fix) that you can add to channel factories (client) and service endpoints (server) that will do just that. If you care about confidentiality of credentials on the wire don't use it. For this to work, you need to put the behavior on both ends. The behavior will do nothing (as intended) when the binding isn't the BasicHttpBinding with BasicHttpSecurityMode.None). The header will not show up in WSDL.

On the client, you simply add the behavior and otherwise set the credentials as you would usually do for UserName authentication. This makes sure that the client code stays compatible when you upgrade the wire protocol to a more secure (yet still username-based) binding via config.

MyClient remoteService = new MyClient();
remoteService.ChannelFactory.Endpoint.Behaviors.Add(new SimpleAuthenticationBehavior());
remoteService.ClientCredentials.UserName.UserName = "admin";
remoteService.ClientCredentials.UserName.Password = "!adminadmin";

On the server, you just configure your ASP.NET membership and role database. With that in place, you can even use role-based security attributes or any other authorization mechnanism you are accustomed to in ASP.NET. Just as on the client, the behavior goes out of the way and gives way for the "real thing" once you turn on security.

using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Security;
using System.Threading;
using System.Web.Security;
using System.Xml.Serialization;

namespace dasBlog.Storage
{
    [
DataContract(Namespace = Names.DataContractNamespace)]
    class SimpleAuthenticationHeader
    {
        [
DataMember]
       
public string UserName;
        [
DataMember]
       
public string Password;
    }

   
public class SimpleAuthenticationBehavior : IEndpointBehavior
    {
        #region IEndpointBehavior Members

       
public void AddBindingParameters(ServiceEndpoint endpoint, 
                                        
BindingParameterCollection bindingParameters)
        {
           
        }

       
public void ApplyClientBehavior(ServiceEndpoint endpoint, 
                                       
ClientRuntime clientRuntime)
        {
           
if (endpoint.Binding is BasicHttpBinding &&
                ((
BasicHttpBinding)endpoint.Binding).Security.Mode == BasicHttpSecurityMode.None )
            {
               
var credentials = endpoint.Behaviors.Find<ClientCredentials>();
               
if (credentials != null && credentials.UserName != null && credentials.UserName.UserName != null)
                {
                    clientRuntime.MessageInspectors.Add(
new ClientMessageInspector(credentials.UserName));                   
                }
            }
        }

       
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
        {
           
if (endpoint.Binding is BasicHttpBinding &&
                ((
BasicHttpBinding)endpoint.Binding).Security.Mode == BasicHttpSecurityMode.None)
            {
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(
new DispatchMessageInspector());
            }
        }

       
public void Validate(ServiceEndpoint endpoint)
        {
           
        }

        #endregion

        class DispatchMessageInspector : IDispatchMessageInspector
        {
            #region IDispatchMessageInspector Members

           
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
               
int headerIndex = request.Headers.FindHeader("simpleAuthenticationHeader", "http://dasblog.info/2007/08/security");
               
if (headerIndex >= 0)
                {
                   
var header = request.Headers.GetHeader<SimpleAuthenticationHeader>(headerIndex);
                    request.Headers.RemoveAt(headerIndex);
                   
if ( Membership.ValidateUser(header.UserName, header.Password) )
                    {
                       
var identity = new FormsIdentity(new FormsAuthenticationTicket(header.UserName, false, 15));
                       
Thread.CurrentPrincipal = new RolePrincipal(identity);
                    }
                }
               
return null;
            }

           
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
               
            }

            #endregion
        }

       
class ClientMessageInspector : IClientMessageInspector
        {
            #region IClientMessageInspector Members

           
UserNamePasswordClientCredential creds;

           
public ClientMessageInspector(UserNamePasswordClientCredential creds)
            {
               
this.creds = creds;
            }

           
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
               
            }

           
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
            {
                request.Headers.Add(
MessageHeader.CreateHeader("simpleAuthenticationHeader", http://dasblog.info/2007/08/security,
                                    new SimpleAuthenticationHeader{ UserName = creds.UserName, Password = creds.Password }));
                
return null;
            }

            #endregion
        }
    }
}

Wednesday, August 22, 2007 10:20:05 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback
Indigo | WCF
 Tuesday, August 21, 2007

I'm writing lots of code lately. I've rejoined the dasBlog community and I'm busy writing a prototype for the .NET Framework 3.5 version of dasBlog (we just released the 2.0 version, see http://www.dasblog.info/).

One of the goals of the prototype, which we'll eventually merge into the main codebase once the .NET Framework 3.5 is available at hosting sites is to standardize on WCF for all non-HTML endpoints. Since lots of the relevant inter-blog and blogging tool APIs are still based on XML-RPC, that called for an implementation of XML-RPC on WCF. I've just isolated that code and put it up on wcf.netfx3.com.

My XML-RPC implementation is a binding with a special encoder and a set of behaviors. The Service Model programming experience is completely "normal" with no special extension attributes. That means you can also expose the XML-RPC contracts as SOAP endpoints with all the advanced WCF bindings and features if you like.

The binding supports client and service side and is completely config enabled. Here's a snippet from the MetaWeblog contract:

[ServiceContract(Namespace = http://www.xmlrpc.com/metaWeblogApi)]
public interface IMetaWeblog : Microsoft.ServiceModel.Samples.XmlRpc.Contracts.Blogger.
IBlogger
{
   [OperationContract(Action="metaWeblog.editPost")]
   bool metaweblog_editPost(string postid,
                             string username,
                             string password,
                             Post post,
                             bool publish);

   [OperationContract(Action="metaWeblog.getCategories")]
   CategoryInfo[] metaweblog_getCategories( string blogid,
                                            string username,
                                            string password);
    ...
}

For your convenience I've included complete Blogger, MetaWeblog, and MovableType API contracts along with the respective data types in the test application. The test app is a small in-memory blog that you can use with the blogging function of Word 2007 as a client or some other blogging client for testing.

Of the other interesting XML-RPC APIs, the Pingback API has the following contract:

    [ServiceContract(Namespace="http://www.hixie.ch/specs/pingback/pingback")]
   
public interface
IPingback
    {
        [
OperationContract(Action="pingback.ping"
)]
       
string ping(string sourceUri, string
targetUri);
    }

and the WeblogUpdates API looks like this:

    [DataContract]
   
public struct
WeblogUpdatesReply
    {
        [
DataMember
]
       
public bool
flerror;
        [
DataMember
]
       
public string
message;
    }

    [
ServiceContract
]
   
public interface
IWeblogUpdates
    {
        [
OperationContract(Action = "weblogUpdates.extendedPing"
)]
       
WeblogUpdatesReply ExtendedPing(string weblogName, string weblogUrl, string checkUrl, string
rssUrl);
        [
OperationContract(Action="weblogUpdates.ping"
)]
       
WeblogUpdatesReply Ping(string weblogName, string
weblogUrl);
    }

I'm expecting some interop bugs since I've done a clean implementation from the specs, so if you find any please let me know.

The code is subject to the Microsoft samples license, which means that you can put it into your (blogging) apps. Enjoy.

Tuesday, August 21, 2007 12:46:33 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback
MSDN | Indigo | WCF | Weblogs
 Monday, August 06, 2007

I wanted to get the blog going again with something more substantial than this (I've got several demos in the pipeline, including an XmlRpcHttpBinding for WCF), but given the circumstances, I'll start with this here.

My wife, the baby and I went to Seafair on Saturday to see the boat races and the air show. It was a beautiful day and we had a lot of fun with friends. On the shuttle bus back to the Eastgate P&R little Eva suddenly (and quite loudly) started demanding food, so we hastily dug up all the necessary stuff from the stroller and that required taking the camera bag off the stroller. So I put the camera bag on the seat right next to me - and that's where I left it. Pretty stupid. So if someone found it and finds this post through a search  ... clemensv@microsoft.com

Sigh!

Monday, August 06, 2007 12:06:10 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

 Wednesday, June 27, 2007

Eva Tag 3 001.JPG

 

Now that’s what I call shipping a successful project. My wife Sabine gave birth to a beautiful daughter on Monday afternoon. Sabine and Eva are doing perfectly well, we’re actually getting good sleep between feedings and everyone is happy. Stats: born 25 June 2007, Bellevue, 3579 grams, 52 cm.

A big “Thank You” to the awesome staff at Overlake Hospital in Bellevue and Dr. Mitchell Nudelman and staff for their support.

Wednesday, June 27, 2007 8:20:42 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [27] - Trackback

 Monday, June 04, 2007

As Scott says, work on DasBlog is still happening and the project is getting ready for the very last ASP.NET 1.1 release before moving on to the ASP.NET 2.0 model and being fully compatible with the 2.0 runtime. You can run it on 2.0 today without any problems, but since the project has been committed to 1.1 compatibility so far, there were quite a bit of things that weren't possible to change.

Once the project switches over to be "native" on the CLR/BCL 2.0 (we're discussing the actual target framework version), I'll rejoin the effort and I already have several truckloads of new features or changes in the wait loop. You'll be surprised what that little engine will learn to do over the next several months.... ;)

Monday, June 04, 2007 12:32:55 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback
Blog
 Tuesday, May 22, 2007

As announced, if you are subscribed to my blog at friends.newtelligence.net or staff.newtelligence.net or have the site address in your favorites, now is the time to update those links. The old addresses permanently redirect to the new site and the associated webserver might in fact go away within a few weeks. 

http://vasters.com/clemensv is the new place. Thanks, Richard.

Tuesday, May 22, 2007 7:39:11 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [1] - Trackback
Blog
 Wednesday, May 16, 2007

Having an Internet Service Bus up in the cloud is not very entertaining unless there are services in the bus. Therefore, I built one (and already showed some of the code basics) that’s hopefully fun to play with and will soon share the first version with you after some scrubbing and pending a few updates to the ISB that will optimize the authentication process. It’s a 0.1 version and an experiment. The code download should be ready in the next two weeks, including those adjustments. But you can actually play with parts of it today without compiling or installing anything. The info is at the bottom of this post.

To make matters really interesting, this sample not only shows how to plug a service into the cloud and call it from some Console app, but is a combo of two rather unusual hosts for WCF services: A Windows Live Messenger Add-In that acts as the server, and a Windows Vista Sidebar gadget that acts as the client.

Since the Silicon Valley scene is currently all over Twitter and clones of Twitter are apparently popping up somewhere every day, I thought I could easily provide fodder to the proponents of the alleged Microsoft tradition of purely relying on copying other’s ideas and clone them as well ;-)  Well, no, maybe not. This is a bit different.

TweetieBot is an example of a simple personal service. If you choose to host it, you own it, you run it, you control it. The data is held nowhere but on your personal machine and it’s using the BizTalk Services ISB to stick its head up into the cloud and at a stable endpoint so that its easily reachable for a circle of friends, bridging the common obstacles of dynamic IPs, firewalls and NAT. No need to use UPnP or open up ports on your router. If you choose to do so, you can encrypt traffic so that there’s no chance that anyone looking at our ISB nor anyone else can see the what’s actually going across the wire.

Right now, lots of the Web 2.0 world lives on the assumption that everything needs to live at central places and that community forms around ad-driven hubs. The mainframe folks had a similar stance in the 70s and 80s and then Personal Computers came along. The pendulum is always swinging and I have little doubt that it will swing back to “personal” once more and that the federation of personal services will seriously challenge the hub model once more.

So what does the sample do? As indicated, TweetieBot is a bot that plugs into a Windows Live Messenger using a simple Add-In. Bart De Smet has a brilliant summary for how to build such Add-Ins. When the Add-In is active and someone chats the bot, it answers politely and remembers the chat line, time and sender. The bird has a leaky long term memory, though. It forgets everything past the last 40 lines.

Where it gets interesting is that the Add-In can stick three endpoints into the BizTalk Services ISB:

  • A Request/Response Web Service that allows retrieving the list of the last 40 (or less) “tweets” and also allows client to submit tweets programmatically.
  • An RSS service that allows (right now) anyone to peek in to the chat log of the last 40 tweets.
  • An Event service that allows subscribers to get real-time notifications whenever a new tweet is recorded.

The accompanying Sidebar Gadget, which is implemented using WPF, is a client for two of these services.

 When you drop the Gadget on the Sidebar, it will prompt for the IM address of the TweetieBot service you’d like to subscribe to. Once you’ve authenticated at the relay using your registered Information Card, the gadget will pull and show the current list of Tweets and subscribe to the Events service for real-time updates. And whenever someone chats the bot, the Sidebar gadget will immediately show the new entry. So even though the Gadget lives on some client machine that’s hidden between several layers of firewalls and behind NAT, it can actually get push-style event notifications through the cloud!

“How do I send events to clients?” must be one of the most frequent questions that I’ve been asked about Web Services in the past several years. Well, this is your answer right here.

While I’m still toying around with the code and the guys on the 1st floor in my building are doing some tweaks on the ISB infrastructure to make multi-endpoint authentication simpler, you can already play with the bot and help me a bit:

Using Windows Live Messenger you can chat (click here) tweetiebot@hotmail.com now. Drop a few lines. If the bot is online (which means that I’m not tinkering with it) it will reply. Then look at this RSS feed [1] and you can see what you and everyone else have been telling the bot recently. Enjoy.

[1] http://connect.biztalk.net/services/tweetiebot/tweetiebot%40hotmail.com/rss

Wednesday, May 16, 2007 12:33:48 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback
Technology | BizTalk | ISB | WCF
 Tuesday, May 15, 2007

Windows Live Alerts  I must have lived under a rock for the past several months so that I didn't see this service. Anyways, if this works as advertised, subscribing to Live Alerts using the button in this post (and the one under the blog calendar) will have Live alert you whenever my feed gets updated.

Tuesday, May 15, 2007 10:46:25 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback
Blog

Abgestiegen. Macht nix. Wer Fan der einzig wahren Borussia ist, hat gelernt zu leiden. Wer keine Tore macht, steigt halt ab. 

Jeden Samstag brav um 6:15 Uhr morgens hier in Kirkland aufstehen um durch sensationellen technischen Aufwand Borussia live via Arena und zwei verlinkte Rechner und einen 400KBps Privatstream Woche fuer Woche verlieren zu sehen. Das ist Treue! (Oder grandiose, teure Dummheit). Naechstes Jahr halt Sonntags und Freitag oder Montag. Dann wird aber aufgezeichnet. 

Ach ja, und Bayern wird nicht Meister. Und Schlacke 04 auch nicht. Das ist ja schonmal was. Und Aachen steigt mit ab und Köln nicht auf. Das ist auch was ;-)

 

Tuesday, May 15, 2007 9:36:18 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [1] - Trackback
Borussia

Changes come little by little. My blog is moving. It's still sitting on the same server in Germany, but in order to take all of you with me to the new home I've flipped the switch on the domain name already. So if you are subscribed to staff.newtelligence.net/com or friends.newtelligence.net/com, this is a good time to edit that entry. Either point to http://vasters.com/clemensv/rss.ashx or directly subscribe to the Feedburner mirror at http://feeds.feedburner.com/clemensv where the first URL redirects to.

Tuesday, May 15, 2007 8:48:35 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback
Blog
 Wednesday, May 09, 2007

Mary Jo,

I don't really want to disagree with you in public, but in this instance I really think I have to. In your latest blog post you equate "community" to "everything open-source" and I don't think that makes sense. Is there a "Microsoft Community?". Sure, there is. There are active user groups with tens of thousands of members across the world focusing on all kind of aspects around Microsoft products that exist in independence or under the umbrella of INETA, Culminis or Mindshare. There are fantastic developer community sites out there like CodeProject, DotNetJunkies or ASPAlliance, we have a whole network of Microsoft-driven community sites with a lot of community engagement in forums and community samples (ASP.NET, IIS.NET, etc.) and CodePlex is actually quite impressive for hosting open source projects. The code for this blog engine is on SourceForge along with hundreds and hundreds of Win32 and .NET based other projects. 

It goes further. How about JorDev in Jordan? How about Developers.ie in Ireland? CodeZone.de in Germany? NNUG in Norway? SDN in The Netherlands? GotDotNet.RU in Russia? I could continue this list for several pages. And a lot of these groups speak and publish in their local language so their activities don't pop-up on the New York, Redmond, or Silicon Valley radar screens. In the last 4 years before joining the firm I've spoken at some 250 events in over 40 countries and I can tell you, the community you say is missing is there and very much alive. We even seem to have rabid fanboys like Apple, if someone were to believe this unbiased complaint ;-)

But to the heart of your story. You write "When the vendor whose technology you are using doesn't require your participation to create/advance its products, you tend to feel less personally vested in that vendor." The reality looks different. We require that participation and that participation happens. In fact, customer-defined requirements and quality gates are part of our release criteria these days. We broadly engage in technical discussions in blogs, we invite and solicit opinion from industry luminaries, we listen very closely to what people have to say in the forums (and file bugs and design change requests as the result of it), we speak to customers on on-site visits, we run small and big Software Design Reviews previewing and discussing very early bits or just raw ideas (my division ran such an event right after MIX on the 1st floor of the Venetian Convention Center), and there's a a lot of email (and IM discussions) going back and forth with individuals on a daily basis that helps us doing the right thing. And we're not shy changing plans if we're being told that we're not doing the right thing.

The only thing that we don't do is allowing everyone coming along to check out files from our source code depot and start coding along. If people really want to do work on the internals of the .NET Framework, we'll figure out their skills (as even open source projects eventually end up doing as they succeed and grow), see what parts of the code they can best work on for design, code or test, and hire them if it's a fit.

Lastly, to your question "Could/should Microsoft try to make Visual Studio running on Windows more appealing to Linux developers and deployers? Port Microsoft Office or SQL Server to Linux?". Should we? Not mine to decide. This point isn't about "community", at all, I believe. There's a huge, world-wide community that focuses on Windows and the .NET Framework. A significant part of the open source community build software that runs on Windows - and in very many instances even exclusively on Windows. Isn't that the community we should care about in the first place?

As much as folks with vested interest want to play the story that way, the open source community isn't all about Linux (let alone Java). I don't think anyone at Microsoft needs to have "Slashdot envy" as Scoble once put it. Our community does fantastic work and does a lot of it. It'd be nice if you'd recognize them for it.

And you write "Even though Microsoft and its products have helped a number of resellers, software vendors, peripheral makers, consultants and programmers carve out a living for themselves, most of these folks seem to consider Microsoft a job, not an adventure."  The adventure made me move from Germany to Redmond and work for the firm. The adventure has made me lots of friends all across the world. I love this stuff. So do my friends. It'd be nice if you'd recognize that as well.

Have a great day!
Clemens 

PS: I'm not cross-posting this to the MSDN blog as I usually do these days. This is my personal opinion and one motivated by me feeling to be very much a member of the community that you say doesn't exist.

Wednesday, May 09, 2007 3:26:23 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [4] - Trackback
Blog