通过在 Startup.Auth.cs 文件中执行此操作,我取得了一定的成功
// 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 登录页面中提供正确的用户 ID 和密码并单击登录,它仍然会在 http://login.windows.net 内的不同 URL 之间进行重定向。并且根本不访问我们的网站。
这是注销代码 -
AuthenticationManager.SignOut(new string[] { DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.ApplicationCookie, OpenIdConnectAuthenticationDefaults.AuthenticationType });
return RedirectToAction("Login", "Account");
我不确定我在这里做错了什么。
编辑 1 我的ExternalLoginCallback方法
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 声明。在这种情况下,还有检查用户是否允许外部登录的逻辑。
// 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);
}
}
关于c# - 是否可以在一个 ASP.NET MVC 应用程序中同时进行 Azure AD 和个人帐户身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29006822/