Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement SAML2 authentication in .net 4.5 against AzureAD? (Consuming Tokens)

I'd like to allow SAML authentication for my web app, including against AzureAD as an identity provider and also ADFS. (Can anyone point me to a good tutorial or walkthrough on this?) I've got so far as generating the SAML Request, getting back a SAMLP response from AzureAD, and validating its signature (including the fact it's SHA256 which doesn't work by default).

Now I want to extract information from it to verify the issuer and get the user's email to identify them. Is it 'ok' to do this manually via XML or should I use classes like Saml2SecurityTokenHandler? They look like they should do the trick but I find it difficult to understand all the configuration required and whether it's necessary to use such classes from a security point of view.

My app is multi-tenant so I want code rather than configuration to process the Saml as different tenants will use different authentication options.

This blog says to not use ConfigurationBasedIssuerNameRegistry and instead points to [ValidatingIssuerNameRegistry][3]. Ok, that seems appropriate for my scenario.

In this question there's some code to programmatically configure a trusted issuer, so I can adjust to use ValidatingIssuerNameRegistry and then presumably I can use tokenHandlers to read the Assertion from the SAMLP response and then extract the claims including the Name (email). But where do I get the thumbprint & name to pass to it from the AzureAD metadata? And exactly what's the value in using these classes instead of parsing the response myself? It definitely feels like using a library for this is the right thing to do, but the complexity of WIF and lack of walk-through articles on doing this makes it feel like something not appropriate except for those deep in the world of identity.

My guess is if I already have the certificate stored locally to validate the identity of the issuer of the SAML response and I verify the signature in the XML then I can happily use the content of the SAML response. i.e. the user's identity. Still it feels like the wrong approach to do this manually though, but I'm ok with that provided there's no obvious drawbacks.

Some related SO questions & articles:

  • How to convert SAML XML token string to either SecurityToken or ClaimsPrincipal instance?
  • web.config convert saml security token to claim principal
  • Working with SAML 2.0 in C# .NET 4.5
  • http://www.cloudidentity.com/blog/2013/03/25/a-refresh-of-the-identity-and-access-tool-for-vs-2012/
like image 419
Rory Avatar asked Feb 13 '16 00:02

Rory


1 Answers

As you've found out - there is no built in support in .NET for the SAML2 Protocol, even though SAML2 tokens are supported.

Instead of doing it yourself, I'd suggest you look into the available opens source and commercial libraries for SAML2P for ASP.NET. There's A LOT of work to build a reliable service provider on top of what's offered in the .NET framework. (I know, because I've built one and if I had known what I now know I don't think I'd do it again).

If you chose to go ahead yourself, the Saml2SecurityTokenHandler contains the important tooling for reading assertions from XML, converting them to claims identities and validating signatures on the assertion. Note that the handler expects the assertions to be signed - there's AFAIK no built in support for handling the case where the entire SAML Response was signed (which covers the embedded Assertions too).

Using Kentor.AuthServices

The scenario described here is using the Kentor.AuthServices API directly, which is an advanced scenario that is not recommended as a first choice. For Web API and modern MVC applications it is much better to use the Owin middleware from the Kentor.AuthServices.Owin package.

The code here is using the API from the Kentor.AuthServices.HttpModule package.

Config

To use the AuthServices API directly, you will first have to create a configuration, as described in the docs. It's possible to do both in code and in web.config. For this example I'll just refer to an Options property which is an IOptions instance. It can be loaded from web.config through the Options.FromConfiguration property.

Send an AuthnRequest

The first step for authentication is sending an AuthnRequest. The dummyUrl is just any non-null Uri object. It won't be used in this scenario, but is not allowed to be null.

var idp = Options.IdentityProviders.Default;
var urls = new AuthServicesUrls(fullUrlOfYourAcsService, dummyUrl, applicationUrl);

var authnRequest = idp.CreateAuthenticateRequest(dummyUrl, urls);

// Apply will call Response.End
idp.Bind(authnRequest).Apply(new HttpResponseWrapper(HttpContext.Current.Response));

Even the OP has managed to do this already, it must be done through AuthServices to correctly register the pending request which is then matched with the returned response.

Receive Response

The next step is to receive the returned SAML2Response. This code should be at the "fullUrlOfYourAcsService" location specified when sending the AuthnRequest.

var result = CommandFactory.GetCommand(CommandFactory.AcsCommandName)
  .Run(new HttpRequestWrapper(HttpContext.Current.Response), Options);

// result.Principal will now contain the received identity.
like image 79
Anders Abel Avatar answered Sep 22 '22 13:09

Anders Abel