Sharepoint 2010 and ADFS

March 5th, 2010

I’ve seen a few questions on identity federation with SharePoint before, so I thought about sharing this more broadly.
I recorded a 9 minutes screencast showing the capabilities of ADFSv2 + SharePoint 2010. This is using Microsoft STS, LiveID and our own company STS allowing the following usecases:

  • Manage access to employees that belong to the Active Directory
  • Manage access to partners that has their own STS
  • Manage access to certain webparts, doc libraries or lists through Sharepoint groups and claims
  • Allow/deny access to Windows LiveID users

image

I found myself posting more on twitter than my blog. However this deserved a post.
The RTM of the guide is finally out there in PDF version.

image

Looking at my name in the cover of a book together with such a group of experts is really a significant milestone in my career. I want to specially thanks Eugenio for trusting me and inviting me to participate in this project. Hope you find the content useful. If you have any questions or you want to discuss about claims, identity, federation towards your next project feel free to mail me at matias at southworks dot net.

Now heading towards the second book: Cloud Guidance! Stay tuned…

Wow, 3 months since my last post… Lots of things happened. We’ve been working with James Conard’s team from Microsoft DPE on the PDC09 keynote demos, specifically the Platform Converge demo (Doug Pourdy) and the VS2010, AppFabric, NET4, WIF demo (by Cameron Skinner, read more in his post). We also helped delivering the training kits (identity, vs2010, azure, etc.) and the labs that were available on PDC. Tim and Johnny posted more details about this.

Being part of the making of a PDC keynote was very interesting. We had meetings with Partner Architects and Distinguished Engineers of the different Microsoft product groups. You get to learn a lot about politics in those meetings ;).

Once again we worked closely with Vittorio on Windows Identity Foundation content which was RTMed. David and Ryan on Azure and Jonathan Carter on Tailspin among other things. Finally, thanks all the team @ Southworks for the great support pre-PDC.

On a related note, the last month we worked hard with Eugenio, Erwin, the team at patterns & practices, Fede Boerr, Keith, Dominick to deliver a printed preview of the Claims Based Identity & Access Control Guide. Limited copies were distributed on the WIF booth and p&p booth at PDC and the book was very well received. We’ll be soon reaching a milestone and publish the following chapters:

 image 

Well, I had to catch-up with the blog… hopefully will keep the pace now.

Eugenio announced yesterday the kickoff of a new guide from patterns & practices in which I’m collaborating: Claims based Authentication & Authorization Guide.

This is not a new topic as Eugenio suggests in his blog, but it’s getting more and more attention because:

  • Technology is more mature, hence it’s easier to implement claim-based identity
  • Enterprises are failing to control the amount of different identity repositories, leading to higher provisioning/deprovisioning costs, security problems, etc.
  • End users want simpler user experiences and less passwords
  • The cloud makes all these even more challenging

We started with this project a couple of weeks ago planning the content. The approach we decided to use was heavily driven by scenarios (aka zero bulls**t). We used the visual metaphor of a tube map with scenarios being the stations separated in two main lines:

  • The blue one, the Enterprise track approaches the federated identity problem from the point of view of a company with many applications that wants to implement SSO and Federation. The main stations are SSO (within the enterprise), Federation (with partners), SOAP Web Services (and flow of identity across services), SSO with a third party cloud app and some variations like: what if the company decides to host an application on the cloud (namely Windows Azure); or what if the company needs to integrate with an application that talks SAML protocol (i.e. Salesforce, Google Apps)
  • The yellow one, ISV track on the other hand tackle the problem from the perspective of an ISV that wants to offer an application as a service (think about Salesforce or Dynamics CRM Online as the canonical examples). In this track we start by explaining how to implement federated identity for a cloud application. Then we show how to automate federation to on board new customers. We also show things like exposing a REST API and how that plays with claims; how to integrate with LiveID (or OpenID) for small customers that don’t have an Identity Provider in place; and we end up explaining how to do auditing/billing with claims.

image

I’m very proud and excited about being part of such a great team including: Dominick Baier, Vittorio Bertocci, Keith Brown, David Hill and Eugenio Pace. I’m sure that something great will come up from this team, the board of reviewers and the community that will help to prioritize and keep the focus!

Another identity development widget brought to you by Vittorio’s team. This time it’s a very tiny control called clip_image002SecurityTokenVisualizer that helps debugging claims-aware web applications. But the thing I like of this control is that it can also be used as a teaching tool, very useful for demos by the way. Last week we “dogfooded” it during the Iteration Review of an identity-related project and the audience made the click when we expanded the red small pentagon that shows the behind the scenes.

Simply drag and drop the control on any page and it will render a collapsible table with

  • Issued Identity claims
  • Delegated Identity claims
  • The raw SAML token (in a textarea)
  • The SAML token properties (validfrom, validto, audience, signing certificate, etc.)
  • The certificate used for token decryption

As usual, read the details on Vittorio’s blog.

Vittorio just announced it in his blog… we helped writing an experiment of raising the level of abstraction to work against claims. We created a server control that allows you to work with claims. There are three types of expression:
  • Claim Value: set the value of a property with the value of a specified claim type

<cc1:ClaimsDrivenModifierControl ID=”cdmFirstName” runat=”server” ControlToDrive=”txtFirstName” PropertyToModify=”Text”> <Expression Type=”ClaimValue”> <ClaimType>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname</ClaimType> </Expression> </cc1:ClaimsDrivenModifierControl>

  • Condition: set the value of a property based on a condition <cc1:ClaimsDrivenModifierControl ID=”cdmPrivileges” runat=”server” ControlToDrive=”pnlPrivileges” PropertyToModify=”Visible”> <Expression Type=”Condition”> <ClaimType>http://cloudbuddies.com/2009/06/FrequentFlierProgram</ClaimType> <Operator>Equals</Operator> <Value>FabrikamAirlines</Value> </Expression> </cc1:ClaimsDrivenModifierControl>
    • Mapping: it will set the value of a property based on a set of conditions with an output <cc1:ClaimsDrivenModifierControl ID=”cdmMemebershipLevel” runat=”server” ControlToDrive=”imgMembershipLevel” PropertyToModify=”ImageUrl”> <Expression Type=”Mapping”> <cc1:Mapping ClaimType=”http://cloudbuddies.com/2009/06/FrequentFlierLevel” ClaimValue=”silver” Result=”~/img/silver.png” /> <cc1:Mapping ClaimType=”http://cloudbuddies.com/2009/06/FrequentFlierLevel” ClaimValue=”gold” Result=”~/img/gold.png” /> </Expression> </cc1:ClaimsDrivenModifierControl>

    And of course you can use the designer to set this all up. I’m not a huge fan of server controls and designers but I know that there are people out there that loves them, so this is something that will bring you closer to developing claims-aware applications.

    Download the control from http://code.msdn.microsoft.com/ClaimsDrivenControl/Release/ProjectReleases.aspx?ReleaseId=2861

  • The following table shows an analogy of identity concepts between a single application and a federated application.

    The single app has its own identity silo and the federated app relies on an STS (like Geneva Server). I find this analogy useful to explain how things differ from the non-federated non-claim-based world.

    image

    Couple of months ago Ezequiel posted a summary of a very interesting article published on the Identity issue of the Architecture Journal. This article talked about different patterns on the federated identity world. Last week we had an interesting requirement to solve in a project and this article came to my mind. Specifically one of the scenarios this article points out is when you don’t want the consumer to have knowledge about the relying party STS or you don’t want the client to “see” the token from that STS. The figure below illustrates this scenario. In this diagram, the relying party (service) will receive a token from STS A and will call the STS B to obtain the token.

    This might be helpful when you can’t change the consumer side of the equation. This lead me to introduce the federated blog engine and how we leveraged this in that project…

    The Federated Blog Engine

    Let’s say we want to implement a blog engine where users can access through federated identity. My blog engine supports the passive profile federation, so when someone access it will get redirected to its IP STS, get authenticated, post the token to the website and voila! We can create new blog posts under our organization identity.

    So far nothing new here. Now let’s say that we want to be able to post through Windows Live Writer. This is a rich client that runs on your desktop that you can’t change. On the other side the blog engine will have to expose the MetaWeblog API. Every operation of this API receives the user and password like the code below:

    string NewPost(string blogId, string username, string password, Post post, bool publish);

    In this case, the token on the client is a UsernameToken (not the WS-Security one, but think about the analogy). We will send that token (through Https) to the remote MetaWeblog API.

    NewPost("mwoloski", "DOMAIN\matias", "mypassword", post, true)

    When the message gets to the service we can intercept it and call the STS that will validate the credentials and will issue a SAML token for the service. The following piece of code shows how to make such request to a Geneva Server Beta 2 using the UserNameMixed endpoint. This endpoint will authenticate the user against AD.

    private static ClaimsIdentityCollection GetToken(string username, string password, Uri stsUrl, X509Certificate2 signatureCertificate, Uri relyingPartyIdentifier, X509Certificate2 decryptingCertificate){    var binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential, false);    binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;    binding.Security.Message.EstablishSecurityContext = false;
    
        var credentials = new ClientCredentials();    credentials.UserName.UserName = username;    credentials.UserName.Password = password;    var client = new WSTrustClient(binding, new EndpointAddress(stsUrl), TrustVersion.WSTrust13, credentials);
    
        var request = new RequestSecurityToken();    request.RequestType = "http://schemas.microsoft.com/idfx/requesttype/issue";    request.AppliesTo = new EndpointAddress(relyingPartyIdentifier);    var token = client.Issue(request) as GenericXmlSecurityToken;
    
        var claims = token.ToClaimsIdentityCollection(TrustVersion.WSTrust13, signatureCertificate, decryptingCertificate);
    
        return claims;}

    var token = GetToken("matias",         "password",         new Uri("https://genevaserverurl/Trust/13/UsernameMixed"),        CertificateUtility.GetCertificate(StoreName.TrustedPeople, StoreLocation.LocalMachine, "CN=Geneva Signing Certificate…"),        new Uri("http://hostname/someservice"),        CertificateUtility.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=hostname"))

     
    In the Geneva Server console we configured a new relying party providing the encrypting certificate and the identifier (http://hostname/someservice). If you noticed the code above we are sending those parameters so Geneva Server can execute the rules configured for that relying party and the token gets encrypted with the certificate.
     
    image
     
    Then we have configured a rule that will output the name, groups and UPN of the user that is being authenticated. Those attributes will be taken from the AD store but if we had a SQL where we stored user attributes or ADLDS
     
    image
     
    Finally you can see below a console app that is exercising the code above. Here is what Geneva Server returns. Notice the name, group and upn claims.
    image
     

    This post had a lot of visits so I have updated it to work with Geneva Beta 2

       1: public static ClaimsIdentityCollection ToClaimsIdentityCollection(this GenericXmlSecurityToken originalToken, TrustVersion trustVersion, X509Certificate2 signature, X509Certificate2 encryption)

       2: {

       3:     var tokenReader = new StringReader(originalToken.TokenXml.OuterXml);

       4:     var reader = XmlReader.Create(tokenReader);

       5:  

       6:     var privateKeyToken = new X509SecurityToken(encryption);

       7:     var issuerKeyToken = new X509SecurityToken(signature);

       8:     var tokens = new List<SecurityToken>();

       9:     tokens.Add(privateKeyToken);

      10:     tokens.Add(issuerKeyToken);

      11:     SecurityTokenResolver outOfBandTokenResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(new ReadOnlyCollection<SecurityToken>(tokens), false);

      12:  

      13:     var handlers = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();

      14:     var samlHandler = handlers[typeof(SamlSecurityToken)] as Saml11SecurityTokenHandler;

      15:     samlHandler.ContainingCollection[typeof(EncryptedSecurityToken)].Configuration.ServiceTokenResolver = outOfBandTokenResolver;

      16:     var issuerRegistry = new ConfigurationBasedIssuerNameRegistry();

      17:     issuerRegistry.AddTrustedIssuer(signature.Thumbprint, signature.Subject);

      18:     samlHandler.Configuration.IssuerNameRegistry = issuerRegistry;

      19:  

      20:     var serializer = new SecurityTokenSerializerAdapter(handlers,

      21:         SecurityVersion.WSSecurity11,

      22:         trustVersion,

      23:         trustVersion == TrustVersion.WSTrust13 ? SecureConversationVersion.WSSecureConversation13 : SecureConversationVersion.WSSecureConversationFeb2005,

      24:         false,

      25:         null,

      26:         null,

      27:         null);

      28:  

      29:     var samlSecurityToken = serializer.ReadToken(reader, outOfBandTokenResolver);

      30:     reader.Close();

      31:  

      32:     var claims = handlers.ValidateToken(samlSecurityToken);

      33:  

      34:     return claims;

      35: }

     

    During the last couple of months I’ve been helping the Microsoft DPE team (namely Vittorio and Donovan) building the Identity Development Training Kit. It’s been great to work with such knowledgeable guys like them and with one of the best frameworks I’ve ever developed with: Microsoft Geneva Framework. Identity Training Kit

    The training kit covers a lot of interesting scenarios related to claim-based identity. Here is the shortcut list (if you want a full explanation of each one, read Vittorio’s post)

    • Lab: Web Sites and Identity:
      • Exercise 1: Enabling claims based access for an ASP.NET Web Application by generating a local STS
      • Exercise 2: Customizing the Credentials Accepted by a Local STS
      • Exercise 3: Accepting Tokens from a Geneva Server STS
      • Exercise 4: Accepting Tokens from Live ID
      • Exercise 5: Accepting Tokens from .NET Access Control Service
      • Exercise 6: Invoking a WCF Service on the Backend via Delegated Access
    • Lab: Enhancing an ASP.NET Membership Provider Website with Identity Provider Capabilities
    • Lab: Web Services and Identity
      • Exercise 1: Using Geneva Framework for Handling Authentication and Authorization in a WCF Service
      • Exercise 2: Accepting Tokens from a Geneva Server STS
      • Exercise 3: Accepting Tokens from .NET Access Control Service
      • Exercise 4: Invoking a WCF Service on the Backend via Delegated Access

    We made sure that all of the exercises followed the best practices of developing with Geneva Framework. Building this training kit was a big effort and I would like to mention the great team that helped creating this:  Ariel “lutz” Neisen, Jonathan “passive” Cisneros, Ezequiel “checklist” Sculli and Sebastian “pattern” Iacomuzzi

    I invite you to take a look at the training kit and open your mind with the new possibilities the Geneva Framework brings into the table.