本文介绍了是否可以在一个 ASP.NET MVC 应用程序中同时使用 Azure AD 和个人帐户身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过在 Startup.Auth.cs 文件中执行此操作,我有点成功

I am kind of successful by doing this in the Startup.Auth.cs file

  // Configure the db context and user manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.Properties["Microsoft.Owin.Security.Constants.DefaultSignInAsAuthenticationType"] = "ExternalCookie";

        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
             Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        app.UseOpenIdConnectAuthentication(
          new OpenIdConnectAuthenticationOptions
          {
              ClientId = clientId,
              Authority = authority,
              PostLogoutRedirectUri = postLogoutRedirectUri
          });

我面临的挑战是,当用户注销并尝试访问非登录页面时,例如 http://mywebsite/users/management 而不是 http://mywebsite/account/login 应用程序重定向自动到 Azure AD 登录页面,这是不对的.因为可能有些用户根本没有 Azure AD 帐户.即使我们在 AD 登录页面中提供了正确的用户名和密码并单击登录,它也会在 http 内的不同 url 之间重定向://login.windows.net 并且从不访问我们的网站.

The challenge I have is, when a user is signed out,and tries to hit a non-login page like say http://mywebsite/users/management rather than http://mywebsite/account/login the application redirects to the Azure AD sign-in page automatically, which is not right. Because there could be users who do not have account on Azure AD at all. Even if we give a proper userid and password in the AD sign in page and click sign-in, it keeps redirecting between different urls within http://login.windows.net and never goes to our website at all.

这是注销代码 -

           AuthenticationManager.SignOut(new string[] { DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.ApplicationCookie, OpenIdConnectAuthenticationDefaults.AuthenticationType });
        return RedirectToAction("Login", "Account");

我不确定我在这里做错了什么.

I am not sure what I'm doing wrong here.

编辑 1我的 ExternalLoginCallback 方法

Edit 1My ExternalLoginCallback method

public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (loginInfo == null)
        {
            return RedirectToAction("Login");
        }

        var claims = new List<Claim>();
        claims.Add(new Claim(ClaimTypes.Sid, "Office365"));

        // Sign in the user with this external login provider if the user already has a login

        var user = await UserManager.FindByEmailAsync(loginInfo.ExternalIdentity.Name);

        if (user != null && user.IsActive == true && user.EmailConfirmed == true)
        {
            var result = await UserManager.AddLoginAsync(user.Id, loginInfo.Login);

            if (result.Succeeded)
            {
                if (claims != null)
                {
                    var userIdentity = await user.GenerateUserIdentityAsync(UserManager);
                    userIdentity.AddClaims(claims);
                }
            }

            await SignInAsync(user, isPersistent: true);
            Session[AppConstants.General.UserID] = user.Id;

            string fullName = string.Format("{0} {1}",user.FirstName,user.LastName);
            Session[AppConstants.General.UserFullName] = fullName;

            return RedirectToLocal(returnUrl);
        }
        else
        {
            // If the user does not have an account, tell that to the user.
            ViewBag.ReturnUrl = returnUrl;
            ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
            return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
        }
    }

推荐答案

试试这个

app.UseOpenIdConnectAuthentication(
           new OpenIdConnectAuthenticationOptions
           {
               ClientId = ClientId,
               Authority = Authority,                   
               Notifications = new OpenIdConnectAuthenticationNotifications()
               {


                   RedirectToIdentityProvider = (context) =>
                   {

                       if (context.Request.Path.Value == "/Account/ExternalLogin" || (context.Request.Path.Value == "/Account/LogOff" && context.Request.User.Identity.IsExternalUser()))
                       {
                           // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                           // this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
                           // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                           string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                           context.ProtocolMessage.RedirectUri = appBaseUrl + "/";
                           context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
                       }
                       else
                       {
                           //This is to avoid being redirected to the microsoft login page when deep linking and not logged in 
                           context.State = Microsoft.Owin.Security.Notifications.NotificationResultState.Skipped;
                           context.HandleResponse();
                       }
                       return Task.FromResult(0);
                   },
               }
           });

忘记这个扩展方法

    public static class IdentityExtensions
{
    public static bool IsExternalUser(this IIdentity identity)
    {
        ClaimsIdentity ci = identity as ClaimsIdentity;

        if (ci != null && ci.IsAuthenticated == true)
        {
            var value = ci.FindFirstValue(ClaimTypes.Sid);
            if (value != null && value == "Office365")
            {
                return true;
            }
        }
        return false;
    }
}

编辑 2:

您必须在 ExternalLoginCallback (AccountController) 中有一些自定义逻辑,例如添加 Sid 声明.在这种情况下,还有检查用户是否允许外部登录的逻辑.

You have to have some custom logic in the ExternalLoginCallback (AccountController) e.g. add the Sid claim. In this case there is also logic to check if the user allows external login.

 // GET: /Account/ExternalLoginCallback
    [AllowAnonymous]
    public async Task<ActionResult> ExternalLoginCallback(string returnUrl, string urlHash)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (loginInfo == null)
        {
            return RedirectToAction("Login");
        }

        var claims = new List<Claim>();
        claims.Add(new Claim(ClaimTypes.Sid, "Office365"));

        // 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)
        {
            user = await UserManager.FindByNameAsync(loginInfo.DefaultUserName);

            if (user != null)
            {
                if(user.AllowExternalLogin == false)
                {
                    ModelState.AddModelError("", String.Format("User {0} not allowed to authenticate with Office 365.", loginInfo.DefaultUserName));
                    return View("Login");
                }
                var result = await UserManager.AddLoginAsync(user.Id, loginInfo.Login);

                if (result.Succeeded)
                {
                    if (claims != null)
                    {
                        var userIdentity = await user.GenerateUserIdentityAsync(UserManager);
                        userIdentity.AddClaims(claims);
                    }
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                }
                return RedirectToLocal(returnUrl);
            }
            else
            {
                ModelState.AddModelError("", String.Format("User {0} not found.", loginInfo.DefaultUserName));
                return View("Login");
            }
        }
        else
        {

            if (user.AllowExternalLogin == false)
            {
                ModelState.AddModelError("", String.Format("User {0} not allowed to authenticate with Office 365.", loginInfo.DefaultUserName));
                return View("Login");
            }

            if (claims != null)
            {
                var userIdentity = await user.GenerateUserIdentityAsync(UserManager);
                userIdentity.AddClaims(claims);
            }
            await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
            return RedirectToLocal(returnUrl);
        }
    }

这篇关于是否可以在一个 ASP.NET MVC 应用程序中同时使用 Azure AD 和个人帐户身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 10:43