<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Joe Kaplan - Windows Security</title>
    <link>http://www.joekaplan.net/</link>
    <description>.NET. LDAP. Geekery.</description>
    <language>en-us</language>
    <copyright>Joseph E. Kaplan</copyright>
    <lastBuildDate>Mon, 25 Sep 2006 04:42:39 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.6264.0</generator>
    <managingEditor>blog@joekaplan.net</managingEditor>
    <webMaster>blog@joekaplan.net</webMaster>
    <item>
      <trackback:ping>http://www.joekaplan.net/Trackback.aspx?guid=637a1db3-198d-4215-ae8f-6b0ee4b3c671</trackback:ping>
      <pingback:server>http://www.joekaplan.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.joekaplan.net/PermaLink,guid,637a1db3-198d-4215-ae8f-6b0ee4b3c671.aspx</pingback:target>
      <dc:creator>Joe Kaplan</dc:creator>
      <wfw:comment>http://www.joekaplan.net/CommentView,guid,637a1db3-198d-4215-ae8f-6b0ee4b3c671.aspx</wfw:comment>
      <wfw:commentRss>http://www.joekaplan.net/SyndicationService.asmx/GetEntryCommentsRss?guid=637a1db3-198d-4215-ae8f-6b0ee4b3c671</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
An interesting thread on LDAP and authentication came up again today on activedir.org. 
In the conversation, I had suggested that it would be a good feature if AD and ADAM
had a setting somewhere that could be enabled that would prevent LDAP simple bind
from working if the network channel was not secured (via SSL).  The problem with
simple bind (for those not in the know) is that the user's credentials are passed
over the network in plaintext, which is potentially a huge security risk (depending
on the network).  It is actually even worse (by just a little) that HTTP basic
authentication, as the credentials aren't even base64 encoded.
</p>
        <p>
Eric Fleischman then pointed out that ADAM actually already has such a switch. 
Tomek blogged about it <a href="http://blogs.dirteam.com/blogs/tomek/archive/2006/09/24/Disable-simple-bind-without-SSL-on-ADAM.aspx">here</a>,
so I'll let him cover the details on how to enable this.
</p>
        <p>
I went on to suggest that AD should also have this feature (off by default for backwards
compat most likely).  The problem is that without this feature, the AD admin
really has no way to prevent apps that use simple bind for auth from sending plaintext
credentials on the network, even if SSL has been configured.  You can't just
turn off port 389 access to AD without breaking other stuff as you might be able to
do in other directories.  Many of the NOS features of AD rely on port 389.
</p>
        <p>
I also suggested adding an ability to audit simple bind attempts over non-SSL channels,
including the IP address, so that admins have a way to track down rogue apps.
</p>
        <p>
In many IT organizations these days, we must specify policies about how we are going
to treat sensitive data (like passwords!) on the network and can get ourselves into
hot water with our auditors if we are found to not be in compliance with our own policies. 
At least with this auditing support in place, violations of the policy can be capture
and violators may be traceable.
</p>
        <p>
Also note that with most ADSI (and System.DirectoryServices programming in .NET),
simple binds are not used.  Windows secure binds (using GSS-SPNEGO, which amounts
to Kerberos or NTLM at the heart of it) are used by default.  You can get a simple
bind, but you must do more work.  As such, most ADSI script code is not likely
to have this problem.  You do have to be careful though.  We go into this
in a great deal more detail in ch. 3 of the <a href="http://www.directoryprogramming.net">book</a>. 
Simple binds are very common with cross platform apps, and especially those that use
non-MS LDAP libraries, as they often do not have the code they need to implement GSS-SPNEGO
at all.  Some of them just use simple bind because it is the lowest common denominator
protocol that all LDAP directories must support.
</p>
        <p>
Anyway, it will be interesting to see if any of these suggestions come to fruition. 
In the mean time, use SSL with your directories (ADAM too!) when doing simple
bind.  Getting certs can be painful, but usually not as painful as getting hacked
or failing an audit.  Unless your networks are totally secure between the endpoints
and there is no threat of snooping, you need a secure channel.  
</p>
        <img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=637a1db3-198d-4215-ae8f-6b0ee4b3c671" />
      </body>
      <title>ADAM Can be Forced to Only Allow Simple Bind on a Secure Channel</title>
      <guid isPermaLink="false">http://www.joekaplan.net/PermaLink,guid,637a1db3-198d-4215-ae8f-6b0ee4b3c671.aspx</guid>
      <link>http://www.joekaplan.net/ADAMCanBeForcedToOnlyAllowSimpleBindOnASecureChannel.aspx</link>
      <pubDate>Mon, 25 Sep 2006 04:42:39 GMT</pubDate>
      <description>&lt;p&gt;
An interesting thread on LDAP and authentication came up again today on activedir.org.&amp;nbsp;
In the conversation, I had suggested that it would be a good feature if AD and ADAM
had a setting somewhere that could be enabled that would prevent LDAP simple bind
from working if the network channel was not secured (via SSL).&amp;nbsp; The problem with
simple bind (for those not in the know) is that the user's credentials are passed
over the network in plaintext, which is potentially a huge security risk (depending
on the network).&amp;nbsp; It is actually even worse (by just a little) that HTTP basic
authentication, as the credentials aren't even base64 encoded.
&lt;/p&gt;
&lt;p&gt;
Eric Fleischman then pointed out that ADAM actually already has such a switch.&amp;nbsp;
Tomek blogged about it &lt;a href="http://blogs.dirteam.com/blogs/tomek/archive/2006/09/24/Disable-simple-bind-without-SSL-on-ADAM.aspx"&gt;here&lt;/a&gt;,
so I'll let him cover the details on how to enable this.
&lt;/p&gt;
&lt;p&gt;
I went on to suggest that AD should also have this feature (off by default for backwards
compat most likely).&amp;nbsp; The problem is that without this feature, the AD admin
really has no way to prevent apps that use simple bind for auth from sending plaintext
credentials on the network, even if SSL has been configured.&amp;nbsp; You can't just
turn off port 389 access to AD without breaking other stuff as you might be able to
do in other directories.&amp;nbsp; Many of the NOS features of AD rely on port 389.
&lt;/p&gt;
&lt;p&gt;
I also suggested adding an ability to audit simple bind attempts over non-SSL channels,
including the IP address, so that admins have a way to track down rogue apps.
&lt;/p&gt;
&lt;p&gt;
In many IT organizations these days, we must specify policies about how we are going
to treat sensitive data (like passwords!) on the network and can get ourselves into
hot water with our auditors if we are found to not be in compliance with our own policies.&amp;nbsp;
At least with this auditing support in place, violations of the policy can be capture
and violators may be traceable.
&lt;/p&gt;
&lt;p&gt;
Also note that with most ADSI (and System.DirectoryServices programming in .NET),
simple binds are not used.&amp;nbsp; Windows secure binds (using GSS-SPNEGO, which amounts
to Kerberos or NTLM at the heart of it) are used by default.&amp;nbsp; You can get a simple
bind, but you must do more work.&amp;nbsp; As such, most ADSI script code is not likely
to have this problem.&amp;nbsp; You do have to be careful though.&amp;nbsp; We go into this
in a great deal more detail in ch. 3 of the &lt;a href="http://www.directoryprogramming.net"&gt;book&lt;/a&gt;.&amp;nbsp;
Simple binds are very common with cross platform apps, and especially those that use
non-MS LDAP libraries, as they often do not have the code they need to implement GSS-SPNEGO
at all.&amp;nbsp; Some of them just use simple bind because it is the lowest common denominator
protocol that all LDAP directories must support.
&lt;/p&gt;
&lt;p&gt;
Anyway, it will be interesting to see if any of these suggestions come to fruition.&amp;nbsp;
In the mean time, use SSL with your directories (ADAM too!)&amp;nbsp;when doing simple
bind.&amp;nbsp; Getting certs can be painful, but usually not as painful as getting hacked
or failing an audit.&amp;nbsp; Unless your networks are totally secure between the endpoints
and there is no threat of snooping, you need a secure channel.&amp;nbsp; 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=637a1db3-198d-4215-ae8f-6b0ee4b3c671" /&gt;</description>
      <comments>http://www.joekaplan.net/CommentView,guid,637a1db3-198d-4215-ae8f-6b0ee4b3c671.aspx</comments>
      <category>LDAP;Windows Security</category>
    </item>
    <item>
      <trackback:ping>http://www.joekaplan.net/Trackback.aspx?guid=9b25d233-a484-4905-a60b-8bb8748c7068</trackback:ping>
      <pingback:server>http://www.joekaplan.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.joekaplan.net/PermaLink,guid,9b25d233-a484-4905-a60b-8bb8748c7068.aspx</pingback:target>
      <dc:creator>Joe Kaplan</dc:creator>
      <wfw:comment>http://www.joekaplan.net/CommentView,guid,9b25d233-a484-4905-a60b-8bb8748c7068.aspx</wfw:comment>
      <wfw:commentRss>http://www.joekaplan.net/SyndicationService.asmx/GetEntryCommentsRss?guid=9b25d233-a484-4905-a60b-8bb8748c7068</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font size="4">Fast Concurrent Binding Overview</font>
        </p>
        <p>
One of the things I alluded to in my <a href="http://www.joekaplan.net/ATaleOfTwoLDAPStacks.aspx">post</a> that
highlighted the differences in capabilities between the ADSI-based System.DirectoryServices
(SDS) namespace and the raw LDAP-based System.DirectoryServices.Protocols (SDS.P)
was the ability to access a feature called <strong><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/using_ldap_for_password_authentication.asp?frame=true">Fast
Concurrent Binding (FCB)</a></strong>.
</p>
        <p>
FCB is a feature available in Active Directory 2003 (and later) and in ADAM. 
To explain it, first let’s cover what happens with a “regular” bind operation in LDAP
against AD or ADAM.  With a normal bind, the user’s credentials are presented
to the LDAP server, either in plaintext format or via the Windows security model if
using a secure binding protocol.  The server then attempts to authenticate these
credentials.  If the credentials are accepted, then the server builds a Windows
token for the user which will be used to for performing security checks on future
operations and changes the state of the current LDAP connection to an authenticated
state so that future requests will continue to use the newly established security
context and this operation is not repeated.  This is the main reason why LDAP
connections are stateful.
</p>
        <p>
FCB eliminates two parts of this equation.  It authenticates the user’s credentials,
but it does not build a Windows token for the user and the connection state stays
anonymous.  As such, the bind operation will give you an “up/down” result based
on whether the user’s name and password were valid, but it won’t let you do anything
else with that connection such as perform searches, except as an anonymous user (which
is pretty limited by default in AD 2003 and ADAM).
</p>
        <p>
The big upside of FCB is that the bind operation is MUCH faster than a normal bind
because the really expensive operation, expanding the user’s group membership to build
the token, is eliminated.  Hence the name <em><strong>fast</strong> concurrent
binding</em>.<sup>*</sup></p>
        <p>
The concurrent part comes from the fact that multiple users can be authenticated on
the same LDAP connection simultaneously without worrying about changing the authenticated
state of the connection, so the expense of setting up and tearing down the associated
socket can also be eliminated.  This makes it potentially even faster.
</p>
        <p>
The big downside with FCB is that it only supports LDAP simple bind, not SASL, and
simple bind does not have a built in mechanism for protecting the credentials on the
wire like the various SASL mechanisms do.  <strong>As such, it is never safe
to use FCB unless some form of transport security is used such as SSL or IPSEC!</strong></p>
        <p>
          <font size="4">When to Use Fast Concurrent Binding</font>
        </p>
        <p>
          <strong>Do</strong> use FCB when your application is doing pure authentication of
credentials via LDAP.  An example of this might be in a web-based application
that uses AD or ADAM as a user store and does LDAP authentication.  If you just
need a “yes/no” vote as to whether a username/password combo is good, FCB will give
you the best performance and may add a significant scalability increase to your application
as a result.  
</p>
        <p>
          <strong>Do not</strong> use FCB if you need to authenticate and then perform operations
against the directory on the user’s behalf (a delegation scenario from the architectural
perspective, although not necessarily using Windows Kerberos delegation features to
implement it).  Since the connection state does not change to “authenticated”,
the user’s credentials will not be used to perform subsequent operations and you won’t
get what you want.
</p>
        <p>
An obvious place where you might want to use FCB would be in something like the ActiveDirectoryMembershipProvider
in ASP.NET 2.0.  My understanding is that the development already thought about
this and tried to add this support already.  Thus, you may already have this
and not even know it!
</p>
        <p>
Another obvious place for this to be used would be in ADFS for authenticating users
in the ADAM store and potentially with users in the AD store as well when used with
the Federation Service Proxy (which accepts credentials via a forms or basic auth
interface in plaintext form).  As of this writing, I do not believe that ADFS
is taking advantage of this feature (or and SDS.P capabilities for that matter). 
Note to product team…
</p>
        <p>
          <font size="4">A Note on ADSI/SDS and Fast Concurrent Binding</font>
        </p>
        <p>
          <em>Hey Joe, I see that ADSI and SDS have an <font face="Courier New">AuthenticationTypes</font> flag
called <font face="Courier New">FastBind</font>.  Can’t I just use that to get
FCB?  Why are you telling me this requires SDS.P?</em>
        </p>
        <p>
The answer here is “no”, they are not the same thing, despite their unfortunately
similar names!  <font face="Courier New"><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/fast_binding_option_for_batch_writemodify_operations.asp?frame=true">FastBind</a></font> in
ADSI/SDS actually has nothing to do with the bind operation per say, but has to do
with what ADSI does after the bind when you go to access an object.  With <font face="Courier New">FastBind</font> NOT
set (the default), ADSI does a base-level search to the object you tried to access
to read its <font face="Courier New">objectClass</font> attribute <em>before</em> it
executes any other searches to load the property cache and such.  ADSI uses this
information to determine which ADSI interfaces to make available.  By default,
you get the core interfaces like <font face="Courier New">IADs</font>, but you don’t
necessarily get one of the “persistent object” interfaces like <font face="Courier New">IADsUser</font> or <font face="Courier New">IADsGroup</font> unless
ADSI knows that it is a user or group.  Without those interfaces, you loose access
to members like <font face="Courier New">SetPassword</font> and <font face="Courier New">Add</font> (for
group membership additions).  
</p>
        <p>
The reason <font face="Courier New">FastBind</font> is called “Fast” is that this
initial search is done in addition to any searches to load the property cache, which
generally means that at least <em>two</em> base-level searches to the directory will
be required to load any given ADSI object (as you normally use the property cache
for something!).  All these extra searches add up to lots of network chatter
and can slow certain types of operations to a crawl.  
</p>
        <p>
Note that <font face="Courier New">FastBind</font> is an ADSI/SDS thing though and
has no bearing on how things work at the lower level LDAP level, as this notion of
the persistent object interfaces and property caches is an ADSI abstraction layer.
</p>
        <p>
          <font size="4">How to Implement Fast Concurrent Binding in SDS.P</font>
        </p>
        <p>
There really isn’t too much too this.  All you really need to do is turn this
option on <strong>BEFORE</strong> your LdapConnection actually connects to the directory
for the first time and you are all set.  Briefly, the code looks something like:
</p>
        <p>
          <font face="Courier New">_authConnect.SessionOptions.FastConcurrentBind();</font>
        </p>
        <p>
In order to get a more thorough look, I’ll simply point you to the LdapAuth.cs class
from our book’s website in ch 12 of the <a href="http://directoryprogramming.net/files/default.aspx">Full
Samples </a>to see this in real usage.  
</p>
        <p>
          <strong>Important Warning</strong>
          <br />
There is a bug in the actual implementation printed in the book (first printing at
least; assuming there will be more than one and we actually fix it ?).  <a href="http://dunnry.com/blog/FastConcurrentBindingInSDSP.aspx">A
small last minute blunder caused the defect</a>.  Please use the version in the
full samples from the website.
</p>
        <p>
          <strong>There are some important caveats as well:</strong>
        </p>
        <ul>
          <li>
            <em>Both the server and client must support FCB</em>.  In the book sample, we
actually check the server first via its <font face="Courier New">supportedCapabilities</font><font face="Courier New">RootDSE</font> attribute
to find the specific OID.  On the client requirements, be aware the SDS.P requires
the client code to be run on Windows 2003 server or higher.  XP and below does
not support this!  Our code tries to handle this gracefully, but you should plan
ahead anyway.</li>
          <li>
            <em>You are using simple bind, so you need plaintext usernames and passwords and must
use a user name syntax supported by simple bind</em>.  For AD, this is NT Account
Name (domain\user), UPN or DN.  For ADAM, this is generally UPN or DN, but actually
could be a lot of things like displayName as well.  Ch 3 of our book goes into
more detail.</li>
          <li>
This is simple bind.  <em>You MUST encrypt the network traffic with SSL or something!</em></li>
        </ul>
        <p>
          <font size="4">Conclusion</font>
        </p>
        <p>
We already covered most of this information in our book, but I don’t think we hit
all of these things in as much detail as I have covered here.  Additionally,
not all of you will buy the book and this isn’t in the free chapter, and we want you
to be successful with this somewhat mysterious feature, regardless.  Happy fast(er)
binding!<br /><em><font size="1"></font></em></p>
        <p>
          <em>
            <font size="1">* Of course, with all performance optimizations, always measure
and never assume.  Premature optimization is one of the seven deadly sins of
software engineering, yada-yada-yada.</font>
          </em>
        </p>
        <img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=9b25d233-a484-4905-a60b-8bb8748c7068" />
      </body>
      <title>Using Fast Concurrent Binding in SDS.P</title>
      <guid isPermaLink="false">http://www.joekaplan.net/PermaLink,guid,9b25d233-a484-4905-a60b-8bb8748c7068.aspx</guid>
      <link>http://www.joekaplan.net/UsingFastConcurrentBindingInSDSP.aspx</link>
      <pubDate>Thu, 17 Aug 2006 18:05:52 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font size=4&gt;Fast Concurrent Binding Overview&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
One of the things I alluded to in my &lt;a href="http://www.joekaplan.net/ATaleOfTwoLDAPStacks.aspx"&gt;post&lt;/a&gt; that
highlighted the differences in capabilities between the ADSI-based System.DirectoryServices
(SDS) namespace and the raw LDAP-based System.DirectoryServices.Protocols (SDS.P)
was the ability to access a feature called &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/using_ldap_for_password_authentication.asp?frame=true"&gt;Fast
Concurrent Binding (FCB)&lt;/a&gt;&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
FCB is a feature available in Active Directory 2003 (and later) and in ADAM.&amp;nbsp;
To explain it, first let’s cover what happens with a “regular” bind operation in LDAP
against AD or ADAM.&amp;nbsp; With a normal bind, the user’s credentials are presented
to the LDAP server, either in plaintext format or via the Windows security model if
using a secure binding protocol.&amp;nbsp; The server then attempts to authenticate these
credentials.&amp;nbsp; If the credentials are accepted, then the server builds a Windows
token for the user which will be used to for performing security checks on future
operations and changes the state of the current LDAP connection to an authenticated
state so that future requests will continue to use the newly established security
context and this operation is not repeated.&amp;nbsp; This is the main reason why LDAP
connections are stateful.
&lt;/p&gt;
&lt;p&gt;
FCB eliminates two parts of this equation.&amp;nbsp; It authenticates the user’s credentials,
but it does not build a Windows token for the user and the connection state stays
anonymous.&amp;nbsp; As such, the bind operation will give you an “up/down” result based
on whether the user’s name and password were valid, but it won’t let you do anything
else with that connection such as perform searches, except as an anonymous user (which
is pretty limited by default in AD 2003 and ADAM).
&lt;/p&gt;
&lt;p&gt;
The big upside of FCB is that the bind operation is MUCH faster than a normal bind
because the really expensive operation, expanding the user’s group membership to build
the token, is eliminated.&amp;nbsp; Hence the name&amp;nbsp;&lt;em&gt;&lt;strong&gt;fast&lt;/strong&gt; concurrent
binding&lt;/em&gt;.&lt;sup&gt;*&lt;/sup&gt;
&lt;/p&gt;
&lt;p&gt;
The concurrent part comes from the fact that multiple users can be authenticated on
the same LDAP connection simultaneously without worrying about changing the authenticated
state of the connection, so the expense of setting up and tearing down the associated
socket can also be eliminated.&amp;nbsp; This makes it potentially even faster.
&lt;/p&gt;
&lt;p&gt;
The big downside with FCB is that it only supports LDAP simple bind, not SASL, and
simple bind does not have a built in mechanism for protecting the credentials on the
wire like the various SASL mechanisms do.&amp;nbsp; &lt;strong&gt;As such, it is never safe
to use FCB unless some form of transport security is used such as SSL or IPSEC!&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;When to Use Fast Concurrent Binding&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Do&lt;/strong&gt; use FCB when your application is doing pure authentication of
credentials via LDAP.&amp;nbsp; An example of this might be in a web-based application
that uses AD or ADAM as a user store and does LDAP authentication.&amp;nbsp; If you just
need a “yes/no” vote as to whether a username/password combo is good, FCB will give
you the best performance and may add a significant scalability increase to your application
as a result.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Do not&lt;/strong&gt; use FCB if you need to authenticate and then perform operations
against the directory on the user’s behalf (a delegation scenario from the architectural
perspective, although not necessarily using Windows Kerberos delegation features to
implement it).&amp;nbsp; Since the connection state does not change to “authenticated”,
the user’s credentials will not be used to perform subsequent operations and you won’t
get what you want.
&lt;/p&gt;
&lt;p&gt;
An obvious place where you might want to use FCB would be in something like the ActiveDirectoryMembershipProvider
in ASP.NET 2.0.&amp;nbsp; My understanding is that the development already thought about
this and tried to add this support already.&amp;nbsp; Thus, you may already have this
and not even know it!
&lt;/p&gt;
&lt;p&gt;
Another obvious place for this to be used would be in ADFS for authenticating users
in the ADAM store and potentially with users in the AD store as well when used with
the Federation Service Proxy (which accepts credentials via a forms or basic auth
interface in plaintext form).&amp;nbsp; As of this writing, I do not believe that ADFS
is taking advantage of this feature (or and SDS.P capabilities for that matter).&amp;nbsp;
Note to product team…
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;A Note on ADSI/SDS and Fast Concurrent Binding&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Hey Joe, I see that ADSI and SDS have an &lt;font face="Courier New"&gt;AuthenticationTypes&lt;/font&gt; flag
called &lt;font face="Courier New"&gt;FastBind&lt;/font&gt;.&amp;nbsp; Can’t I just use that to get
FCB?&amp;nbsp; Why are you telling me this requires SDS.P?&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
The answer here is “no”, they are not the same thing, despite their unfortunately
similar names!&amp;nbsp; &lt;font face="Courier New"&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/fast_binding_option_for_batch_writemodify_operations.asp?frame=true"&gt;FastBind&lt;/a&gt;&lt;/font&gt; in
ADSI/SDS actually has nothing to do with the bind operation per say, but has to do
with what ADSI does after the bind when you go to access an object.&amp;nbsp; With &lt;font face="Courier New"&gt;FastBind&lt;/font&gt; NOT
set (the default), ADSI does a base-level search to the object you tried to access
to read its &lt;font face="Courier New"&gt;objectClass&lt;/font&gt; attribute &lt;em&gt;before&lt;/em&gt; it
executes any other searches to load the property cache and such.&amp;nbsp; ADSI uses this
information to determine which ADSI interfaces to make available.&amp;nbsp; By default,
you get the core interfaces like &lt;font face="Courier New"&gt;IADs&lt;/font&gt;, but you don’t
necessarily get one of the “persistent object” interfaces like &lt;font face="Courier New"&gt;IADsUser&lt;/font&gt; or &lt;font face="Courier New"&gt;IADsGroup&lt;/font&gt; unless
ADSI knows that it is a user or group.&amp;nbsp; Without those interfaces, you loose access
to members like &lt;font face="Courier New"&gt;SetPassword&lt;/font&gt; and &lt;font face="Courier New"&gt;Add&lt;/font&gt; (for
group membership additions).&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
The reason &lt;font face="Courier New"&gt;FastBind&lt;/font&gt; is called “Fast” is that this
initial search is done in addition to any searches to load the property cache, which
generally means that at least &lt;em&gt;two&lt;/em&gt; base-level searches to the directory will
be required to load any given ADSI object (as you normally use the property cache
for something!).&amp;nbsp; All these extra searches add up to lots of network chatter
and can slow certain types of operations to a crawl.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Note that &lt;font face="Courier New"&gt;FastBind&lt;/font&gt; is an ADSI/SDS thing though and
has no bearing on how things work at the lower level LDAP level, as this notion of
the persistent object interfaces and property caches is an ADSI abstraction layer.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;How to Implement Fast Concurrent Binding in SDS.P&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
There really isn’t too much too this.&amp;nbsp; All you really need to do is turn this
option on &lt;strong&gt;BEFORE&lt;/strong&gt; your LdapConnection actually connects to the directory
for the first time and you are all set.&amp;nbsp; Briefly, the code looks something like:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;_authConnect.SessionOptions.FastConcurrentBind();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
In order to get a more thorough look, I’ll simply point you to the LdapAuth.cs class
from our book’s website in ch 12 of the &lt;a href="http://directoryprogramming.net/files/default.aspx"&gt;Full
Samples &lt;/a&gt;to see this in real usage.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Important Warning&lt;/strong&gt;
&lt;br&gt;
There is a bug in the actual implementation printed in the book (first printing at
least; assuming there will be more than one and we actually fix it ?).&amp;nbsp; &lt;a href="http://dunnry.com/blog/FastConcurrentBindingInSDSP.aspx"&gt;A
small last minute blunder caused the defect&lt;/a&gt;.&amp;nbsp; Please use the version in the
full samples from the website.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;There are some important caveats as well:&lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Both the server and client must support FCB&lt;/em&gt;.&amp;nbsp; In the book sample, we
actually check the server first via its &lt;font face="Courier New"&gt;supportedCapabilities&lt;/font&gt; &lt;font face="Courier New"&gt;RootDSE&lt;/font&gt; attribute
to find the specific OID.&amp;nbsp; On the client requirements, be aware the SDS.P requires
the client code to be run on Windows 2003 server or higher.&amp;nbsp; XP and below does
not support this!&amp;nbsp; Our code tries to handle this gracefully, but you should plan
ahead anyway.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;You are using simple bind, so you need plaintext usernames and passwords and must
use a user name syntax supported by simple bind&lt;/em&gt;.&amp;nbsp; For AD, this is NT Account
Name (domain\user), UPN or DN.&amp;nbsp; For ADAM, this is generally UPN or DN, but actually
could be a lot of things like displayName as well.&amp;nbsp; Ch 3 of our book goes into
more detail.&lt;/li&gt;
&lt;li&gt;
This is simple bind.&amp;nbsp; &lt;em&gt;You MUST encrypt the network traffic with SSL or something!&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;font size=4&gt;Conclusion&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
We already covered most of this information in our book, but I don’t think we hit
all of these things in as much detail as I have covered here.&amp;nbsp; Additionally,
not all of you will buy the book and this isn’t in the free chapter, and we want you
to be successful with this somewhat mysterious feature, regardless.&amp;nbsp; Happy fast(er)
binding!&lt;br&gt;
&lt;em&gt;&lt;font size=1&gt;&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;font size=1&gt;* Of course, with all performance optimizations, always measure and
never assume.&amp;nbsp; Premature optimization is one of the seven deadly sins of software
engineering, yada-yada-yada.&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=9b25d233-a484-4905-a60b-8bb8748c7068" /&gt;</description>
      <comments>http://www.joekaplan.net/CommentView,guid,9b25d233-a484-4905-a60b-8bb8748c7068.aspx</comments>
      <category>Application Architecture;LDAP;Windows Security</category>
    </item>
    <item>
      <trackback:ping>http://www.joekaplan.net/Trackback.aspx?guid=e226874d-37e0-4d15-a9a8-646c1a4471b3</trackback:ping>
      <pingback:server>http://www.joekaplan.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.joekaplan.net/PermaLink,guid,e226874d-37e0-4d15-a9a8-646c1a4471b3.aspx</pingback:target>
      <dc:creator>Joe Kaplan</dc:creator>
      <wfw:comment>http://www.joekaplan.net/CommentView,guid,e226874d-37e0-4d15-a9a8-646c1a4471b3.aspx</wfw:comment>
      <wfw:commentRss>http://www.joekaplan.net/SyndicationService.asmx/GetEntryCommentsRss?guid=e226874d-37e0-4d15-a9a8-646c1a4471b3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
In a newsgroup thread today, <a href="http://staceyw.spaces.live.com/">William Stacey</a> taught
me some stuff about salted password hashes stored in a traditional relational database. 
Apparently, this is not the way the cool kids do it anymore (although MS still has
plenty of guidance suggesting to use this approach).  Apparently, the those in
the know use an implementation like <a href="http://srp.stanford.edu/">Secure Remote
Password (SRP-6a)</a>.
</p>
        <p>
William couldn't find a .NET implementation, so he built one!  You can find his
implementation <a href="http://channel9.msdn.com/ShowPost.aspx?PostID=107763">here</a>.
</p>
        <img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=e226874d-37e0-4d15-a9a8-646c1a4471b3" />
      </body>
      <title>William Stacey Builds an SRP-6a .NET Implementation</title>
      <guid isPermaLink="false">http://www.joekaplan.net/PermaLink,guid,e226874d-37e0-4d15-a9a8-646c1a4471b3.aspx</guid>
      <link>http://www.joekaplan.net/WilliamStaceyBuildsAnSRP6aNETImplementation.aspx</link>
      <pubDate>Thu, 10 Aug 2006 02:52:50 GMT</pubDate>
      <description>&lt;p&gt;
In a newsgroup thread today, &lt;a href="http://staceyw.spaces.live.com/"&gt;William Stacey&lt;/a&gt; taught
me some stuff about salted password hashes stored in a traditional relational database.&amp;nbsp;
Apparently, this is not the way the cool kids do it anymore (although MS still has
plenty of guidance suggesting to use this approach).&amp;nbsp; Apparently, the those in
the know use an implementation like &lt;a href="http://srp.stanford.edu/"&gt;Secure Remote
Password (SRP-6a)&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
William couldn't find a .NET implementation, so he built one!&amp;nbsp; You can find his
implementation &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=107763"&gt;here&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=e226874d-37e0-4d15-a9a8-646c1a4471b3" /&gt;</description>
      <comments>http://www.joekaplan.net/CommentView,guid,e226874d-37e0-4d15-a9a8-646c1a4471b3.aspx</comments>
      <category>Application Architecture;Cryptography;Windows Security</category>
    </item>
    <item>
      <trackback:ping>http://www.joekaplan.net/Trackback.aspx?guid=fcdf0808-8196-4eb7-b171-8b54a5790687</trackback:ping>
      <pingback:server>http://www.joekaplan.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.joekaplan.net/PermaLink,guid,fcdf0808-8196-4eb7-b171-8b54a5790687.aspx</pingback:target>
      <dc:creator>Joe Kaplan</dc:creator>
      <wfw:comment>http://www.joekaplan.net/CommentView,guid,fcdf0808-8196-4eb7-b171-8b54a5790687.aspx</wfw:comment>
      <wfw:commentRss>http://www.joekaplan.net/SyndicationService.asmx/GetEntryCommentsRss?guid=fcdf0808-8196-4eb7-b171-8b54a5790687</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font size="4">Authentication Mechanisms in SDS</font>
        </p>
        <p>
In ADSI and System.DirectoryServicess (SDS), we are really only given two choices
for how authentication will be performed when we do a bind operation.  We can
specify the "Secure" flag (AuthenticationTypes.Secure), and ADSI will attempt to the
bind to the remote directory using Windows SSPI authentication with the Negotiate
protocol.  As you may know, the Negotiate protocol is the primary authentication
protocol in Windows since Windows 2000 and selects between using Kerberos (always
preferred) and NTLM (there for backwards compatibility).  For the really nerdy
of you out there, the Negotiate protocol is implemented by Microsoft's LDAP API using
the GSS-SPNEGO SASL mechanism.
</p>
        <p>
The other option in SDS is to NOT specify AuthenticationTypes.Secure and it will
attempt to use an LDAP simple bind instead<sup><font size="1">*</font></sup>. 
The only authentication mechanism defined by LDAP specification is the simple bind,
so every directory implements it.  As such, it ends up being the cross-platform
lowest common denominator approach.  The problem with the simple bind is that
it is totally insecure by itself.  Simple bind passes the user's plaintext credentials
on the network, so unless some sort of channel encryption is provided (like SSL, the
defacto cross-platform standard here as well), anyone who can sniff the wire traffic
can recover the user's password.  This sort of thing is generally frowned on
my security enthusiasts.  :(
</p>
        <p>
          <font size="4">Digest Authentication in LDAP API/SDS.P</font>
        </p>
        <p>
There is, however, a richer set of authentication mechanisms supported by Microsoft's
LDAP API than what ADSI/SDS get to use, and these are available to System.DirectoryServices.Protocols
(SDS.P).  One of the most interesting of these is the Digest authentication protocol. 
Digest is a <a href="http://www.faqs.org/rfcs/rfc2831.html">standard</a>, secure authentication
protocol that does not involve the exchange of plaintext credentials and is implemented
by AD and ADAM, as well as some other LDAP directories.  In SDS.P, we can use
it very easily.  Here is a short sample illustrating this (and no, there is no
ADAM instance at adam.joekaplan.net; dream on...):
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">public</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">static</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">bool</span> DoDigestAuth(NetworkCredential
cred)<br />
{ 
<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   
const</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">int</span> LDAP_INVALID_CREDENTIALS <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> 49;<br />
    LdapConnection conn <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">       
new</span> LdapConnection(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"adam.joekaplan.net:389"</span>);<br />
    conn.AuthType <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> AuthType.Digest;<br />
    conn.Credential <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> cred;<br /><br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   
try</span><br />
    {<br />
        conn.Bind();<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">       
return</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">true</span>;<br />
    }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   
catch</span> (LdapException ex)<br />
    {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">       
if</span> (ex.ErrorCode == LDAP_INVALID_CREDENTIALS)<br />
        {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">           
return</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">false</span>;<br />
        }<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">       
else</span><br />
        {<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">           
throw</span>;<br />
        }<br />
    }<br />
}</span>
        </p>
        <p>
Here, we have a trivial little sample that shows how this might be done.  Note
that we probably wouldn't create a new <font face="Courier New">LdapConnection</font> object
each time this is called and we'd also try to find a way to clean that up with a proper
Dispose, but the point here is to illustrate that all we really have to do is set
the <font face="Courier New">AuthType</font> property to <font face="Courier New">AuthType.Digest</font> and
it works.  The credentials are specified with a standard <font face="Courier New">NetworkCredential</font> object. 
For Digest, just specify the username and password, not the domain parameter.
</p>
        <p>
          <font size="4">Why is This Important?</font>
        </p>
        <p>
Digest authentication is really interesting particularly for ADAM, as it is supported
by ADAM principals.  Before ADAM supported Digest auth (as of SP1), the only
way to authenticate an ADAM principal was with a simple bind.  That wasn't secure
(see above), so SSL was required to make it secure.  However, SSL certs are not
always easy to procure and take extra effort to install, so many people were missing
this and were insecure.  :(
</p>
        <p>
The other cool thing with Digest is that since it is implemented through Microsoft's
SSPI model, it can also be used as a mechanism for getting channel encryption and
signing, just like negotiate auth supports today<sup><font size="1">**</font></sup>. 
This means that not only can you get secure binding for free, but all of your network
traffic after the bind can be encrypted and signed for free (no SSL required). 
This is done through setting the <font face="Courier New">Signing</font> and <font face="Courier New">Sealing</font> properties
to true on the <font face="Courier New">LdapSessionOptions</font> class.  This,
in turn, allows a way to do LDAP password operations on ADAM principals without using
SSL and without having to change the setting in ADAM to turn off the requirement for
a secure channel on password ops (another big security frown sandwich there...).  
</p>
        <p>
One great scenario for this feature would be to use it with <strong>ADFS for their
ADAM Account Store support</strong>.  This would allow secure authentication
without requiring SSL out of the box and would also provide free channel encryption.  <strong>Product
team please take note!</strong></p>
        <p>
          <sub>* There is a feature in Windows Server 2003 SP1 ADSI will try Digest auth
when the Secure flag is specified and ADSI detects that the server supports Digest
but not negotiate auth.  However, this doesn't help us for AD or ADAM, since
they both support negotiate auth.  The problem with negotiate auth for ADAM is
that it is only used for authenticating Windows users, not ADAM principals.</sub>
        </p>
        <p>
          <sub>** There appears to be a bug in the implementation in ADAM SP1 where the channel
encryption feature only works if the network traffic is NOT on the loopback
(localhost) port.  This is different from the way negotiate channel encryption
works.  This appears to be an oversight in the implementation and not an underlying
issue in the design, so presumably this will get fixed someday.</sub>
        </p>
        <img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=fcdf0808-8196-4eb7-b171-8b54a5790687" />
      </body>
      <title>Another SDS.P-only feature: Digest authentication</title>
      <guid isPermaLink="false">http://www.joekaplan.net/PermaLink,guid,fcdf0808-8196-4eb7-b171-8b54a5790687.aspx</guid>
      <link>http://www.joekaplan.net/AnotherSDSPonlyFeatureDigestAuthentication.aspx</link>
      <pubDate>Mon, 07 Aug 2006 15:31:20 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font size=4&gt;Authentication Mechanisms in SDS&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
In ADSI and System.DirectoryServicess (SDS), we are really only given two choices
for how authentication will be performed when we do a bind operation.&amp;nbsp; We can
specify the "Secure" flag (AuthenticationTypes.Secure), and ADSI will attempt to the
bind to the remote directory using Windows SSPI authentication with the Negotiate
protocol.&amp;nbsp; As you may know, the Negotiate protocol is the primary authentication
protocol in Windows since Windows 2000 and selects between using Kerberos (always
preferred) and NTLM (there for backwards compatibility).&amp;nbsp; For the really nerdy
of you out there, the Negotiate protocol is implemented by Microsoft's LDAP API using
the GSS-SPNEGO SASL mechanism.
&lt;/p&gt;
&lt;p&gt;
The other option&amp;nbsp;in SDS is to NOT specify AuthenticationTypes.Secure and it will
attempt to use an LDAP simple bind instead&lt;sup&gt;&lt;font size=1&gt;*&lt;/font&gt;&lt;/sup&gt;.&amp;nbsp;
The only authentication mechanism defined by LDAP specification is the simple bind,
so every directory implements it.&amp;nbsp; As such, it ends up being the cross-platform
lowest common denominator approach.&amp;nbsp; The problem with the simple bind is that
it is totally insecure by itself.&amp;nbsp; Simple bind passes the user's plaintext credentials
on the network, so unless some sort of channel encryption is provided (like SSL, the
defacto cross-platform standard here as well), anyone who can sniff the wire traffic
can recover the user's password.&amp;nbsp; This sort of thing is generally frowned on
my security enthusiasts.&amp;nbsp; :(
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;Digest Authentication in LDAP API/SDS.P&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
There is, however, a richer set of authentication mechanisms supported by Microsoft's
LDAP API than what ADSI/SDS get to use, and these are available to System.DirectoryServices.Protocols
(SDS.P).&amp;nbsp; One of the most interesting of these is the Digest authentication protocol.&amp;nbsp;
Digest is a &lt;a href="http://www.faqs.org/rfcs/rfc2831.html"&gt;standard&lt;/a&gt;,&amp;nbsp;secure&amp;nbsp;authentication
protocol that does not involve the exchange of plaintext credentials and is implemented
by AD and ADAM, as well as some other LDAP directories.&amp;nbsp; In SDS.P, we can use
it very easily.&amp;nbsp; Here is a short sample illustrating this (and no, there is no
ADAM instance at adam.joekaplan.net; dream on...):
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;static&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;bool&lt;/span&gt; DoDigestAuth(NetworkCredential
cred)&lt;br&gt;
{ 
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
const&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;int&lt;/span&gt; LDAP_INVALID_CREDENTIALS &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 49;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; LdapConnection conn &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
new&lt;/span&gt; LdapConnection(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"adam.joekaplan.net:389"&lt;/span&gt;);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.AuthType &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; AuthType.Digest;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Credential &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; cred;&lt;br&gt;
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
try&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Bind();&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
return&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;true&lt;/span&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
catch&lt;/span&gt; (LdapException ex)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
if&lt;/span&gt; (ex.ErrorCode == LDAP_INVALID_CREDENTIALS)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
return&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;false&lt;/span&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
else&lt;/span&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
throw&lt;/span&gt;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
Here, we have a trivial little sample that shows how this might be done.&amp;nbsp; Note
that we probably wouldn't create a new &lt;font face="Courier New"&gt;LdapConnection&lt;/font&gt; object
each time this is called and we'd also try to find a way to clean that up with a proper
Dispose, but the point here is to illustrate that all we really have to do is set
the &lt;font face="Courier New"&gt;AuthType&lt;/font&gt; property to &lt;font face="Courier New"&gt;AuthType.Digest&lt;/font&gt; and
it works.&amp;nbsp; The credentials are specified with a standard &lt;font face="Courier New"&gt;NetworkCredential&lt;/font&gt; object.&amp;nbsp;
For Digest, just specify the username and password, not the domain parameter.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;Why is This Important?&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Digest authentication is really interesting particularly for ADAM, as it is supported
by ADAM principals.&amp;nbsp; Before ADAM supported Digest auth (as of SP1), the only
way to authenticate an ADAM principal was with a simple bind.&amp;nbsp; That wasn't secure
(see above), so SSL was required to make it secure.&amp;nbsp; However, SSL certs are not
always easy to procure and take extra effort to install, so many people were missing
this and were insecure.&amp;nbsp; :(
&lt;/p&gt;
&lt;p&gt;
The other cool thing with Digest is that since it is implemented through Microsoft's
SSPI model, it can also be used as a mechanism for getting channel encryption and
signing, just like negotiate auth supports today&lt;sup&gt;&lt;font size=1&gt;**&lt;/font&gt;&lt;/sup&gt;.&amp;nbsp;
This means that not only can you get secure binding for free, but all of your network
traffic after the bind can be encrypted and signed for free (no SSL required).&amp;nbsp;
This is done through setting the &lt;font face="Courier New"&gt;Signing&lt;/font&gt; and &lt;font face="Courier New"&gt;Sealing&lt;/font&gt; properties
to true on the &lt;font face="Courier New"&gt;LdapSessionOptions&lt;/font&gt; class.&amp;nbsp; This,
in turn, allows a way to do LDAP password operations on ADAM principals without using
SSL and without having to change the setting in ADAM to turn off the requirement for
a secure channel on password ops (another big security frown sandwich there...).&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
One great scenario for this feature would be to use it with &lt;strong&gt;ADFS for their
ADAM Account Store support&lt;/strong&gt;.&amp;nbsp; This would allow secure authentication
without requiring SSL out of the box and would also provide free channel encryption.&amp;nbsp; &lt;strong&gt;Product
team please take note!&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;sub&gt;* There is a feature in Windows Server 2003 SP1&amp;nbsp;ADSI will try Digest auth
when the Secure flag is specified and ADSI detects that the server supports Digest
but not negotiate auth.&amp;nbsp; However, this doesn't help us for AD or ADAM, since
they both support negotiate auth.&amp;nbsp; The problem with negotiate auth for ADAM is
that it is only used for authenticating Windows users, not ADAM principals.&lt;/sub&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;sub&gt;** There appears to be a bug in the implementation in ADAM SP1 where the channel
encryption feature&amp;nbsp;only works&amp;nbsp;if the network traffic is NOT on the loopback
(localhost) port.&amp;nbsp; This is different from the way negotiate channel encryption
works.&amp;nbsp; This appears to be an oversight in the implementation and not an underlying
issue in the design, so presumably this will get fixed someday.&lt;/sub&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=fcdf0808-8196-4eb7-b171-8b54a5790687" /&gt;</description>
      <comments>http://www.joekaplan.net/CommentView,guid,fcdf0808-8196-4eb7-b171-8b54a5790687.aspx</comments>
      <category>Identity Federation;LDAP;Windows Security</category>
    </item>
    <item>
      <trackback:ping>http://www.joekaplan.net/Trackback.aspx?guid=871baf79-22b3-4e6f-bdd4-026a770bf9e0</trackback:ping>
      <pingback:server>http://www.joekaplan.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.joekaplan.net/PermaLink,guid,871baf79-22b3-4e6f-bdd4-026a770bf9e0.aspx</pingback:target>
      <dc:creator>Joe Kaplan</dc:creator>
      <wfw:comment>http://www.joekaplan.net/CommentView,guid,871baf79-22b3-4e6f-bdd4-026a770bf9e0.aspx</wfw:comment>
      <wfw:commentRss>http://www.joekaplan.net/SyndicationService.asmx/GetEntryCommentsRss?guid=871baf79-22b3-4e6f-bdd4-026a770bf9e0</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
When I was at TechEd this year, I ran into a few people asking how to integrate <a href="http://www.rsasecurity.com/node.asp?id=1156">SecurID</a> authentication
into ADFS.  As it currently stands, Microsoft has no direct support for this,
or any other authentication mechanism besides AD/ADAM password authentication and
client certificate auth.  Hopefully in the future, Microsoft will make the account
store and authentication mechanisms a first class extensibility point, but for now,
we must hack.  :)
</p>
        <p>
As you can probably tell by the article title, I have gotten this working in my organization's
environment, even though it is not supported by MS.  So, how do we make this
work?  First, I'll explain the overall principles of how we glue these things
together and then I'll share how I actually did it.  In part 2 of the posting,
I'll talk about some other ways that we might get this working.
</p>
        <p>
          <font size="4">Basic Principles</font>
        </p>
        <p>
In Windows Server 2003 and Active Directory 2003, Microsoft implemented an important
and useful extension to the Kerberos authentication protocol called <a href="http://technet2.microsoft.com/WindowsServer/en/library/0d3a0555-9a68-4cc6-ad55-fd076d037fcf1033.mspx?mfr=true">"Service
for User" (S4U), aka Protocol Transition</a>.  S4U adds the ability for a service
to authenticate a client with a non-Kerberos protocol and then transition to a Kerberos-based
identity for accessing Windows resources on local or remote services (hence "protocol
transition").  Protocol transition is something that can be done automatically
by services like IIS when a user authenticates with Basic, Digest or NTLM, but it
can also be called programmatically and used by non-Windows authentication systems
such as SecurID.
</p>
        <p>
To use S4U, your code must execute on a Windows Server 2003 machine (or higher) AND
your Active Directory must be 2003 forest functional level.  If you are doing
ADFS, you already have the former.  However, since ADFS supports both Windows
2000 Server and Windows Server 2003 AD, you might not have the latter.  If you
don't, you are basically SOL for now.  Upgrade!
</p>
        <p>
When using S4U programmatically, you are basically calling the Windows API <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/lsalogonuser.asp">LsaLogonUser</a> with
the S4U option specified.  When usings the S4U option, LsaLogonUser only requires
you to know the user's UPN, not their password, in order to get a Windows logon token
for them.  There are some restrictions on how this token can be used, but that
really isn't too important for this discussion.  <a href="http://www.pluralsight.com/blogs/keith/default.aspx">Keith</a> covers
this stuff in detail in his <a href="http://www.pluralsight.com/wiki/default.aspx/Keith.GuideBook/HomePage.html">book</a> and
several <a href="http://msdn.microsoft.com/msdnmag/issues/03/04/SecurityBriefs/">articles</a> anyway. 
One other nice thing is that .NET (as of 1.1 and higher) has a very easy way to call
LsaLogonUser for S4U with the WindowsIdentity constructor that just takes the UPN. 
It is that simple.
</p>
        <p>
So, now we know we need to use S4U to get a Windows token for the user and we'll need
their UPN to call this.  How does the Windows token then help us with ADFS? 
Well, the ADFS logon service (LS) has a method that allows a user to authenticate
given their Windows token.  In fact, the /ls/auth/integrated directory on the
federation server does just this.  It is set to use Windows Integrated authentication
(IWA) in IIS.  IIS logs the user on with IWA, passes the corresponding Windows
token to ASP.NET.  Then, the ADFS HTTP Module grabs that and calls the correct
method to log you into ADFS and now you have a federation token.  
</p>
        <p>
An interesting side note is that ADFS itself uses protocol transition in the web agent
for token-based applications to achieve similar things (assuming again that you have
2003 AD; otherwise it uses its custom authentication package).  
</p>
        <p>
So, our basic approach with SecurID authentication is to:
</p>
        <ol>
          <li>
Authenticate the user with SecurID using one of RSA's supported methods for web authentication 
</li>
          <li>
 Get the user's UPN somehow (perhaps an LDAP query?) 
</li>
          <li>
Use S4U to get a Windows token for the user 
</li>
          <li>
Use the appropriate method on the LS to authenticate with ADFS using the token</li>
        </ol>
        <p>
This is cake!  :)
</p>
        <p>
          <font size="4">How I Did This</font>
        </p>
        <p>
Ok, I cheated a little bit.  In addition to using RSA's SecurID/ACE Server product
in our company, we also use their <a href="http://www.rsasecurity.com/node.asp?id=1186">ClearTrust</a> web
SSO product (now apparently called Access Manager, but I didn't get that memo). 
ClearTrust already basically let's me do steps 1-3 above using their standard
product when the protocol transition/S4U feature is enabled.  Since it runs as
an ISAPI Filter/ISAPI Extension (via a wildcard map in IIS), it runs before any .NET
code executes.  All I had to do was configure ClearTrust on my /ls/auth/integrated
directory, and ADFS doesn't know the difference between IIS having used IWA or some
other thing.  The LS just grabs the Windows token from where it expects to find
it in ASP.NET and proceeds with logon.  It really is cake and actually worked
the first time I tried it.
</p>
        <p>
The hardest part was instructing ClearTrust to NOT execute on any resources other
than the /ls/auth/integrated directory, which essentially came down to a lengthy URL
exclusion list in the ClearTrust configuration.  Anyone who has used ClearTrust
probably already knows how to do that.  I will probably experiment with alternate
directory structures to simplify this a bit more in the future.
</p>
        <p>
Since ClearTrust is a web SSO product, it also contains a signout function that is
implemented by navigating to a page.  We integrated this into the ADFS signout
by using the same technique it does: we referred to the ClearTrust signout page in
a hidden image tag on the normal signout page.  That results in our ClearTrust
cookie being cleared.
</p>
        <p>
One thing I should make clear is that we did this customization on the FS, not the
FS-P (Federation Service Proxy).  I don't see a reason why you couldn't
do this there too, but you'd need to mess with it a bit more as the FS-P is configured
out of the box to do its own forms auth instead of redirecting to the /ls/auth/integrated
directory.
</p>
        <p>
One important caveat with SecurID auth is that it basically requires forms authentication,
especially to support PIN operations.  This basically implies that you can't
use the "basic" authentication support built in to ADFS here.  As such, you should
probably turn off that option in your ADFS configuration.  That may also mean
that you some SharePoint/Office integration stuff breaks though.  I'm not sure
how to reconcile that problem.  Forms auth and Office don't like each other.
</p>
        <p>
          <font size="4">Summary</font>
        </p>
        <p>
So anyway, that's the basic concept.  If anyone needs additional details, let
me know and I'll try to expand on this.
</p>
        <p>
In Part 2 of this post, I'll try to expand on how one might accomplish if one were
not so blessed with a working ClearTrust infrastructure in place to do the hard part. 
Note that I've never actually done this part, so some of it might just be wild supposition
and it might take some help from someone else out there who really wants this to make
it happen.  We'll see.  In the meantime, I hope the blueprint was helpful.
</p>
        <img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=871baf79-22b3-4e6f-bdd4-026a770bf9e0" />
      </body>
      <title>Integrating SecurID Authentication into ADFS--Part 1</title>
      <guid isPermaLink="false">http://www.joekaplan.net/PermaLink,guid,871baf79-22b3-4e6f-bdd4-026a770bf9e0.aspx</guid>
      <link>http://www.joekaplan.net/IntegratingSecurIDAuthenticationIntoADFSPart1.aspx</link>
      <pubDate>Tue, 01 Aug 2006 18:08:18 GMT</pubDate>
      <description>&lt;p&gt;
When I was at TechEd this year, I ran into a few people asking how to integrate &lt;a href="http://www.rsasecurity.com/node.asp?id=1156"&gt;SecurID&lt;/a&gt; authentication
into ADFS.&amp;nbsp; As it currently stands, Microsoft has no direct support for this,
or any other authentication mechanism besides AD/ADAM password authentication and
client certificate auth.&amp;nbsp; Hopefully in the future, Microsoft will make the account
store and authentication mechanisms a first class extensibility point, but for now,
we must hack.&amp;nbsp; :)
&lt;/p&gt;
&lt;p&gt;
As you can probably tell by the article title, I have gotten this working in my organization's
environment, even though it is not supported by MS.&amp;nbsp; So, how do we make this
work?&amp;nbsp; First, I'll explain the overall principles of how we glue these things
together and then I'll share how I actually did it.&amp;nbsp; In part 2 of the posting,
I'll talk about some other ways that we might get this working.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;Basic Principles&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
In Windows Server 2003 and Active Directory 2003, Microsoft implemented an important
and useful extension to the Kerberos authentication protocol called &lt;a href="http://technet2.microsoft.com/WindowsServer/en/library/0d3a0555-9a68-4cc6-ad55-fd076d037fcf1033.mspx?mfr=true"&gt;"Service
for User" (S4U), aka Protocol Transition&lt;/a&gt;.&amp;nbsp; S4U adds the ability for a service
to authenticate a client with a non-Kerberos protocol and then transition to a Kerberos-based
identity for accessing Windows resources on local or remote services (hence "protocol
transition").&amp;nbsp; Protocol transition is something that can be done automatically
by services like IIS when a user authenticates with Basic, Digest or NTLM, but it
can also be called programmatically and used by non-Windows authentication systems
such as SecurID.
&lt;/p&gt;
&lt;p&gt;
To use S4U, your code must execute on a Windows Server 2003 machine (or higher) AND
your Active Directory must be 2003 forest functional level.&amp;nbsp; If you are doing
ADFS, you already have the former.&amp;nbsp; However, since ADFS supports both Windows
2000 Server and Windows Server 2003 AD, you might not have the latter.&amp;nbsp; If you
don't, you are basically SOL for now.&amp;nbsp; Upgrade!
&lt;/p&gt;
&lt;p&gt;
When using S4U programmatically, you are basically calling the Windows API &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/lsalogonuser.asp"&gt;LsaLogonUser&lt;/a&gt; with
the S4U option specified.&amp;nbsp; When usings the S4U option, LsaLogonUser only requires
you to know the user's UPN, not their password, in order to get a Windows logon token
for them.&amp;nbsp; There are some restrictions on how this token can be used, but that
really isn't too important for this discussion.&amp;nbsp; &lt;a href="http://www.pluralsight.com/blogs/keith/default.aspx"&gt;Keith&lt;/a&gt; covers
this stuff in detail in his &lt;a href="http://www.pluralsight.com/wiki/default.aspx/Keith.GuideBook/HomePage.html"&gt;book&lt;/a&gt; and
several &lt;a href="http://msdn.microsoft.com/msdnmag/issues/03/04/SecurityBriefs/"&gt;articles&lt;/a&gt; anyway.&amp;nbsp;
One other nice thing is that .NET (as of 1.1 and higher) has a very easy way to call
LsaLogonUser for S4U with the WindowsIdentity constructor that just takes the UPN.&amp;nbsp;
It is that simple.
&lt;/p&gt;
&lt;p&gt;
So, now we know we need to use S4U to get a Windows token for the user and we'll need
their UPN to call this.&amp;nbsp; How does the Windows token then help us with ADFS?&amp;nbsp;
Well, the ADFS logon service (LS) has a method that allows a user to authenticate
given their Windows token.&amp;nbsp; In fact, the /ls/auth/integrated directory on the
federation server does just this.&amp;nbsp; It is set to use Windows Integrated authentication
(IWA)&amp;nbsp;in IIS.&amp;nbsp; IIS logs the user on with IWA, passes the corresponding Windows
token to ASP.NET.&amp;nbsp; Then, the ADFS HTTP Module grabs that and calls the correct
method to log you into ADFS and now you have a federation token.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
An interesting side note is that ADFS itself uses protocol transition in the web agent
for token-based applications to achieve similar things (assuming again that you have
2003 AD; otherwise it uses its custom authentication package).&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
So, our&amp;nbsp;basic approach&amp;nbsp;with SecurID authentication is to:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Authenticate the user with SecurID using one of RSA's supported methods for web authentication 
&lt;li&gt;
&amp;nbsp;Get the user's UPN somehow (perhaps an LDAP query?) 
&lt;li&gt;
Use S4U to get a Windows token for the user 
&lt;li&gt;
Use the appropriate method on the LS to authenticate with ADFS using the token&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
This is cake!&amp;nbsp; :)
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;How I Did This&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Ok, I cheated a little bit.&amp;nbsp; In addition to using RSA's SecurID/ACE Server product
in our company, we also use their &lt;a href="http://www.rsasecurity.com/node.asp?id=1186"&gt;ClearTrust&lt;/a&gt; web
SSO product (now apparently called Access Manager, but I didn't get that memo).&amp;nbsp;
ClearTrust already basically let's me do steps&amp;nbsp;1-3 above using their standard
product when the protocol transition/S4U feature is enabled.&amp;nbsp; Since it runs as
an ISAPI Filter/ISAPI Extension (via a wildcard map in IIS), it runs before any .NET
code executes.&amp;nbsp; All I had to do was configure ClearTrust on my /ls/auth/integrated
directory, and ADFS doesn't know the difference between IIS having used IWA or some
other thing.&amp;nbsp; The LS just grabs the Windows token from where it expects to find
it in ASP.NET and proceeds with logon.&amp;nbsp; It really is cake and actually worked
the first time I tried it.
&lt;/p&gt;
&lt;p&gt;
The hardest part was instructing ClearTrust to NOT execute on any resources other
than the /ls/auth/integrated directory, which essentially came down to a lengthy URL
exclusion list in the ClearTrust configuration.&amp;nbsp; Anyone who has used ClearTrust
probably already knows how to do that.&amp;nbsp; I will probably experiment with alternate
directory structures to simplify this a bit more in the future.
&lt;/p&gt;
&lt;p&gt;
Since ClearTrust is a web SSO product, it also contains a signout function that is
implemented by navigating to a page.&amp;nbsp; We integrated this into the ADFS signout
by using the same technique it does: we referred to the ClearTrust signout page in
a hidden image tag on the normal signout page.&amp;nbsp; That results in our ClearTrust
cookie being cleared.
&lt;/p&gt;
&lt;p&gt;
One thing I should make clear is that we did this customization on the FS, not the
FS-P (Federation Service Proxy).&amp;nbsp; I don't see&amp;nbsp;a reason why you couldn't
do this there too, but you'd need to mess with it a bit more as the FS-P is configured
out of the box to do its own forms auth instead of redirecting to the /ls/auth/integrated
directory.
&lt;/p&gt;
&lt;p&gt;
One important caveat with SecurID auth is that it basically requires forms authentication,
especially to support PIN operations.&amp;nbsp; This basically implies that you can't
use the "basic" authentication support built in to ADFS here.&amp;nbsp; As such, you should
probably turn off that option in your ADFS configuration.&amp;nbsp; That may also mean
that you some SharePoint/Office integration stuff breaks though.&amp;nbsp; I'm not sure
how to reconcile that problem.&amp;nbsp; Forms auth and Office don't like each other.
&lt;/p&gt;
&lt;p&gt;
&lt;font size=4&gt;Summary&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
So anyway, that's the basic concept.&amp;nbsp; If anyone needs additional details, let
me know and I'll try to expand on this.
&lt;/p&gt;
&lt;p&gt;
In Part 2 of this post, I'll try to expand on how one might accomplish if one were
not so blessed with a working ClearTrust infrastructure in place to do the hard part.&amp;nbsp;
Note that I've never actually done this part, so some of it might just be wild supposition
and it might take some help from someone else out there who really wants this to make
it happen.&amp;nbsp; We'll see.&amp;nbsp; In the meantime, I hope the blueprint was helpful.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=871baf79-22b3-4e6f-bdd4-026a770bf9e0" /&gt;</description>
      <comments>http://www.joekaplan.net/CommentView,guid,871baf79-22b3-4e6f-bdd4-026a770bf9e0.aspx</comments>
      <category>Identity Federation;Windows Security</category>
    </item>
    <item>
      <trackback:ping>http://www.joekaplan.net/Trackback.aspx?guid=0de1cf66-d371-445d-9b27-65e65157782d</trackback:ping>
      <pingback:server>http://www.joekaplan.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.joekaplan.net/PermaLink,guid,0de1cf66-d371-445d-9b27-65e65157782d.aspx</pingback:target>
      <dc:creator>Joe Kaplan</dc:creator>
      <wfw:comment>http://www.joekaplan.net/CommentView,guid,0de1cf66-d371-445d-9b27-65e65157782d.aspx</wfw:comment>
      <wfw:commentRss>http://www.joekaplan.net/SyndicationService.asmx/GetEntryCommentsRss?guid=0de1cf66-d371-445d-9b27-65e65157782d</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of the things you run into with ASP.NET apps doing authorization using Windows
security is that you often need a way to find out the authenticated user's identity
and security group memberships for troubleshooting.  This is especially useful
under ADFS, where your Windows token can go through a mapping process based on claims
received from an external organization and bear no resemblance to an actual user in
your AD forest.
</p>
        <p>
This is just an ugly sample page in ASP.NET (using VB.NET, but I'll do C# on request
if that's really important; we're talking about 10 lines of code here guys...)
that dumps out the authenticated user's groups and name.
</p>
        <p>
The core function looks like this:
</p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Private</span>
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Sub</span> Page_Load(
_<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   
ByVal</span> sender <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Object</span>,
_<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   
ByVal</span> e <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.EventArgs
_<br />
    ) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Handles</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">MyBase</span>.Load<br /><br />
_nameLabel.Text <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> User.Identity.Name 
<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Dim</span> groupSidHtml <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">New</span> System.Text.Stringbuilder<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Dim</span> sids <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.Security.Principal.IdentityReferenceCollection <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> _<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">   
DirectCast</span>(User.Identity, System.Security.Principal.WindowsIdentity).Groups<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Dim</span> names <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.Security.Principal.IdentityReferenceCollection <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> _<br />
    sids.Translate(<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">GetType</span>(System.Security.Principal.NTAccount))<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">For</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Each</span> name <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">as</span> System.Security.Principal.NTAccount <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">In</span> names<br />
    groupSidHTML.AppendFormat(<span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"&lt;p&gt;{0}&lt;/p&gt;"</span>,
name.ToString())<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Next</span><br /><br />
_groupLabel.Text <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> groupSidHTML.ToString()<br /><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">End</span><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Sub</span></span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#000000" size="2">If
I were a little less lazy, I probably would have added the imports declarations on
the page instead of using the full type names and would have used a repeater and some
formatting, but this was quick and dirty.  Feel free to improve it.  The
working page can be downloaded at the link at the bottom of the page.</font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#000000" size="2">
                <strong>Caveat</strong>
              </font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#000000" size="2">Even
though token apps allow you to run on prior versions of the .NET framework, this page
uses a bunch of .NET 2.0-specific code in it (IdentityReferenceCollection and such),
so you must configure the app for .NET 2.0 to use this.  I'm simply not at all
interested in writing all the p/invoke stuff to crack the user's token and translate
their SIDs into names simply to create a .NET 1.1 solution.  Sorry.  There
is lazy and then there is just wasting time...</font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#000000" size="2">Also,
you must be configured for Windows authentication in ASP.NET, but that should be obvious
I hope.</font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#000000" size="2">I
hope this helps someone figure out what ADFS is actually putting into their Windows
token!</font>
            </span>
          </span>
        </p>
        <p>
          <span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
            <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
              <font face="Verdana" color="#000000" size="2">(Update,
changed the file to a .zip to avoid error mentioned in the comment)</font>
            </span>
          </span>
        </p>
        <a href="http://www.joekaplan.net/content/binary/default.zip">default.zip (.63 KB)</a>
        <img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=0de1cf66-d371-445d-9b27-65e65157782d" />
      </body>
      <title>Discovering the User's Name and Groups in Their Windows Token</title>
      <guid isPermaLink="false">http://www.joekaplan.net/PermaLink,guid,0de1cf66-d371-445d-9b27-65e65157782d.aspx</guid>
      <link>http://www.joekaplan.net/DiscoveringTheUsersNameAndGroupsInTheirWindowsToken.aspx</link>
      <pubDate>Mon, 31 Jul 2006 19:44:06 GMT</pubDate>
      <description>&lt;p&gt;
One of the things you run into with ASP.NET&amp;nbsp;apps doing authorization using Windows
security is that you often need a way to find out the authenticated user's identity
and security group memberships for troubleshooting.&amp;nbsp; This is especially useful
under ADFS, where your Windows token can go through a mapping process based on claims
received from an external organization and bear no resemblance to an actual user in
your AD forest.
&lt;/p&gt;
&lt;p&gt;
This is just an ugly sample page in ASP.NET (using VB.NET, but I'll do C# on request
if that's&amp;nbsp;really important; we're talking about 10 lines of code here guys...)
that dumps out the authenticated user's groups and name.
&lt;/p&gt;
&lt;p&gt;
The core function looks like this:
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Sub&lt;/span&gt; Page_Load(
_&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ByVal&lt;/span&gt; sender &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Object&lt;/span&gt;,
_&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
ByVal&lt;/span&gt; e &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.EventArgs
_&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Handles&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;MyBase&lt;/span&gt;.Load&lt;br&gt;
&lt;br&gt;
_nameLabel.Text &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; User.Identity.Name 
&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Dim&lt;/span&gt; groupSidHtml &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;New&lt;/span&gt; System.Text.Stringbuilder&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Dim&lt;/span&gt; sids &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.Security.Principal.IdentityReferenceCollection &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; _&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
DirectCast&lt;/span&gt;(User.Identity, System.Security.Principal.WindowsIdentity).Groups&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Dim&lt;/span&gt; names &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.Security.Principal.IdentityReferenceCollection &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; _&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; sids.Translate(&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;GetType&lt;/span&gt;(System.Security.Principal.NTAccount))&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;For&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Each&lt;/span&gt; name &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;as&lt;/span&gt; System.Security.Principal.NTAccount &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;In&lt;/span&gt; names&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; groupSidHTML.AppendFormat(&lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"&amp;lt;p&amp;gt;{0}&amp;lt;/p&amp;gt;"&lt;/span&gt;,
name.ToString())&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Next&lt;/span&gt;
&lt;br&gt;
&lt;br&gt;
_groupLabel.Text &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; groupSidHTML.ToString()&lt;br&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;End&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Sub&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#000000 size=2&gt;If
I were a little less lazy, I probably would have added the imports declarations on
the page instead of using the full type names and would have used a repeater and some
formatting, but this was quick and dirty.&amp;nbsp; Feel free to improve it.&amp;nbsp; The
working page can be downloaded at the link at the bottom of the page.&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#000000 size=2&gt;&lt;strong&gt;Caveat&lt;/strong&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#000000 size=2&gt;Even
though token apps allow you to run on prior versions of the .NET framework, this page
uses a bunch of .NET 2.0-specific code in it (IdentityReferenceCollection and such),
so you must configure the app for .NET 2.0 to use this.&amp;nbsp; I'm simply not at all
interested in writing all the p/invoke stuff to crack the user's token and translate
their SIDs into names simply to create a .NET 1.1 solution.&amp;nbsp; Sorry.&amp;nbsp; There
is lazy and then there is just wasting time...&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#000000 size=2&gt;Also,
you must be configured for Windows authentication in ASP.NET, but that should be obvious
I hope.&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#000000 size=2&gt;I
hope this helps someone figure out what ADFS is actually putting into their Windows
token!&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;font face=Verdana color=#000000 size=2&gt;(Update,
changed the file to a .zip to avoid error mentioned in the comment)&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;a href="http://www.joekaplan.net/content/binary/default.zip"&gt;default.zip (.63 KB)&lt;/a&gt;&lt;img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=0de1cf66-d371-445d-9b27-65e65157782d" /&gt;</description>
      <comments>http://www.joekaplan.net/CommentView,guid,0de1cf66-d371-445d-9b27-65e65157782d.aspx</comments>
      <category>Identity Federation;Windows Security</category>
    </item>
    <item>
      <trackback:ping>http://www.joekaplan.net/Trackback.aspx?guid=ac8e564c-1b19-44e7-9ab0-6a4ef74bd614</trackback:ping>
      <pingback:server>http://www.joekaplan.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.joekaplan.net/PermaLink,guid,ac8e564c-1b19-44e7-9ab0-6a4ef74bd614.aspx</pingback:target>
      <dc:creator>Joe Kaplan</dc:creator>
      <wfw:comment>http://www.joekaplan.net/CommentView,guid,ac8e564c-1b19-44e7-9ab0-6a4ef74bd614.aspx</wfw:comment>
      <wfw:commentRss>http://www.joekaplan.net/SyndicationService.asmx/GetEntryCommentsRss?guid=ac8e564c-1b19-44e7-9ab0-6a4ef74bd614</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've been telling myself I was going to finally get into the blogging racket for almost
2 years now, but even though I've had the hosting all put together for that entire
time, it took me forever to actually get it together.  I just had to do it myself
instead of using another site...
</p>
        <p>
Anyway, this blog will probably resemble the blogs I already read, in that it will
be mostly technical with a focus on building software using Microsoft's .NET platform. 
It will probably lean heavily on my specialties, .NET LDAP programming and application
security, but will likely also feature other stuff I'm into like application architecture,
agile development, identity federation, cryptography, and setup development in MSI
using <a href="http://wix.sourceforge.net">WiX</a>.  
</p>
        <p>
Speaking of .NET and LDAP, if you've ever heard of me before, it is most likely because
you might have stumbled across one of the myriad usenet posts I've made over the last
4-5 years on the Microsoft newsgroups, or perhaps I answered your question directly. 
Micrsosoft has actually designated me an <a href="http://mvp.support.microsoft.com">MVP</a> in
this area, and I've even written a <a href="http://www.directoryprogramming.net">book</a> about
this with my intrepid co-author, <a href="http://www.dunnry.com/blog">Ryan Dunn</a>,
to further our aim of providing resources for the .NET community in this obscure,
but stranglely difficult and increasingly important aspect of software development.
</p>
        <p>
That's all for now.  Maybe some real content next time, eh?
</p>
        <img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=ac8e564c-1b19-44e7-9ab0-6a4ef74bd614" />
      </body>
      <title>About time...</title>
      <guid isPermaLink="false">http://www.joekaplan.net/PermaLink,guid,ac8e564c-1b19-44e7-9ab0-6a4ef74bd614.aspx</guid>
      <link>http://www.joekaplan.net/AboutTime.aspx</link>
      <pubDate>Sun, 30 Jul 2006 15:25:14 GMT</pubDate>
      <description>&lt;p&gt;
I've been telling myself I was going to finally get into the blogging racket for almost
2 years now, but even though I've had the hosting all put together for that entire
time, it took me forever to actually get it together.&amp;nbsp; I just had to do it myself
instead of using another site...
&lt;/p&gt;
&lt;p&gt;
Anyway, this blog will probably resemble the blogs I already read, in that it will
be mostly technical with a focus on building software using Microsoft's .NET platform.&amp;nbsp;
It will probably lean heavily on my specialties, .NET LDAP programming and&amp;nbsp;application
security, but will likely also feature other stuff I'm into like application architecture,
agile development, identity federation, cryptography, and setup development in MSI
using &lt;a href="http://wix.sourceforge.net"&gt;WiX&lt;/a&gt;.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Speaking of .NET and LDAP, if you've ever heard of me before, it is most likely because
you might have stumbled across one of the myriad usenet posts I've made over the last
4-5 years on the Microsoft newsgroups, or perhaps I answered your question directly.&amp;nbsp;
Micrsosoft has actually designated me an &lt;a href="http://mvp.support.microsoft.com"&gt;MVP&lt;/a&gt; in
this area, and I've even written a &lt;a href="http://www.directoryprogramming.net"&gt;book&lt;/a&gt; about
this with my intrepid co-author, &lt;a href="http://www.dunnry.com/blog"&gt;Ryan Dunn&lt;/a&gt;,
to further our aim of providing resources for the .NET community in this obscure,
but stranglely difficult and increasingly important aspect of software development.
&lt;/p&gt;
&lt;p&gt;
That's all for now.&amp;nbsp; Maybe some real content next time, eh?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.joekaplan.net/aggbug.ashx?id=ac8e564c-1b19-44e7-9ab0-6a4ef74bd614" /&gt;</description>
      <comments>http://www.joekaplan.net/CommentView,guid,ac8e564c-1b19-44e7-9ab0-6a4ef74bd614.aspx</comments>
      <category>General;LDAP;Windows Security;WiX;Identity Federation;Cryptography;Agile;Application Architecture;Software Engineering</category>
    </item>
  </channel>
</rss>