How to set up Office Communicator (for OCO/BPOS) in an alternate chat client (Pidgin)

by Grank July 30, 2010 15:05

I've got to blog on this one, because it was both maddening and seemingly obscure.  (Whenever I can't get a good search result on something, I make a point of blogging on it myself.)

For a long time now, I've used one chat client to handle all of my online presences: my personal Live Messenger (MSN), 3 Google Talk accounts (personal, corporate, and ENTS), Facebook Chat (which is XMPP compliant these days), IRC, even Twitter (though that started to drive me nuts so I stopped using it).  I've tried a few different programs, and am currently finding that Pidgin (formerly Gaim) is my personal best choice for everyday use.

Over the past few months, the office has been transitioning from our existing infrastructure, which was a cobbled-together assortment of SaaS/cloud solutions out there on the interwebs (sort of single-responsibility, pick-the-best-service-for-each-task idea) to a more narrow, integrated approach that reflects our firm commitment to Microsoft software products and solutions.  Part of that has meant moving from Google Apps for our email, calendar, contacts, and chat, to Microsoft Business Productivity Online Standard Suite (BPOS), which among other things gives us Exchange Online for our email, calendar, and contacts, and Office Communications Online (OCO) for our company chat.

While GTalk was obviously a zero-effort add to my all-in-one presence via Pidgin, Office Communicator proved a much more difficult beast to integrate.

The first question was fundamental: what is the server name?

I searched for this quite heavily, to no avail, and eventually had to give in and actually install Office Communicator, dreading having to use more than one chat client.  See, with BPOS, there's a Single Sign-On app that sits in your tray, and automatically configures Communicator for you.  The upside, as I pleasantly discovered, is that even though you never get to enter or know the communications server address, if you open up your Communicator options after successfully signing in and have a look at the Advanced account options, you can just read off the screen the manual configuration that Single Sign-On did.

Now, Pidgin didn't always support Communicator out-of-the-box, and any information you read about it will suggest that's still the case.  Office Communicator implements a version of the standardized SIP/SIMPLE protocol, but Microsoft added enough of their own (clearly documented but non-standard) stuff to it that just using SIP/SIMPLE won't work.  The good news is that there's a very good third-party plugin called SIPe that adds support for Office Communicator to Pidgin.  You might have to install this yourself, as I can't find any indication of where it might have been merged into the trunk, but the Windows binary I have had it already installed, and "Office Communicator" actually appeared as a protocol choice in the Pidgin account management tool already.

The settings with which I had (eventual) success when adding the account to Pidgin were as follows:
Username: my full email address
Login: just my login name; I didn't put a domain name or full email address
Password obviously.
Now head to the Advanced tab, and put in your server and port you got from the Communicator settings (mine was pool1.oconline.microsoftonline.com:443, which looks probably pretty standard, but I'm sure that could change at any time).
Connection type has to be SSL/TLS, obviously.
Don't check Kerberos, but check Single Sign-On.

Here's where it got tricky:
If you just leave it at that, you'll get an irritating error message.


You have been rejected by the server: You are currently not using the recommended version of the client.


Well yes, Microsoft, I do realise that.  Unfortunately, when they say "recommended", they actually mean mandatory; this is the header message of a 403 Forbidden that your Pidgin has just been sent.

You probably noticed the User Agent field that I skipped over in the Pidgin settings, because I didn't know what to do with it when I was first setting this up and assumed it was optional.  As it turns out, this is actually used in a SIP header just like the User-Agent of a web request, and OCS strictly adheres to it when deciding if it can support you (so says the Microsoft SIP registration extensions documentation).

So, I guess we need Pidgin to speak OCS's secret password before it can get into the Communicator clubhouse.

You could connect with Communicator and sniff for that if you're feeling ambitious, but let me save you some time.  Here's a really handy unrelated blog entry that shows us a great example of some functioning OCS SIP headers, including a User-Agent that matches my installed Communicator version.

So I set my User Agent field in the Pidgin account settings to "UCCAPI/3.5.6907.0 OC/3.5.6907.0 (Microsoft Office Communicator 2007 R2)", and now it works as expected.

It's quite likely this could break once new versions of Communicator come out, as OCS will probably expect you to upgrade the client, and it's also possible that, if that happens and you pass the new User-Agent string for the new version, you'll experience some bugs or quirks or unsupported behavior.  Right now, however, with my build of Pidgin 2.6.6 which integrates SIPe 1.10.0, it's perfectly compatible with Communicator 2007 R2 3.5.6907.0.

Hope someone out there gets use out of this write-up!

TFS Integration for Source Control in Blend 4, and why it might not be working for you

by Grank May 28, 2010 11:03

Since I haven't written here in a while, I thought I'd toss out this quick tip while it's on my mind.

Working with Expression Blend for WPF or Silverlight can be gratifying.  Sketchflow in particular is a great way to rapidly develop clickable prototypes.  Of course, especially if you're working on a Blend project as a team, you'll want to be using version control with a source repository.  Turns out that Blend 4 has TFS 2010 integration built in (and it can be enabled for Blend 3 via patches for both Blend and TFS 2008).

However, if you're working in Blend, you may find the path to that a little convoluted.

See, you can't actually initially add a project to source control from within Blend. 

At first, I had created the project in Blend, and then when we got to the point where wanted to work on it as a team, we used the Source Control Explorer in Visual Studio 2010 to map the path and check the files into TFS source control.  However, there was no integration with Blend, which was painful, as files would have to be manually checked out through Visual Studio and then manually checked back in.  More painfully, new files added to the project would not be picked up and would have to be manually added. 

This frustrated me enough (and made me start worrying about potentially sticky bad-merging scenarios) to see if the Internet knew of any way to make Blend behave the same way as Visual Studio does with regards to source controlled projects... only to find that it's supposed to already be a part of Blend 4.  So why wasn't it working?

After a little poking and prodding, I finally realised that although the files were in source control, the solution and project files were not BOUND to source control.

This is not something you can accomplish via Blend.  However, if you close Blend, open the solution in Visual Studio, go to File > Source Control > Change Source Control..., select each item listed and click Bind, since the containing folder is already mapped to a source repository folder and the solution and project files are in source control it'll pick up the correct binding.  Save and close Visual Studio, and then open the solution in Blend again, and voila!  Blend is now aware of TFS!  You can check files in and out manually from the Projects pane, files will automatically be checked out when you edit them in Blend, and new files added to the project will automatically be added to source control, just like in Visual Studio.

This is one of those things that seems really self-evident after you recognize it, but you might be like me and not recognize it right away.  So here it is blogged for the benefit of your Google search results.

Use Silverlight style resources to style *any* property, not just the boring ones!

by Grank October 08, 2009 13:53

So, as I mentioned last time, when working with Silverlight you'll sometimes run into properties that you'd love to set in a style resource in markup, but can't.  You can almost always hack around that, though, wrapping it in your own attached dependency property.  Pull up a chair and I'll show you how to do that!

Since I can't think of a good example (which I'll explain after), we're going to do something maybe a little bit silly: use a style resource to set the Grid.Column property.  It's not entirely arbitrary; when you're working with grids, and then you have to insert a row or column in the middle, it's not very fun to go and change the Grid attached properties on every element in the grid.  This isn't a great way to deal with this but it does make a good example (it'd be a decent way to deal with it if the framework provided a way to assign or inherit multiple styles as I mentioned last time, but oh well).

Let's consider the following user control xaml:

    <UserControl.Resources>
        <Style x:Name="Buttons" TargetType="Button">
        </Style>
        <Style x:Name="TextBoxes" TargetType="TextBox">
            <Setter Property="Height" Value="30"/>
            <Setter Property="VerticalAlignment" Value="Top"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style x:Name="TextBlocks" TargetType="TextBlock">
            <Setter Property="Height" Value="30"/>
            <Setter Property="VerticalAlignment" Value="Bottom"/>
            <Setter Property="HorizontalAlignment" Value="Right"/>
        </Style>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" ShowGridLines="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="100"/>
            <RowDefinition Height="100"/>
        </Grid.RowDefinitions>

        <Button Content="Button 1" Grid.Row="0" Style="{StaticResource Buttons}"/>
        <Button Content="Button 2" Grid.Row="1" Style="{StaticResource Buttons}"/>
        <Button Content="Button 3" Grid.Row="2" Style="{StaticResource Buttons}"/>

        <TextBox Text="TextBox 1" Grid.Row="0" Style="{StaticResource TextBoxes}"/>
        <TextBox Text="TextBox 2" Grid.Row="1" Style="{StaticResource TextBoxes}"/>
        <TextBox Text="TextBox 3" Grid.Row="2" Style="{StaticResource TextBoxes}"/>

        <TextBlock Text="TextBlock 1" Grid.Row="0" Style="{StaticResource TextBlocks}"/>
        <TextBlock Text="TextBlock 2" Grid.Row="1" Style="{StaticResource TextBlocks}"/>
        <TextBlock Text="TextBlock 3" Grid.Row="2" Style="{StaticResource TextBlocks}"/>
    </Grid>

We get this somewhat less than desirable output:

 

 

Here's how I justify this as more than just a lame example; we can specify the grid column in the style for all the textblocks, textboxes, and buttons on this control, so if we need to add another column we only have to change the values in one place.  What we need to do is add an attached dependency property.  For the sake of simplicity, I'm going to add it to the default control we're playing around with, but if you wanted to do this in lots of places you'd probably want to put it in a static class.

There's actually a snippet in Visual Studio for attached dependency properties; "propa" [TAB] will get you started.

Completing the snippet (and noting that in WPF it's UIPropertyMetadata but for Silverlight we have to change it to just PropertyMetadata), we've got this:

        public static int GetGridColumn(DependencyObject obj)
        {
            return (int)obj.GetValue(GridColumnProperty);
        }

        public static void SetGridColumn(DependencyObject obj, int value)
        {
            obj.SetValue(GridColumnProperty, value);
        }

        public static readonly DependencyProperty GridColumnProperty =
                                                DependencyProperty.RegisterAttached(
                                                "GridColumn", 
                                                typeof(int), 
                                                typeof(MainPage), 
                                                new PropertyMetadata(0));

The fun part comes with the overload for the PropertyMetadata constructor that lets us specify a callback for when the value changes.  The signature for the callback gives us the DependencyObject to which the property is attached, and event args inside which we can find the NewValue.  So in the handler there, we can run whatever line of code we want with both of those values.

        public static readonly DependencyProperty GridColumnProperty =
                                                DependencyProperty.RegisterAttached(
                                                "GridColumn", 
                                                typeof(int), 
                                                typeof(MainPage), 
                                                new PropertyMetadata(OnGridColumnChanged));
                                                
        private static void OnGridColumnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            d.SetValue(Grid.ColumnProperty, e.NewValue);
        }        

Now we just need to add those values to our style resources block:

    <UserControl.Resources>
        <Style x:Name="Buttons" TargetType="Button">
            <Setter Property="this:MainPage.GridColumn" Value="2"/>
        </Style>
        <Style x:Name="TextBoxes" TargetType="TextBox">
            <Setter Property="this:MainPage.GridColumn" Value="1"/>
            <Setter Property="Height" Value="30"/>
            <Setter Property="VerticalAlignment" Value="Top"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style x:Name="TextBlocks" TargetType="TextBlock">
            <Setter Property="this:MainPage.GridColumn" Value="0"/>
            <Setter Property="Height" Value="30"/>
            <Setter Property="VerticalAlignment" Value="Bottom"/>
            <Setter Property="HorizontalAlignment" Value="Right"/>
        </Style>
    </UserControl.Resources>

And lo, the output looks much more sane:

 

Yknow, in theory, we don't even have to use this to set other properties... If you wanted to, you could use this approach to run arbitrary code as a result of a style being applied, by just tossing whatever code you want into your changed handler.  In some situations that might be a cool way to assign some behavior.

I did say at the beginning that I'd explain why I didn't have a better example.  Truth be told, the reason I was looking into this in the first place was because I wanted to set Telerik's StyleManager.Theme in a style resource for all my buttons on a user control.  Unfortunately, although this method would work great in theory, the reality of that particular situation is that as their StyleManager sets the theme, it removes the current style and thus it resets itself right before applying and we see no effect.  I thought I was being clever...  Oh well.

"Cascading" styles in Silverlight 3

by Grank October 05, 2009 14:29

One of the things that was slightly uncomfortable about working with Silverlight 2 was Style resources, specifically that you couldn't cascade them.  Those of us used to using CSS to style web applications found that to interfere with our ability to leverage style resources effectively.

Fortunately, in Silverlight 3, they seem to have addressed this problem, albeit not completely.  In SL 3, they have added a "BasedOn" attribute to the markup for a style, which can point to another style, like so:

<UserControl.Resources>
<Style x:Name="ButtonSize" TargetType="Button">
<Setter Property="Height" Value="30" />
<Setter Property="Width" Value="65" />
<Setter Property="Margin" Value="5" />
</Style>
<Style x:Name="GreenButton" TargetType="Button" BasedOn="{StaticResource ButtonSize}">
<Setter Property="Background" Value="#FF00FF00" />
</Style>
</UserControl.Resources>

A button with Style="{StaticResource GreenButton}" will now have the height, width, and margin of ButtonSize as well.

Where CSS is more general, applying by selector and precedence, this is very concrete.  It's really much more analagous to inheritance in C# or VB.NET.  There doesn't seem (at least as far as I can see) to be a way to use multiple styles like one can assign multiple classes to an element with CSS, but you can chain as many BasedOn Styles as you want, so that hopefully shouldn't limit you too much.

Next post, I'll show you a trick to style (and animate, for that matter) a static attached property or other unavailable or non-dependency property.

Tags: , , , , ,

Awesome: Visual Studio Content Installer

by Grank September 30, 2009 10:52

Sometimes you have things like code snippets or project templates that you want to share with your team or even with the whole wide webbernets.  If you're anything like me, you'd just post the content itself and let the recipients install that stuff manually in their Visual Studio...

Turns out there's a WAY easier way, about which I never knew until today!

You can create a .vsi file, which is already associated with some sort of VS component called Visual Studio Content Installer, and just open it to get prompted through installation of your content.

All you have to do is write a .vscontent file (which is just XML telling VSCI what these files are and what to do with them; here's the wonderfully-easy-to-grok schema reference for that), zip it up with the content, and rename the .zip to .vsi.

Srsly, that's it.  Now anyone can double-click to install your useful snippets and what not!  (Pro Tip: if you're using StyleCop for ReSharper and you're the only one on your team who's doing so and their formatting is driving you CRAZY, maybe if you can't make them make that leap you'd be able to make them leap to using a snippet for some of the patterns that consistently annoy you ;)

I don't have time at the moment to look into this further as I'm kinda busy, but I wouldn't be surprised if someone had written a quick interface for generating .vscontent files, and if no one has, I think I will as soon as I get a spare second.  I'll let you know if I ever do!

Dear Microsoft...

by Grank September 25, 2009 13:27

Preface: Anyone who knows me well in person knows that I am very much a man with opinions and am not afraid to share them with people.  However, I usually hate positioning my opinions in the public domain in written form, because I know that while I tend to rant passionately, I also re-evaluate constantly, and hate to be tied down without room to manouver and change my mind if I find myself mistaken.  Expressing ones frustrations off the record orally over beers or what not is one thing, but in this age of instant no-cost transmission and duplication, and with resources like the Wayback Machine always looming over ones shoulder, the truth is that once you put something out there in written form, you can never really take it back.  As such, I've always tried to steer clear of that kind of writing in this blog (in fact made me reluctant to ever start a blog at all) and for the most part have succeeded, focusing on the technical and verifiable and injecting my opinion and commentary in the form of style and sass here and there rather than outright diatribe.
However, I just responded to a survey Microsoft sent out to Certified Professionals, and found myself getting things off my chest in a little "how can we improve" box that was clearly not intended to take on this kind of dialectical heft.  Since it's been written already, and I don't think there's anything surprising or unfair about my opinion, I think I will put it up for you all to read and debate if you'd like.  (It appears as I sent it in the survey, with the exception that I've added some hyperlinks for your amusement.) Enjoy!


As someone who uses a lot of Microsoft products at work and at home across several machines and platforms, the lack of care in some install processes has been a major irritation.  Despite Ballmer's famous rant, Microsoft continually alienates developers by wasting their time with broken or overly obfuscated installer hoops to jump through for the privilege of using the software, and no improvements are made in this area because Microsoft recognizes people using development-related tools are technical enough to figure out, handle and put up with it.


One example is the difficulty installing SQL Server 2008 on Windows 7, your much-trumpeted new flagship operating system which is deserving of its praise.  Unfortunately, SQL 2008 RTM won't install properly on it; SQL 2008 SP1 is required.  However, though there are four different install packages for SQL 2008 Express, only ONE of them has been updated with SP1 and it's the most limited, containing only the database engine itself. (This is very frustrating when you download a 500 mb file that's supposed to contain everything and then leave your internet access for the weekend only to find you can't install it!)  Furthermore, one can't just use the SP1 base installer to get the database engine running and then run the RTM Tools or RTM Advanced Services installer to add features to the instance, because someone decided that it doesn't matter what's actually available to the install package being run, it'll only be able to add features to an instance based on what was available when it was first installed! [Note: I made that a link for you blog readers because it explains the problem, but the solution suggested in it doesn't work in this case.] So the "best" way I found to get SQLX08 working on Windows 7 with SSMS is to install the RTM and let it FAIL, (which will still have installed Management Studio just no working database engine), and then install the SP1 base overtop.  That's outrageous!  Why haven't those installers been updated with SP1 by now, let alone why wasn't it done immediately when SP1 came out!


Visual Studio 2008 is another example of a horrible install process.  I rely on the features and fixes of VS 2008 SP1, as well as features exclusive to Team Edition, as well as features exclusive to Database Edition.  There is NO full VS08 SP1 download nor any way to slipstream the service pack into your initial install, so every developer in the Microsoft sphere is stuck going through the lengthy VS08 RTM install process and then going through the even lengthier VS08 SP1 patch process when in all sanity the latter should be eliminated by now.  Furthermore, the only way to get the features that are unique Team Edition and Database Edition all into one VS instance is to install Team and then install Database overtop of Team.  (It's critical that one do this BEFORE doing SP1, however.)  So basically I have to install Visual Studio 2008 three times just to get the environment I want.  That's pretty much a whole day wasted needlessly, any time I have to set up a new or refreshed development environment.


I recently started doing development for Surface.  This is a fantastic, exciting new piece of technology that is somewhat crippled by, once again, making the software process difficult for developers.  The Workstation Edition of the Surface SDK will only work in 32-bit Vista.  My workstation at work is 64-bit Server 2008, and all of my machines at home are 64-bit Windows 7.  Surface development can't even be done on a VM or via RDP, as it often requires Direct3D, and performance would be unusably horrible even if that worked in those scenarios.  So I was forced to repartition one of my Windows 7 machines and dual-boot it with 32-bit Vista just to be able to write apps for Surface while not tethered to the physical Surface table.  Being forced to create an entire dedicated root-level operating system just to run one program is an awful user experience, and already feeling at home in my Windows 7 partition and faced with the prospect of rebooting just to work on my Surface apps, well that's destroyed my multitasking and my willingness to do Surface work will suffer as a result.


These are just a few examples of a consistent pattern of carelessness with installers for developer and server tools.  Other examples that come to mind are having to disable Software Restriction Policies in order to install VS 2005 SP1 (because the install is so large that the hash check literally can't be calculated without running out of the RAM the system gives the hash check process), and a bug in the SQL Server 2008 Enterprise x64 installer where it would ignore the specified installation folder and look for files it had just placed there in the default folder instead, thus failing install.  I'm sure I have a lot more examples that just aren't coming to mind at the moment but these are already far too many.


Microsoft has positioned itself as an industry leader in software development and data management, and has a number of excellent software products that support that position.  It's obvious, however, that not enough attention has been spent looking at what us often blindingly loyal members of the developer community are put through in order to get all that software into a usable state.  Until progress is made in that area, experiences writing applications on any Microsoft app stacks will continue to be bitter ones.

-------------------------------------------------------------------------

 

Edit:  Some have expressed some curiosity about whether or not I got a response to this from Microsoft, and how positive or negative it was...  While the survey I answered was not the kind designed to generate two-way communication, I did hear from a Developer Advisor/Evangelist at Microsoft Canada whom I've had the pleasure of meeting at a number of conferences (and who apparently reads my tweets), who sent me a couple of encouraging DMs:

 

him: Nice post! Clearly, there's more work that we need to do. BTW, if you have questions, please drop me a line; 555-555-5555(redacted)

me: Thanks man. I hate speaking up, as I know those who hear and care (MS evangelists like you, thx btw) aren't the ones coding that stuff!

him: Any feedback is good feedback. Don't ever be afraid to let me/us know what's on your mind. We can/need to do a lot better.

Tags: , , ,

MonoTouch released!

by Grank September 14, 2009 09:48

I know a lot of people have been waiting to see a .NET framework for mobile platforms other than Windows Mobile...

Today, MonoTouch officially went 1.0, meaning that wait is over.

Unfortunately, it's not a free product, in fact it carries a heavy price tag.  But if you've got a great idea that'll sell well at the App Store, but you don't have time to learn Objective-C, maybe this is a great value proposition for you!

No real news or word about an official Microsoft offering in this area.  There were certainly a lot of rumors around them working on it at one point, but now that Novell has a commercial product, I imagine they'd find it difficult to release their own for free...  Oh well, expensive options are better than no options!

Tags: , , , , , , , , ,

Resolving security issues hosting a WCF service in IIS

by Grank September 11, 2009 11:32

This past week I've been working on some Silverlight controls that need to be hosted in and deal with users and groups in SharePoint, as well as their own tables in a SQL database.

This has meant hosting a WCF service below the SharePoint app so it can access some SharePoint context objects, and that has been an adventure.  I will save you the gory details and just link you to Sahil Malak's outstanding series of posts on SharePoint as a WCF Host. (with the following extra advice:  Read all the parts 1 through 4, but don't start implementing any of it until you read the Real World part 1 post in which he links to a wsp that does most of the annoying heavy lifting for you.  Don't waste your time implementing manually, just read the other posts so you understand what's happening.)

All that having been said and done, I still had no end of trouble making the endpoint work, due to the dreaded security configuration... 

One thing you need to know about WCF is that it's pretty pragmatic about security: it's not going to let you send a username and password in plain text. (Well, unless you go through the trouble of adding and parsing and validating it manually, but then you're just being a brat.  Take the framework's implicit advice and don't ever send credentials in plain text!)  Basically, any combination of mode, transport, and message settings in the security node of your binding declaration that would lead to plain text credentials will lead to one InvalidOperationException or NotSupportedException or another. 

Since we're consuming the WCF service using Silverlight, we need to use basicHttpBinding.  By default that uses and requires anonymous access.  We're in SharePoint, and our authentication methods include integrated Windows authentication and Forms authentication.  Anonymous access to this site is not allowed, and we don't want to enable it.  So our first attempt yields the following exception:

Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.

Okay, that's reasonable.  So, as a first attempt, we could try and secure it by using the Forms authentication. (In this case we actually don't want the Forms users to have access, but we'll explore that option.)  So let's set the security mode to message and give it a message element with clientCredentialType="UserName"...

BasicHttp binding requires that BasicHttpBinding.Security.Message.ClientCredentialType be equivalent to the BasicHttpMessageCredentialType.Certificate credential type for secure messages. Select Transport or TransportWithMessageCredential security for UserName credentials.

Oops.  Right.  That would lead to plain-text passwords.  Reading that exception message, it's actually one of the more helpful ones I've seen.  It makes it clear to us that we have the choice of changing the clientCredentialType to "Certificate" (which we can't do because technically that's still anonymous access as far as IIS is concerned and we don't want to turn that on), or changing the security mode to Transport or TransportWithMessageCredential.  What does that mean, you ask?  Well let's try it:

Could not find a base address that matches scheme https for the endpoint with binding BasicHttpBinding. Registered base address schemes are [http].

When those say "Transport", they're referring to promising to WCF that it'll be called through SSL.  So if SSL is not an option for you, this doesn't help you.  Also, remember that all WCF cares about at this point is whether or not you're passing credentials in plain text, but once you get past this point by using https you'll be back to the part where you have to authenticate in a manner that satisfies IIS anyway.

"But wait!" you say, "this endpoint is only accessible from the internal network anyway, and integrated Windows auth over http is fine in this case!"  Well, fortunately you're not out of luck.  WCF will allow this scenario; the magic word is a security mode of "TransportCredentialOnly". Now you give it a transport element with clientCredentialType="Windows" and bam, you're using integrated Windows authentication!

...Except here's where I got stuck.

Doing that didn't make my endpoint start working.  Instead, it gave me this fun message:

 Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service.

 Wait, what?  Of course Windows Authentication is enabled!  It's a SharePoint application hosted in IIS which is USING integrated Windows auth for sign-in. Visiting IIS Manager, we can look and confirm that Integrated Windows authentication is checked.

Here's the thing you need to know about Windows Authentication, if you weren't already aware:  there are two kinds of it.  Windows 2000 and later make use of Kerberos tickets for Windows Auth.  This is a nice and relatively secure option.  Previous to Kerberos being adopted by Microsoft, however, Windows Auth was accomplished using a Microsoft protocol called NTLM, which is less secure, but is OK and still in wide use.  Kerberos is preferred when available, but when it's impossible (you're not on the domain, or there's no Active Directory, or ports Kerberos needs aren't open, or any number of scenarios) then NTLM is automatically used as a fallback.

In the metabase for a site hosted in IIS 5.1 and later, there's a property called NTAuthenticationProviders.  This is a comma-separated list with a couple possible values, and it controls the behavior of Windows Authentication on that IIS site.  The value "NTLM" enables NTLM to be used, obviously.  The value "Negotiate" indicates that Kerberos should be used, unless while negotiating with IIS it's determined that Kerberos isn't possible, in which case NTLM will be used instead.

The default for this value is "Negotiate,NTLM".

For some reason, on my development VM, this was set to just "NTLM".

When you say clientCredentialType="Windows" in your endpoint's binding configuration, you're actually requiring the Negotiate option.  If only NTLM is available, you'll get the strange exception message about Windows Authentication not being enabled even though strictly speaking it is enabled.

I could probably have solved this problem by changing the metabase value back, but I hate touching the metabase and I don't need Kerberos level security for this scenario anyway.  The solution was thus to put clientCredentialType="Ntlm".  This got me up and running... finally.

Tags:

Well that escalated quickly.

by Grank September 04, 2009 10:38

I finally got the chance to get to an ENTS meeting last night...

I now find myself serving as the head of their Events Committee.

I guess I've been in need of an organization to which to lend my organizational skills, obsession with detail, and love of Roberts-style meetings, now that I won't be on the executive for the UAMC for the first time in 5 years.  And the ENTS ideals fall very comfortably in line with my desire to see this city's tech community continue to grow and see the city respond by transitioning to an open-data, tech-oriented metropolis.

I will also have to get my butt in gear if I'm going to write a ribbon-cutting application for our Surface before the grand opening in two weeks!

So there you have it!  If you are interested in using the ENTS facility for an event (recalling that we're still in the process of getting a lot of this stuff set up), getting ENTS members out to your event, joining ENTS and/or my events committee, or really anything else related, get in touch with me at grant at ents dot ca.

Tags: , , , , ,

PostSharp Bug, or "How To Recycle Your Own App Pool"

by Grank July 27, 2009 15:15

PostSharp is a post-compiler for .NET that gives us a cool way to automatically add non-functional requirements like error-handling, tracing, logging, etc. to your assembly, without having to surround every method with handling code or doing a ton of reflection at runtime or anything like that.  In the current project which we're getting ready to roll out to prod, we're using it both to log and report any exceptions thrown out of our business logic, and to keep a detailed log of the requests and responses of all our webservice calls for debugging purposes.  It's truly been a fantastic help, and I'm really not sure what the last few weeks of defect resolution would have looked like without it!

We did run into a problem though. (A common theme on my blog; since when do I just mention something cool without talking about some technical squirming I did?)

Identifying the symptoms and what triggers them came fairly easily.  For some reason, whenever the web.config is updated, say to change an appSettings key perhaps, it causes our application to fail until we recycle the application pool.  The failures come from our PostSharp OnEntry code, and in our case were NullReferenceException, specifically because we were accessing properties on MethodExecutionEventArgs.Method which was mysteriously null.

Identifying the underlying cause is somewhat more difficult.  How does it make any sense to end up in the body of a PostSharp OnEntry method with a null method name?  I'm not too sure about that.  When the web.config is updated, ASP.NET restarts the application in question, but it won't recycle the whole app pool.  The business logic methods that are being wrapped by PostSharp are all in a separate assembly (.Core.dll) from the web UI code (.Web.dll), which probably has something to do with it.  I'm going to make a post on the PostSharp forum and get them to look at this blog entry, so hopefully someone over there will have some idea what's going on and how to fix it.  But in the meantime, here's how we hacked around it!

So basically, we can tell when this is a problem, because we see the eventArgs property that's null.  So why not recycle our own app pool programmatically?  ...Actually that sounds like a weird idea.  But we can do it, so let's.

There are a few bits of information we need.  The first is when specifically to do the recycle, which we know is in OnEntry when eventArgs.Method == null.  The second is the app pool's IIS address.  IIS paths are formatted like so:

IIS://SERVERNAME/W3SVC/AppPools/AppPoolName

So we can get that in context from a couple of environment variables.  Environment.MachineName will get you the server, and Environment.GetEnvironmentVariable("APP_POOL_ID") yields the application pool name.  Other than that the rest shouldn't change.

So what do we do with that path now that we have it?

System.DirectoryServices.DirectoryEntry is a MarshalByRefObject that will encapsulate Active Directory Domain Services functionality, and its Invoke method gives you an interface to make native AD DS calls.  So that gives us a way to initiate a Recycle command to the application pool.

With that now defined, we have a full first crack at implementation ready to go!  Let's see how that looks:

 

public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
 if (eventArgs.Method == null)
 {
  var appPoolPath = string.Format(
    "IIS://{0}/W3SVC/AppPools/{1}",
    Environment.MachineName,
    Environment.GetEnvironmentVariable("APP_POOL_ID"));

  using (var appPoolDS = new DirectoryEntry(appPoolPath))
  {
   appPoolDS.Invoke("Recycle", null);
  }
 }
 
 // the aspect's original functionality
}

Not bad, not bad.  I've trimmed a bunch out here for simplicity that you shouldn't forget though:

  • To do this you need DirectoryServicesPermission, which you may not have.  Impersonating for that out of scope of this blog entry.
  • Depending on your call stack when you get here, you'll likely want to throw an exception after recycling to make sure the thread stops executing.
  • You'll probably want to at least log it to an event log whenever this happens, and possibly notify an administrator.
  • Since you may have a bunch of requests coming into the OnEntry body at around the same time, you might want to set a flag once you start recycling so that you don't end up with multiple calls to recycle.

Tags: , , , , ,

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen | Modified by Mooglegiant

About The Author

I'm a software developer and musician in Edmonton, AB.  I write mostly web-based software, primarily on the Microsoft stack.  I have an MCPD and several MCTS, but I've only been at this whole developer thing for a few years, and the truth is that I'm still learning more than knowing.  So these are my adventures and experiments and some of it will probably be blatantly wrong...  Just warning ya.