Wednesday, April 16, 2008

Why DotNetOpenID as your C# OpenID library of choice

In choosing an implementation of OpenID for your .NET web site, of course I would have to recommend DotNetOpenId, seeing as I spend a considerable amount of my spare time working on it.  But Samuli (in the comments on Troy's recent blog post regarding OpenID) recently asked me to give a sales pitch for DotNetOpenID over another implementation called ExtremeSwank. 

First I want to make clear that I respect John Ehn (of ExtremeSwank) and his very dedicated work to his library. He has no doubt spent countless hours and published all his work as free open-source software, for which he is to be commended. 

On with the sales pitch... (I'll abbreviate to ES and DNOI to refer to the two libraries)

  • DNOI supports Providers and Relying Party web sites.  ES only supports Relying Parties.
  • DNOI has several ASP.NET custom controls built-in that make relying party and provider scenarios very easy, should you choose to use them. (Please note that the ASP.NET controls are not required, and that the API-level OpenID support is still simple to use.)  ES has a couple of web user controls which simplify its API, but have to be copied into the hosting web site as source code -- since there's a bucketload of code in the code-behind for these controls, that's difficult to maintain with each successive version of the library for consumers to hand-upgrade in their web sites.
  • DNOI doesn't require an ASP.NET HttpContext, allowing all OpenID handling to be done on a backend server (useful for web farms).  ES requires the HttpContext, apparently disallowing this.
  • ES doesn't have any unit tests while DNOI has well over 100 to verify proper function and resistance against security exploits.
  • DNOI has been much more widely adopted, and therefore tested in the field.
  • DNOI has already been deployed on many shared hosting environments, and even web farms successfully.
  • DNOI has been scrubbed for public classes/members to minimize surface area for simple Intellisense discovery of how to use the library, for fewer breaking changes going forward, and for security.  It seems ES still has way too many classes marked Public. 
  • DNOI is prepared for future versions of OpenID (by abstracting away most of the protocol version differences in a dedicated class) so we should be able to rev for the next version quickly.
  • DNOI is prepared for localization (all our human-readable strings are in a resource file), and we've already had a volunteer to begin translation into at least one other language. [27Apr2008 Update: John of ES points out in comments below that ES is also localization ready in that it doesn't return or throw any strings at all -- just an enum so that the site author can provide the text to display.]
  • DNOI's approach to OpenID has been to implement the spec fully and to the letter so that we interoperate with all (so far) OpenID web sites, whereas ES's change history is ridden with 'now works with aol, ... now works with claimid, ... now works with ___....', which suggests to me that it's a gradual hit-or-miss thing.  ES also has a Quirks class that special cases interop with certain other web sites in order to work with them.  DNOI hasn't needed a Quirks class (at least not yet) because our implementation of the spec works with everything people have tested against. Now maybe there's a history behind the Quirks class and those other web sites were not implementing the spec properly but now are... I don't know for sure.  But I know DNOI doesn't have a class like this and works with all the sites ES mentions in its Quirks class.

There is one area where I bow to ExtremeSwank's better coverage.  While DotNetOpenID supports extensions in an extensible way (that is, you can use any extension you want with it), it currently only comes prepackaged with support for Simple Registration, leaving any other extension to have to be hand-coded by the hosting web site.  The difficulty of this depends largely on the complexity of the extension you want to use.  ExtremeSwank apparently has built-in support for several extensions out of the box including Simple Registration, Attribute Exchange, and Authentication Policy.  I expect DotNetOpenID to develop these extensions as standard offerings soon though, so this doesn't bother me too much.

Please note that while I've glossed over the ExtremeSwank codebase a couple of times, especially in writing this post, I have not ever used it in production.  While I believe what I've written above to be correct, if someone finds something I'm mistaken about please comment and I'll be happy to make note of it. This post is as-of today however, so if some of these things get fixed later, kudos to ExtremeSwank, but I'll leave the post as-is.

5 comments:

  1. Samuli Lintunen9:52 AM

    Andrew, thanks for taking the time to write this. In short, your project seems very promising with all the current and upcoming features. I'm going to try it out, if not in my current project, the next one.

    Thank you for providing the ASP.NET community with such a library and an advancing the OpenID movement in general.

    ReplyDelete
  2. Thanks for this writing this up, Andrew. You've been doing a great job both with writing this library and evangelizing the use of OpenId throughtout the .net developer community.

    I'm looking forward to seeing your project implement more of the extensions you referred to!

    -Troy Goode

    ReplyDelete
  3. Andrew,

    Just some responses to your statements.

    ---

    DNOI supports Providers and Relying Party web sites. ES only supports Relying Parties.

    - This is correct. I am personally more interested in the client side than the server side.

    DNOI has several ASP.NET custom controls built-in that make relying party and provider scenarios very easy, should you choose to use them. (Please note that the ASP.NET controls are not required, and that the API-level OpenID support is still simple to use.) ES has a couple of web user controls which simplify its API, but have to be copied into the hosting web site as source code -- since there's a bucketload of code in the code-behind for these controls, that's difficult to maintain with each successive version of the library for consumers to hand-upgrade in their web sites.

    - This isn't necessarily a bad thing. The public API (at least the members that are used the most heavily) haven't changed for several versions, so existing implementations shouldn't have to change their Control code to use the new library. I use OpenIDControl to also showcase new ways of using the library as time goes on. I wouldn't be able to do this easily if all the code were embedded in the library itself.

    DNOI doesn't require an ASP.NET HttpContext, allowing all OpenID handling to be done on a backend server (useful for web farms). ES requires the HttpContext, apparently disallowing this.

    - This has been fixed as of recent releases (3.1.1.1+). I have also recently added zero-save-state functionality when Stateless authentication is requested.

    ES doesn't have any unit tests while DNOI has well over 100 to verify proper function and resistance against security exploits.

    - This is true. As a result, I spend a bit of time (one could say too much time) testing everything by hand. I do have a bit of experience modelling out security exploits, so the lack of unit tests in this regard is unfortunate, but not the end of the world. I have not yet been notified of any security deficiencies.

    DNOI has been much more widely adopted, and therefore tested in the field.

    - Although probably true, this is a very big statement to make. Do you have objective data to support this?

    DNOI has already been deployed on many shared hosting environments, and even web farms successfully.

    - This is correct. However, you must recall that the dotnetopenid library was unable to be deployed in shared hosting environments until very recently. ExtremeSwank OpenID could be installed in parial trust environments several months before dotnetopenid.

    DNOI has been scrubbed for public classes/members to minimize surface area for simple Intellisense discovery of how to use the library, for fewer breaking changes going forward, and for security. It seems ES still has way too many classes marked Public.
    DNOI is prepared for future versions of OpenID (by abstracting away most of the protocol version differences in a dedicated class) so we should be able to rev for the next version quickly.

    - I took this to heart. The new version has marked all reasonably internal classes as "internal", and a few members within some classes have also been marked internal. Be careful about making statements on the impact on security, though. Simply marking classes as internal or private only hides them from direct execution. Anyone with some experience with System.Reflection can get access from outside the assembly.

    DNOI is prepared for localization (all our human-readable strings are in a resource file), and we've already had a volunteer to begin translation into at least one other language.

    - Yes, dotnetopenid does have localization support, but so does ES. There are no strings in ES that are intended to be end-user visible. All feedback is provided by the Errors enumeration. The implementor can provide translations in any language he wants. Since the enumeration is only a few members, there is little need to create an entire localization infrastructure to support it.

    DNOI's approach to OpenID has been to implement the spec fully and to the letter so that we interoperate with all (so far) OpenID web sites,...

    - Sorry, but this is misleading. What use would I have to write a library that isn't written to the OpenID specification? You also have to admit that with your code being based on the original JanRain libraries, it is not unreasonable to assume that the vast majority of OpenID Providers have tested their implementations against that same original code? Wouldn't it follow that there is a much higher probability that dotnetopenid would interoperate more smoothly than an independently developed library?

    ... ES also has a Quirks class that special cases interop with certain other web sites in order to work with them. DNOI hasn't needed a Quirks class (at least not yet) because our implementation of the spec works with everything people have tested against....

    - I do freely admit that I had a lapse of judgement when not understanding the real issue causing the creation of part of the Quirks class, so I proceeded to band-aid each condition. The root issue has since been corrected, though. The only Provider-specific issue remaining in Quirks is due to a single provider's broken association negotiation and stateless fallback implementations. In all probability, I probably overlooked something. I do not believe implementing temporary workarounds for situations where functionality is broken is a bad thing, though.

    ReplyDelete
  4. MR. ExtremeSwank,

    Thanks for your comments. I'm pleased to hear about some of the recent enhancements you've made. And I do tip my hat to your earlier support for partial trust shared hosting environments. It looks like you had a more recent drop of the mono BigInteger class than we did. You still do, in fact, although I did correct the full trust requiring code myself to solve that problem.

    You make some good points. Just a few responses:
    As far as being able to use reflection to get to internal members of another assembly, that's true, but only when the other code is running with full trust. I think we agree here that the security benefits of marking classes/members internal are existent, but small in comparison to other possible security holes that are in the nature of the kind of authentication library we each provide.
    The objective data regarding the adoption rate is the traffic on our mailing list from people actually deploying on live sites and have questions, and the count of software downloads. I believe those are good indicators.
    Regarding localization, if your library has always used this mode of just returning an error enum then I apologize for an incorrect comparison. My review of your code looked like it had lots of english strings in it, but maybe they were all asserts, trace messages, etc. and I may not have noticed that.
    And regarding the OpenID spec compliance, our library has virtually no code in common with its Janrain roots any more, so I can't attribute much if any credit for compatibility with other implementations to that.

    To reiterate, I take my hat off to your selfless work and meant to offense with my original post. I will make corrections in my post regarding the localization comparison.

    ReplyDelete
  5. Could you direct me to a link where I can download the OpenID dll for ASP.NET 3.5

    ReplyDelete