ASP.NET MVC 标识 - 同时使用内部用户和 Azure AD 身份验证



我们已经在运行一个 ASP.NET 的MVC Web应用程序,该应用程序通过令牌身份验证使用内部用户。这是以 ASP.NET MVC 模板提供的标准方式实现的。

现在,我们需要扩展此身份验证模型,并允许外部 Azure AD 用户登录到已配置租户的 Web 应用程序。我已经弄清楚了Azure AD方面的所有内容。感谢Microsoft的 Azure 示例示例。

现在,个人帐户身份验证Azure AD都可以独立运行。但他们没有一起工作。当我将两个中间件插入在一起时,它的给出问题。

这是我startup_auth.cs文件:

public partial class Startup
{

public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});            
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

string ClientId = ConfigurationManager.AppSettings["ida:ClientID"];            
string Authority = "https://login.microsoftonline.com/common/";
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = ClientId,
Authority = Authority,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{                        
ValidateIssuer = false,
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = (context) =>
{                            
string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;                         
context.ProtocolMessage.RedirectUri = appBaseUrl;
context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
return Task.FromResult(0);
},                        
SecurityTokenValidated = (context) =>
{
// retriever caller data from the incoming principal
string issuer = context.AuthenticationTicket.Identity.FindFirst("iss").Value;
string UPN = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
if (
// the caller comes from an admin-consented, recorded issuer
(db.Tenants.FirstOrDefault(a => ((a.IssValue == issuer) && (a.AdminConsented))) == null)
// the caller is recorded in the db of users who went through the individual onboardoing
&& (db.Users.FirstOrDefault(b =>((b.UPN == UPN) && (b.TenantID == tenantID))) == null)
)
// the caller was neither from a trusted issuer or a registered user - throw to block the authentication flow
throw new SecurityTokenValidationException();                            
return Task.FromResult(0);
},
AuthenticationFailed = (context) =>
{
context.OwinContext.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
}
}
});
}
}

此配置适用于本地用户帐户,但不适用于 AAD。若要启用 AAD 身份验证,我需要配置如下所示的UseCookieAuthentication部分,这将破坏我的本地用户帐户身份验证。

app.UseCookieAuthentication(new CookieAuthenticationOptions { });

基本上我需要删除本地用户中间件才能获得 AAD 工作。

我所说的 AAD 不起作用的意思是,我无法转到受[Authorize]属性保护的任何安全操作。它调用SecurityTokenValidated事件,我能够获取所有 AAD 声明,并能够针对我的自定义租户进行验证。但是当我在最后重定向到我的应用程序的根目录(这是一个安全操作(时,它会将我扔回我的自定义登录页面。似乎它不是在内部登录用户,也没有创建必要的身份验证 cookie。

我将不胜感激关于我在这里可能缺少什么的任何想法。

谢谢

要同时支持个人帐户和来自社交数据提供商的其他帐户,只需使用 OWIN 组件添加它们。

若要注销从 Azure AD 登录的用户,我们需要注销从 Web 应用和 Azure AD 发出的 Cookie。首先,我修改了ApplicationUser类以添加自定义声明,以检测用户是从 Azure AD 还是从个人帐户登录,如下所示。

public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
if((this.Logins as System.Collections.Generic.List<IdentityUserLogin>).Count>0)
userIdentity.AddClaim(new Claim("idp", (this.Logins as System.Collections.Generic.List<IdentityUserLogin>)[0].LoginProvider));
return userIdentity;
}
}

然后,我们可以更改LogOff方法以支持从 Azure AD 注销,以清除 Azure AD 中的 Cookie:

// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
var idpClaim = ClaimsPrincipal.Current.Claims.FirstOrDefault(claim => { return claim.Type == "idp"; });
if (idpClaim!=null)
HttpContext.GetOwinContext().Authentication.SignOut(
OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
return RedirectToAction("Index", "Home");
}

听起来您的OpenID Connect身份验证没有连接到您的Cookie身份验证。 看起来您需要在OpenIdConnectAuthenticationOptions中指定一个与CookieAuthenticationOptionsExternalCookie身份验证类型中的AuthenticationType匹配的SignInAsAuthenticationType

最新更新