Mixed mode authentication with Azure AD and AspNetIdentity

Vote:
 

CMS 11.10.6

Is it possible to configure mixed mode authentication using Azure AD (for CMS users) and AspNetIdentity (for website users) ?

This mixed mode authentication example on Episerver documentation uses ADFS, I assume same can be done with Azure AD and AspNetIdentity  ?

https://world.episerver.com/documentation/developer-guides/CMS/security/configuring-mixed-mode-owin-authentication/

#201971
Mar 11, 2019 4:34
Vote:
 

Yes, we have that set up on one of our projects currently using OpenID for the AzureAD connection as described here https://world.episerver.com/documentation/developer-guides/CMS/security/integrate-azure-ad-using-openid-connect/ . Just need the mixed more autentication method adapted depending on your paths/urls.

This is our code

 string clientId, redirectUrl, authority, host, logoutPath;
            GetSettings(out clientId, out redirectUrl, out authority, out host, out logoutPath);

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            // Configure backend authentcation
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = host,
                RedirectUri = redirectUrl,
                UseTokenLifetime = false,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuer = false,
                    RoleClaimType = ClaimTypes.Role
                },
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthenticationFailed = context =>
                    {
                        context.HandleResponse();
                        context.Response.Write(context.Exception.Message);
                        return Task.FromResult(0);
                    },
                    RedirectToIdentityProvider = context =>
                    {
                        // Here you can change the return uri based on multisite
                        HandleMultiSitereturnUrl(context);

                        // To avoid a redirect loop to the federation server send 403 
                        // when user is authenticated but does not have access
                        if (context.OwinContext.Response.StatusCode == 401 &&
                            context.OwinContext.Authentication.User.Identity.IsAuthenticated)
                        {
                            context.OwinContext.Response.StatusCode = 403;
                            context.HandleResponse();
                        }

                        return Task.FromResult(0);
                    },
                    SecurityTokenValidated = (ctx) =>
                    {
                        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<ISynchronizingUserService>().SynchronizeAsync(ctx.AuthenticationTicket.Identity);
                        return Task.FromResult(0);
                    }
                }
            });

            // Front end user login
            app.AddCmsAspNetIdentity<SjaAppUser>();
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                Provider = new CookieAuthenticationProvider
                {
                    // Enables the application to validate the security stamp when the user logs in.
                    // This is a security feature which is used when you change a password or add an external login to your account.
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager<ApplicationUser>, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => manager.GenerateUserIdentityAsync(user)),
                    OnResponseSignedIn = OnResponseSignedIn
                },
                SlidingExpiration = true,
                ExpireTimeSpan = TimeSpan.FromMinutes(30)
            });

            app.UseStageMarker(PipelineStage.Authenticate);

            app.Map(logoutPath, map =>
            {
                map.Run(ctx =>
                {
                    ctx.Authentication.SignOut();
                    return Task.FromResult(0);
                });
            });
#201977
Mar 11, 2019 9:54
Vote:
 

Thanks Scott for sharing the code

#202011
Mar 12, 2019 0:04
Vote:
 

In my experience it's smarter to put something (for example Auth0 or IdentityServer4) in between Azure AD and the Epi site so you don't have to bloat the Epi site with AspNetIdentity and Role Management. It's a lot cleaner with only an ISynchronizingUserService instance and ClaimsIdentitities and it will also support setting up SSO and API security outside of the Epi application.

#202041
Edited, Mar 12, 2019 13:11
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.