public static IAppBuilder UseUmbracoBackOfficeAdfsAuthentication(
            this IAppBuilder app,
            string caption             = "AD FS",
            string style               = "btn-microsoft",
            string icon                = "fa-windows",
            string[] defaultUserGroups = null,
            string defaultCulture      = "en-GB",
            Action <BackOfficeIdentityUser, ExternalLoginInfo> onAutoLinking = null,
            Func <SecurityTokenValidatedNotification <WsFederationMessage, WsFederationAuthenticationOptions>, Task> onSecurityTokenValidated = null
            )
        {
            var adfsMetadataEndpoint           = ConfigurationManager.AppSettings["AdfsMetadataEndpoint"];
            var adfsRelyingParty               = ConfigurationManager.AppSettings["AdfsRelyingParty"];
            var adfsFederationServerIdentifier = ConfigurationManager.AppSettings["AdfsFederationServerIdentifier"];

            app.SetDefaultSignInAsAuthenticationType(Constants.Security.BackOfficeExternalAuthenticationType);

            var wsFedOptions = new WsFederationAuthenticationOptions
            {
                Wtrealm                    = adfsRelyingParty,
                MetadataAddress            = adfsMetadataEndpoint,
                SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType,
                Caption                    = caption
            };

            wsFedOptions.ForUmbracoBackOffice(style, icon);

            wsFedOptions.AuthenticationType = adfsFederationServerIdentifier;

            var autoLinking = new ExternalSignInAutoLinkOptions(
                autoLinkExternalAccount: true,
                defaultUserGroups: defaultUserGroups ?? new[] { "writer" },
                defaultCulture: defaultCulture)
            {
                OnAutoLinking = onAutoLinking
            };

            if (onSecurityTokenValidated != null)
            {
                wsFedOptions.Notifications = new WsFederationAuthenticationNotifications
                {
                    SecurityTokenValidated = onSecurityTokenValidated
                };
            }

            wsFedOptions.SetExternalSignInAutoLinkOptions(autoLinking);

            app.UseWsFederationAuthentication(wsFedOptions);

            return(app);
        }
 public BackOfficeExternalLoginProviderOptions(
     string buttonStyle,
     string icon,
     ExternalSignInAutoLinkOptions autoLinkOptions = null,
     bool denyLocalLogin = false,
     bool autoRedirectLoginToExternalProvider = false,
     string customBackOfficeView = null)
 {
     ButtonStyle     = buttonStyle;
     Icon            = icon;
     AutoLinkOptions = autoLinkOptions ?? new ExternalSignInAutoLinkOptions();
     DenyLocalLogin  = denyLocalLogin;
     AutoRedirectLoginToExternalProvider = autoRedirectLoginToExternalProvider;
     CustomBackOfficeView = customBackOfficeView;
 }
Ejemplo n.º 3
0
        public async Task <HttpResponseMessage> PostUnLinkLogin(UnLinkLoginModel unlinkLoginModel)
        {
            var owinContext = TryGetOwinContext().Result;
            ExternalSignInAutoLinkOptions autoLinkOptions = null;
            var authType = owinContext.Authentication.GetExternalAuthenticationTypes().FirstOrDefault(x => x.AuthenticationType == unlinkLoginModel.LoginProvider);

            if (authType == null)
            {
                Logger.Warn <BackOfficeController>("Could not find external authentication provider registered: {LoginProvider}", unlinkLoginModel.LoginProvider);
            }
            else
            {
                autoLinkOptions = authType.GetExternalSignInAutoLinkOptions();
                if (!autoLinkOptions.AllowManualLinking)
                {
                    // If AllowManualLinking is disabled for this provider we cannot unlink
                    return(Request.CreateResponse(HttpStatusCode.BadRequest));
                }
            }

            var result = await UserManager.RemoveLoginAsync(
                User.Identity.GetUserId <int>(),
                new UserLoginInfo(unlinkLoginModel.LoginProvider, unlinkLoginModel.ProviderKey));

            if (result.Succeeded)
            {
                var user = await UserManager.FindByIdAsync(User.Identity.GetUserId <int>());

                await SignInManager.SignInAsync(user, isPersistent : true, rememberBrowser : false);

                return(Request.CreateResponse(HttpStatusCode.OK));
            }
            else
            {
                AddModelErrors(result);
                return(Request.CreateValidationErrorResponse(ModelState));
            }
        }
Ejemplo n.º 4
0
        private async Task <bool> AutoLinkAndSignInExternalAccount(ExternalLoginInfo loginInfo, ExternalSignInAutoLinkOptions autoLinkOptions)
        {
            if (autoLinkOptions == null)
            {
                return(false);
            }

            if (autoLinkOptions.ShouldAutoLinkExternalAccount(UmbracoContext, loginInfo) == false)
            {
                return(true);
            }

            //we are allowing auto-linking/creating of local accounts
            if (loginInfo.Email.IsNullOrWhiteSpace())
            {
                ViewData.SetExternalSignInProviderErrors(
                    new BackOfficeExternalLoginProviderErrors(
                        loginInfo.Login.LoginProvider,
                        new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." }));
            }
            else
            {
                //Now we need to perform the auto-link, so first we need to lookup/create a user with the email address
                var autoLinkUser = UserManager.FindByEmail(loginInfo.Email);
                if (autoLinkUser != null)
                {
                    try
                    {
                        //call the callback if one is assigned
                        autoLinkOptions.OnAutoLinking?.Invoke(autoLinkUser, loginInfo);
                    }
                    catch (Exception ex)
                    {
                        var msg = "Could not link login provider " + loginInfo.Login.LoginProvider + ".";
                        Logger.Error <BackOfficeController>(ex, msg);
                        ViewData.SetExternalSignInProviderErrors(
                            new BackOfficeExternalLoginProviderErrors(
                                loginInfo.Login.LoginProvider,
                                new[] { msg + " " + ex.Message }));
                        return(true);
                    }

                    await LinkUser(autoLinkUser, loginInfo);
                }
                else
                {
                    if (loginInfo.Email.IsNullOrWhiteSpace())
                    {
                        throw new InvalidOperationException("The Email value cannot be null");
                    }
                    if (loginInfo.ExternalIdentity.Name.IsNullOrWhiteSpace())
                    {
                        throw new InvalidOperationException("The Name value cannot be null");
                    }

                    var groups = Services.UserService.GetUserGroupsByAlias(autoLinkOptions.GetDefaultUserGroups(UmbracoContext, loginInfo));

                    autoLinkUser = BackOfficeIdentityUser.CreateNew(
                        loginInfo.Email,
                        loginInfo.Email,
                        autoLinkOptions.GetDefaultCulture(UmbracoContext, loginInfo));
                    autoLinkUser.Name = loginInfo.ExternalIdentity.Name;
                    foreach (var userGroup in groups)
                    {
                        autoLinkUser.AddRole(userGroup.Alias);
                    }

                    //call the callback if one is assigned
                    try
                    {
                        autoLinkOptions.OnAutoLinking?.Invoke(autoLinkUser, loginInfo);
                    }
                    catch (Exception ex)
                    {
                        var msg = "Could not link login provider " + loginInfo.Login.LoginProvider + ".";
                        Logger.Error <BackOfficeController>(ex, msg);
                        ViewData.SetExternalSignInProviderErrors(
                            new BackOfficeExternalLoginProviderErrors(
                                loginInfo.Login.LoginProvider,
                                new[] { msg + " " + ex.Message }));
                        return(true);
                    }

                    var userCreationResult = await UserManager.CreateAsync(autoLinkUser);

                    if (userCreationResult.Succeeded == false)
                    {
                        ViewData.SetExternalSignInProviderErrors(
                            new BackOfficeExternalLoginProviderErrors(
                                loginInfo.Login.LoginProvider,
                                userCreationResult.Errors));
                    }
                    else
                    {
                        await LinkUser(autoLinkUser, loginInfo);
                    }
                }
            }
            return(true);
        }
Ejemplo n.º 5
0
        private async Task <ActionResult> ExternalSignInAsync(ExternalLoginInfo loginInfo, Func <ActionResult> response)
        {
            if (loginInfo == null)
            {
                throw new ArgumentNullException("loginInfo");
            }
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }
            ExternalSignInAutoLinkOptions autoLinkOptions = null;

            // Here we can check if the provider associated with the request has been configured to allow
            // new users (auto-linked external accounts). This would never be used with public providers such as
            // Google, unless you for some reason wanted anybody to be able to access the backend if they have a Google account
            // .... not likely!
            var authType = OwinContext.Authentication.GetExternalAuthenticationTypes().FirstOrDefault(x => x.AuthenticationType == loginInfo.Login.LoginProvider);

            if (authType == null)
            {
                Logger.Warn <BackOfficeController, string>("Could not find external authentication provider registered: {LoginProvider}", loginInfo.Login.LoginProvider);
            }
            else
            {
                autoLinkOptions = authType.GetExternalSignInAutoLinkOptions();
            }

            // Sign in the user with this external login provider if the user already has a login
            var user = await UserManager.FindAsync(loginInfo.Login);

            if (user != null)
            {
                var shouldSignIn = true;
                if (autoLinkOptions != null && autoLinkOptions.OnExternalLogin != null)
                {
                    shouldSignIn = autoLinkOptions.OnExternalLogin(user, loginInfo);
                    if (shouldSignIn == false)
                    {
                        Logger.Warn <BackOfficeController, string, int>("The AutoLinkOptions of the external authentication provider '{LoginProvider}' have refused the login based on the OnExternalLogin method. Affected user id: '{UserId}'", loginInfo.Login.LoginProvider, user.Id);
                    }
                }

                if (shouldSignIn)
                {
                    //sign in
                    await SignInManager.SignInAsync(user, isPersistent : false, rememberBrowser : false);
                }
            }
            else
            {
                if (await AutoLinkAndSignInExternalAccount(loginInfo, autoLinkOptions) == false)
                {
                    ViewData.SetExternalSignInProviderErrors(
                        new BackOfficeExternalLoginProviderErrors(
                            loginInfo.Login.LoginProvider,
                            new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to an account" }));
                }

                //Remove the cookie otherwise this message will keep appearing
                if (Response.Cookies[Constants.Security.BackOfficeExternalCookieName] != null)
                {
                    Response.Cookies[Constants.Security.BackOfficeExternalCookieName].Expires = DateTime.MinValue;
                }
            }

            return(response());
        }
Ejemplo n.º 6
0
        private async Task<bool> AutoLinkAndSignInExternalAccount(ExternalLoginInfo loginInfo, ExternalSignInAutoLinkOptions autoLinkOptions)
        {
            if (autoLinkOptions == null)
                return false;

            if (autoLinkOptions.ShouldAutoLinkExternalAccount(UmbracoContext, loginInfo) == false)
                return true;

            //we are allowing auto-linking/creating of local accounts
            if (loginInfo.Email.IsNullOrWhiteSpace())
            {
                ViewData.SetExternalSignInError(new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not provided an email address, the account cannot be linked." });
            }
            else
            {
                //Now we need to perform the auto-link, so first we need to lookup/create a user with the email address
                var foundByEmail = Services.UserService.GetByEmail(loginInfo.Email);
                if (foundByEmail != null)
                {
                    ViewData.SetExternalSignInError(new[] { "A user with this email address already exists locally. You will need to login locally to Umbraco and link this external provider: " + loginInfo.Login.LoginProvider });
                }
                else
                {
                    if (loginInfo.Email.IsNullOrWhiteSpace()) throw new InvalidOperationException("The Email value cannot be null");
                    if (loginInfo.ExternalIdentity.Name.IsNullOrWhiteSpace()) throw new InvalidOperationException("The Name value cannot be null");

                    var groups = Services.UserService.GetUserGroupsByAlias(autoLinkOptions.GetDefaultUserGroups(UmbracoContext, loginInfo));

                    var autoLinkUser = BackOfficeIdentityUser.CreateNew(
                        loginInfo.Email,
                        loginInfo.Email,
                        autoLinkOptions.GetDefaultCulture(UmbracoContext, loginInfo));
                    autoLinkUser.Name = loginInfo.ExternalIdentity.Name;
                    foreach (var userGroup in groups)
                    {
                        autoLinkUser.AddRole(userGroup.Alias);
                    }

                    //call the callback if one is assigned
                    if (autoLinkOptions.OnAutoLinking != null)
                    {
                        autoLinkOptions.OnAutoLinking(autoLinkUser, loginInfo);
                    }

                    var userCreationResult = await UserManager.CreateAsync(autoLinkUser);

                    if (userCreationResult.Succeeded == false)
                    {
                        ViewData.SetExternalSignInError(userCreationResult.Errors);
                    }
                    else
                    {
                        var linkResult = await UserManager.AddLoginAsync(autoLinkUser.Id, loginInfo.Login);
                        if (linkResult.Succeeded == false)
                        {
                            ViewData.SetExternalSignInError(linkResult.Errors);

                            //If this fails, we should really delete the user since it will be in an inconsistent state!
                            var deleteResult = await UserManager.DeleteAsync(autoLinkUser);
                            if (deleteResult.Succeeded == false)
                            {
                                //DOH! ... this isn't good, combine all errors to be shown
                                ViewData.SetExternalSignInError(linkResult.Errors.Concat(deleteResult.Errors));
                            }
                        }
                        else
                        {
                            //sign in
                            await SignInManager.SignInAsync(autoLinkUser, isPersistent: false, rememberBrowser: false);
                        }
                    }
                }

            }
            return true;
        }
Ejemplo n.º 7
0
        private async Task<ActionResult> ExternalSignInAsync(ExternalLoginInfo loginInfo, Func<ActionResult> response)
        {
            if (loginInfo == null) throw new ArgumentNullException("loginInfo");
            if (response == null) throw new ArgumentNullException("response");
            ExternalSignInAutoLinkOptions autoLinkOptions = null;

            //Here we can check if the provider associated with the request has been configured to allow
            // new users (auto-linked external accounts). This would never be used with public providers such as
            // Google, unless you for some reason wanted anybody to be able to access the backend if they have a Google account
            // .... not likely!
            var authType = OwinContext.Authentication.GetExternalAuthenticationTypes().FirstOrDefault(x => x.AuthenticationType == loginInfo.Login.LoginProvider);
            if (authType == null)
            {
                Logger.Warn<BackOfficeController>("Could not find external authentication provider registered: {LoginProvider}", loginInfo.Login.LoginProvider);
            }
            else
            {
                autoLinkOptions = authType.GetExternalAuthenticationOptions();
            }

            // Sign in the user with this external login provider if the user already has a login
            var user = await UserManager.FindAsync(loginInfo.Login);
            if (user != null)
            {
                // TODO: It might be worth keeping some of the claims associated with the ExternalLoginInfo, in which case we
                // wouldn't necessarily sign the user in here with the standard login, instead we'd update the
                // UseUmbracoBackOfficeExternalCookieAuthentication extension method to have the correct provider and claims factory,
                // ticket format, etc.. to create our back office user including the claims assigned and in this method we'd just ensure
                // that the ticket is created and stored and that the user is logged in.

                var shouldSignIn = true;
                if (autoLinkOptions != null && autoLinkOptions.OnExternalLogin != null)
                {
                    shouldSignIn = autoLinkOptions.OnExternalLogin(user, loginInfo);
                    if (shouldSignIn == false)
                    {
                        Logger.Warn<BackOfficeController>("The AutoLinkOptions of the external authentication provider '{LoginProvider}' have refused the login based on the OnExternalLogin method. Affected user id: '{UserId}'", loginInfo.Login.LoginProvider, user.Id);
                    }
                }

                if (shouldSignIn)
                {
                    //sign in
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                }
            }
            else
            {
                if (await AutoLinkAndSignInExternalAccount(loginInfo, autoLinkOptions) == false)
                {
                    ViewData.SetExternalSignInError(new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to an account" });
                }

                //Remove the cookie otherwise this message will keep appearing
                if (Response.Cookies[Constants.Security.BackOfficeExternalCookieName] != null)
                {
                    Response.Cookies[Constants.Security.BackOfficeExternalCookieName].Expires = DateTime.MinValue;
                }
            }

            return response();
        }