Test driving the WS-Federation Authentication Middleware for Katana

Microsoft just released an alpha version of the “most wanted” middleware for Katana: WS-Federation authentication!

I tested the bits against ADFS and of course – IdentityServer – and it is unspectacularly easy to get started (that’s a good thing).

1 The WS-Fed middleware itself
As with all other middlewares you wire it up in your Startup class:

app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions

{

    MetadataAddress = https://idsrv.local/…/metadata.xml,

    Wtrealm = “urn:owinrp”,

 

    TokenValidationParameters = new TokenValidationParameters

    {

        ValidAudience = “urn:owinrp”

    },

});

Remember the various configuration entries for the FAM and SAM in web.config – those have been essentially condensed down to the MetadataAddress property. Nice!

Of course you can still take control over validation yourself. But that’s for a future post.

2 Establishing the local authentication session
In WIF the FAM used the SAM to sign in locally (and that was hardwired). The equivalent of the SAM is now the Katana cookie middleware. It is not yet as feature rich as the SAM (e.g. chunking and reference mode missing) – but it is an alpha release.

app.UseCookieAuthentication(new CookieAuthenticationOptions

{

    AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType

});

Contrary to the normal Katana authentication middleware design pattern, where you specify which middleware to use to establish the local session (the SignInAsAuthenticationType property), the cookie middleware you want to use must “listen” to a pre-defined authentication type. I hope this will change in later versions.

3 Signing in
To initiate the WS-Fed handshake, you simply emit a 401:

app.Map(“/login”, map =>

{

    map.Run(async ctx =>

    {

        if (ctx.Authentication.User == null ||

            !ctx.Authentication.User.Identity.IsAuthenticated)

        {

            ctx.Response.StatusCode = 401;

        }

        else

        {

            ctx.Response.Redirect(“/”);

        }

    });

});

Again there are some open questions, e.g. will the Katana AuthenticationManager APIs like AuthenticateAsync or Challenge in active and passive mode scenarios behave as expected. We will find out in a future post!

4 Signing out
Signing out works like this:

app.Map(“/logout”, map =>

{

    map.Run(async ctx =>

    {

        ctx.Authentication.SignOut();

        ctx.Response.Redirect(“/”);

    });

 

});

This does a federated sign out.

5 Access the claims
…and finally we have access to the user’s claims in our application:

app.Run(async ctx =>

    {

        var user = ctx.Authentication.User;

        var response = ctx.Response;

 

        response.ContentType = “text/html”;

 

        if (user.Identity.IsAuthenticated)

        {

            await response.WriteAsync(string.Format(“<h2>{0}</h2>”,

                user.Claims.First().Issuer));

 

            await response.WriteAsync(“<dl>”);

            foreach (var claim in user.Claims)

            {

                await response.WriteAsync(string.Format(

                    “<dt>{0}</dt> <dd>{1}</dd>”,

                    claim.Type,

                    claim.Value));

            }

            await response.WriteAsync(“</dl>”);

        }

        else

        {

            await ctx.Response.WriteAsync(“<h2>anonymous</h2>”);

        }

    });

 

This is an excellent start. More to come!

(full gist is here)

This entry was posted in IdentityServer, Katana, OWIN. Bookmark the permalink.

7 Responses to Test driving the WS-Federation Authentication Middleware for Katana

  1. Andreas Leitel says:

    Hi
    I am about to implement a scenario using UseWsFederationAuthentication. Apart from the front end serving WebForms, etc., we also provide a WCF Service endpoint. In order for WCF to work with SAML2 Tokens, it seems to be necessary to let the STS encrypt the SecurityTokens (we use Azure Access Control Service). This results is an encypted security token (EncryptedAssertion). Do you have any idea, where to “plugin” the SecurityToken decryption?
    Thanks and regards, Andreas

    • You would use standard WCF/.NET facilities to setup the SAML2 support – check the WCF docs.

      I also wrote about a similar scenario here:

      WCF and Identity in .NET 4.5: External Authentication with WS-Trust

      • Andreas Leitel says:

        Hi Dominick
        thanks for the Feedback. What I really was trying to do was:
        – use Owin WsFederationAuthenticationExtensions in a single Azure WebRole that exposes both, WebForms AND WCF endpoints. All of them within the same realm (or Access Control Service Namespace respectively). The main problem seems to be that the “very Alpha” Version of Microsoft.IdentityModel.Extensions.Saml2SecurityTokenHandler (from assembly Microsoft.IdentityModel.Protocol.Extensions.1.0.0-alpha) “looses” the ServiceTokenResolver during its ValidateToken call. Since the ServiceTokenResolver holds the X509SecurityToken referencing the private key needed to decrypt the SAML2 token (EncryptedAssertion), we can not authenticate at all. I did subclass Microsoft.IdentityModel.Extensions.Saml2SecurityTokenHandler and override ValidateToken. After that I was able to decrypt the EncryptedAssertion. But of some reason, the ClaimsIdentity didn’t get into neither the Owin request nor the Thread nor somewhere else. If you see any other option to implement Ws-Federation similar to what is provided by Owin and the new Wif 4.5 but that works with encrypted SAML2 Tokens, I would really appreciate to get any info about it.
        Any way, thank you very much

  2. Everything you need to connect to WCF to a SAML2 token is built-in in .NET 4.5 – I wouldn’t use any of the OWIN stuff for that.

    • Andreas Leitel says:

      Sure, that’s true. But as I said, my scenario not only includes WCF but also pure “HTTP” front end stuff. This is where I got problems with the Owin WsFederationAuthenticationExtensions. Or in other word… Owin is not yet ready for encrypted tokens. Never mind… It was a try, we now change the security architecure a bit and everyting will be fine. Sounds good isn’t it?
      Regards, Andreas

  3. Hi Andreas,

    I also wanted owin to be able to decrypt saml2 tokens and I ended up with subclassing Microsoft.IdentityModel.Extensions.Saml2SecurityTokenHandler and forcing the ServiceTokenResolver on CanReadToken and ReadToken.
    See here https://gist.github.com/andreasbotsikas/11356884

    Thanks for the article,
    Andreas

    • Andreas Leitel says:

      Hi Andreas (Botsikas)
      Thanks for your input. As I said, we changed our (security) architecture a bit. As a result, WCF is no longer directly accessed by the client. WCF endpoints were moved to the backend (pure service layer). Clients now only communication over REST alike interfaces, (i.e. HTTP only, no WS/SOAP at all). We no longer need WCF to deal with SAML2 tokens.

      Thanks any way
      Andreas

Leave a comment