Hide menu Last updated: Sep 21 2015

A common use case for mixed-mode authentication is having ADFS for your back-end users and another authentication provider for website users. Configuring mixed-mode authentication for the Episerver platform requires the following nuget packages as dependencies

  • Microsoft.Owin.Security.Cookies
  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security.WsFederation

To configure mixed mode OWIN authentication, set the authentication type in the system.web section of the web.config.

XML
<authentication mode="None"></authentication>

To configure mixed mode authentication, also create a Startup file in your project that will handle the configuration of the different authentication middleware.

C#
using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Owin;
using WebApplication1.Models;

namespace WebApplication1
{
    public partial class Startup
    {
		    const string LogoutUrl = "/util/logout.aspx";
				
        // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            //This will configure cookie authentication at the following urls.  In those pages you are responsible for authentication and calling the OwinContext.Authentication.SignIn method to properly sign in the user
            // and  OwinContext.Authentication.SignOut to logout a user
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
		            AuthenticationType = "Application",
		            LoginPath = new PathString("/Login"),
		            LogoutPath = new PathString("/Logout")
            });

            //This will set ADFS as the default authentication provider 
            app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
           {
		           AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
           });
            //Enable federated authentication
            app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions()
            {
                //Trusted URL to federation server meta data
                MetadataAddress = "https://devdc.dev.test/federationmetadata/2007-06/federationmetadata.xml",
                //Value of Wtreal must *exactly* match what is configured in the federation server
                Wtrealm = "https://localhost:44303/",
                Notifications = new WsFederationAuthenticationNotifications()
                {
                    RedirectToIdentityProvider = (ctx) =>
                        {
                            //To avoid a redirect loop to the federation server send 403 when user is authenticated but does not have access
                            if (ctx.OwinContext.Response.StatusCode == 401 && ctx.OwinContext.Authentication.User.Identity.IsAuthenticated)
                            {
                                ctx.OwinContext.Response.StatusCode = 403;
                                ctx.HandleResponse();
                            }
                            return Task.FromResult(0);
                        },
                    SecurityTokenValidated = (ctx) =>
                        {
                            //Ignore scheme/host name in redirect Uri to make sure a redirect to HTTPS does not redirect back to HTTP
                            var redirectUri = new Uri(ctx.AuthenticationTicket.Properties.RedirectUri, UriKind.RelativeOrAbsolute);
                            if (redirectUri.IsAbsoluteUri)
                            {
                                ctx.AuthenticationTicket.Properties.RedirectUri = redirectUri.PathAndQuery;
                            }
                            //Sync user and the roles to EPiServer in the background
                            ServiceLocator.Current.GetInstance().SynchronizeAsync(ctx.AuthenticationTicket.Identity);
                            return Task.FromResult(0);
                        }
                }
            });
            //Add stage marker to make sure WsFederation runs on Authenticate (before URL Authorization and virtual roles)
            app.UseStageMarker(PipelineStage.Authenticate);

            //Remap logout to a federated logout
            app.Map(LogoutUrl, map =>
            {
                map.Run(ctx =>
                {
                    ctx.Authentication.SignOut();
                    return Task.FromResult(0);
                });
            });

            //Tell antiforgery to use the name claim
            AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;
        }
    }
}

Related topic

Comments