How to implement Web Sign On with ADFS in ASP.NET MVC using OWIN

In this Post I will (try to) shortly explain how to Implement Web Sign on with Active Directory Federation Services under ASP.NET MVC and OWIN/Katana as Middleware.

There is plenty of Resources (read Code Snippets) on the Net about this subject, but what I actually found as important as the Code Snippets is actual Configuration of AD FS Server. The Configuration of ADFS is highly sensitive on every identifier, endpoint definition and even on every character like underscores, slashes, and of course prefixes like http/https are all exactly to be defined and used in your Web App!

 

ADFS Server Configuration

That is why I will first show some screenshots and Configuration of my ADFS Server running on Azure VM Development Environment:

Under Authentication Policies, you should enable Forms Authentication for Extranet users. That way it will be possible for users outside your Domain or on a Public Computer to get a nice Forms Authentication provided by ADFS and still get authenticated.

 

You should create new Relying Party Trust with following Configuration: Display Name you can write whatever you want of course. Under Relaying party identifiers, you should add exactly your Web Application URL (Including correct prefix and slash at the end. If you have more Bindings on you Web Application, define all of them.
NOTE: Some users had problems if their Web Application URLs contains underscores, so if you can, try to avoid them.

Under Endpoint Tab, add a WS-Federation Passive Endpoint with the same URL of your Web Application as in Relying party identifiers.
Note: You can also define multiple if you have more the one Binding, but only one can be Default.

Now knowing your exact ADFS Configuration, you will definitely save time and avoid configuration conditioned Problems so we can continue and finally write some Code.

 

ASP.NET Web Application with OWIN Middleware

First we will start off with OWIN Startup.cs Class. We have the Authentication Configuration Method outsourced into separate Class called Startup.Auth.cs, like the Default ASP.NET MVC Web Application Template do it, but many of you have it all directly under Startup.cs.

Startup.cs

using System.Threading.Tasks;

using Microsoft.Owin;

using Microsoft.Owin.Security.WsFederation;

using Owin;

 

[assembly: OwinStartupAttribute(typeof(adfs.demo.Startup))]

 

namespace adfs.demo

{

public partial class Startup

{

public void Configuration(IAppBuilder app)

{

ConfigureAuth(app);

}

}

}

 

Startup.Auth.cs

using System.Configuration;

using Microsoft.Owin.Security.Cookies;

using Owin;

using Microsoft.Owin.Security;

using Microsoft.Owin.Security.WsFederation;

 

namespace adfs.demo

{

public partial class Startup

{

public void ConfigureAuth(IAppBuilder app)

{

app.UseCookieAuthentication(

new CookieAuthenticationOptions

{

AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType

});

app.UseWsFederationAuthentication(

new WsFederationAuthenticationOptions

{

MetadataAddress = ConfigurationManager.AppSettings["ida:ADFSMetadata"],

Wtrealm = ConfigurationManager.AppSettings["ida:Wtrealm"]

});

 

app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);

}

}

}

Both of this entries I have placed in Web.Config and it looks like this:

<appSettings>

<add key="ida:ADFSMetadata" value="http://your-adfs-server.com/FederationMetadata/2007-06/FederationMetadata.xml" />

<add key="ida:Wtrealm" value="https://your-exact-site-url/" />

</appSettings>

Now that should be enough to have OWIN Security running with our ADFS Server. All you have to do now is to add the [Authorize] Tags on needed Controllers or [AllowAnonymous] on single Actions that needs to be accessed anonymously.

Here is one very simple way of using a Templated AccountController.cs with our ADFS Implementation:

using System.Web;

using System.Web.Mvc;

using Microsoft.Owin.Security;

using Microsoft.Owin.Security.Cookies;

using Microsoft.Owin.Security.WsFederation;

 

namespace adfs.demo.Controllers

{

[Authorize]

public class AccountController : Controller

{

[AllowAnonymous]

public void Login(string returnUrl)

{

if (!Request.IsAuthenticated)

{

HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/adfs.demo" },

WsFederationAuthenticationDefaults.AuthenticationType);

}

}

 

public void LogOff()

{

string callbackUrl = Url.Action("Index", "Home", routeValues: null, protocol: Request.Url.Scheme);

 

HttpContext.GetOwinContext().Authentication.SignOut(

new AuthenticationProperties { RedirectUri = callbackUrl },

WsFederationAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);

}

}

}

 

Conclusion

It was actually pretty easy to implement the ADFS Authentication Provider in OWIN once you understand and have access the whole configuration of ADFS Server. So far it looks really fast and stable, beside few problems I had with Chrome and Firefox Browser that I will explain below. So as I promised, this was actually short post and I hope you will get your ADFS running smoothly just as I did.

Chrome / Firefox Redirection Loop Problem
After my first Implementation of ADFS under OWIN, it looked like everything is working well. As soon as I tested it on Chrome and Firefox, I figured out that after Login, I am being redirected to ADFS Forms Authentication Web Page and back to my Default Return URL few times before getting Error Message (that was not telling me much about Error) on my ADFS Forms Authentication Web Page.

In ADFS Event Log, there was this Error event:
Microsoft.IdentityServer.Web.InvalidRequestException: MSIS7042: The same client browser session has made '6' requests in the last '1' seconds. Contact your administrator for details.

There are many explanations and workarounds for the Redirection Loop Problem under OWIN Security, most of them have something to do with CookieManager under OWIN but none of them has solved my problem.

My Solution:
As soon as I have defined "fresh" new Relying Party Trust (see first part of the Post) with exactly the same Relying Party Identifier as an WS-Federation Passive Endpoint URL (and I really mean exactly the same, same prefix, same URL and / at the end of URL, also see first part of the post) and then updated my Web.Config with the exact Values, it all started working as a Charm.


Posted Oct 06 2016, 04:08 PM by Armin Kalajdzija

Comments

tri_tue@yahoo.com wrote re: How to implement Web Sign On with ADFS in ASP.NET MVC using OWIN
on 11-15-2016 11:23

I make all the same your code, last month run ok, but now it's have an error like this "IDX10213: SecurityTokens must be signed. SecurityToken: '{0}'.."

How I fix it? Pls help me.

TriTue (tri_tue@yahoo.com)

Amit wrote re: How to implement Web Sign On with ADFS in ASP.NET MVC using OWIN
on 04-19-2017 1:55

Thanks for your post Armin. Can you please elaborate more about what is redirecturi in

HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/adfs.demo" },

Thanks

James Ryback wrote re: How to implement Web Sign On with ADFS in ASP.NET MVC using OWIN
on 05-01-2017 13:06

Does this accomplish SSO with the federation or will the user be asked to enter username and password?

I am asking because you mention it will enable Forms Authentication which does not indicate SSO.

Single sign on to Episerver with ADFS, using OWIN and WS-Federation – Hacks by Me wrote Single sign on to Episerver with ADFS, using OWIN and WS-Federation &#8211; Hacks by Me
on 05-07-2017 16:12

Pingback from  Single sign on to Episerver with ADFS, using OWIN and WS-Federation – Hacks by Me

Single sign on to Episerver with ADFS, using OWIN and WS-Federation | Hacks by me wrote Single sign on to Episerver with ADFS, using OWIN and WS-Federation | Hacks by me
on 09-21-2017 15:00

Pingback from  Single sign on to Episerver with ADFS, using OWIN and WS-Federation | Hacks by me

developers.de is a .Net Community Blog powered by daenet GmbH.