.NET 如果 OIDC 提供的用户在数据库中不可用,如何不进行身份验证
.NET How to NOT authenticate if provided user from OIDC is not available in database
所以我的 .NET Core WebApplication 正在通过 Azure AD 登录用户,我有一个包含用户及其角色的数据库。
我已经创建了 OIDC 中间件来从我的数据库中为尝试登录的用户添加声明。
所以流程是:
- 我用我的AD账号登录
- 我得到电子邮件地址并在数据库中检查它的角色
- 现在如果用户被阻止或未分配,登录应该会失败
所以我的问题是:当用户在数据库中不可用或被阻止时,有没有办法拒绝用户的身份验证?
我现在所做的是设置一个声明,如果该声明不可用,它将被重定向到拒绝访问页面(通过使用 AuthorizationPolicy),但我希望用户将被重定向到登录页面来自 Microsoft/AD(最好有一条消息)。
这是否可能,如果可能,如何实现?
现在这是我的代码:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => { Configuration.Bind("AzureAd", options); }
);
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireAssertion(context =>
{
Claim claim = context.User.Claims.First(claim => claim.Type == ClaimTypes.Expired);
return context.User.HasClaim(x => x.Type == ClaimTypes.Expired) &&
context.User.Claims.First(claim => claim.Type == ClaimTypes.Expired).Value
.Equals("false", StringComparison.OrdinalIgnoreCase);
})
.RequireClaim(ClaimTypes.Name)
.RequireClaim(ClaimTypes.Role)
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
// OIDC Middleware, to access the User's Claims while logging in through AzureAD
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = ctx =>
{
ctx.Response.Redirect("/");
ctx.HandleResponse();
return Task.CompletedTask;
},
OnSignedOutCallbackRedirect = ctx =>
{
ctx.Response.Redirect("/");
ctx.HandleResponse();
return Task.CompletedTask;
},
OnTokenValidated = ctx =>
{
// Get the user's email
var email = ctx.Principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
// Query the database to get the role
using (var db = ctx.HttpContext.RequestServices.GetRequiredService<TracingContext>())
{
// Get the Users from the database, with the logged in email address (from Azure)
User user = db.Users.FirstOrDefault(u => u.UPN.Equals(email));
if (user != null)
{
user.LastLogin = DateTime.Now;
db.SaveChanges();
// Add claims
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, user.Role.ToString()),
new Claim(ClaimTypes.Expired, (!user.IsActivated || user.IsBlocked).ToString())
};
// Save the claim
var appIdentity = new ClaimsIdentity(claims);
ctx.Principal.AddIdentity(appIdentity);
}
else
{
**// Send back to Login Page (with error message, maybe?)**
}
}
return Task.CompletedTask;
},
};
});
您可以覆盖默认处理并自己处理响应:
// Send back to Login Page (with error message, maybe?)
ctx.HandleResponse();
ctx.Response.Redirect("/path/to/login");
对 HandleResponse
的调用表示我们要自己处理响应,接下来的调用会设置重定向。有几种发送错误消息的方法。一种方法是向登录 URL.
提供查询字符串参数
所以我的 .NET Core WebApplication 正在通过 Azure AD 登录用户,我有一个包含用户及其角色的数据库。
我已经创建了 OIDC 中间件来从我的数据库中为尝试登录的用户添加声明。
所以流程是:
- 我用我的AD账号登录
- 我得到电子邮件地址并在数据库中检查它的角色
- 现在如果用户被阻止或未分配,登录应该会失败
所以我的问题是:当用户在数据库中不可用或被阻止时,有没有办法拒绝用户的身份验证?
我现在所做的是设置一个声明,如果该声明不可用,它将被重定向到拒绝访问页面(通过使用 AuthorizationPolicy),但我希望用户将被重定向到登录页面来自 Microsoft/AD(最好有一条消息)。
这是否可能,如果可能,如何实现?
现在这是我的代码:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => { Configuration.Bind("AzureAd", options); }
);
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireAssertion(context =>
{
Claim claim = context.User.Claims.First(claim => claim.Type == ClaimTypes.Expired);
return context.User.HasClaim(x => x.Type == ClaimTypes.Expired) &&
context.User.Claims.First(claim => claim.Type == ClaimTypes.Expired).Value
.Equals("false", StringComparison.OrdinalIgnoreCase);
})
.RequireClaim(ClaimTypes.Name)
.RequireClaim(ClaimTypes.Role)
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
// OIDC Middleware, to access the User's Claims while logging in through AzureAD
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Events = new OpenIdConnectEvents
{
OnRemoteFailure = ctx =>
{
ctx.Response.Redirect("/");
ctx.HandleResponse();
return Task.CompletedTask;
},
OnSignedOutCallbackRedirect = ctx =>
{
ctx.Response.Redirect("/");
ctx.HandleResponse();
return Task.CompletedTask;
},
OnTokenValidated = ctx =>
{
// Get the user's email
var email = ctx.Principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
// Query the database to get the role
using (var db = ctx.HttpContext.RequestServices.GetRequiredService<TracingContext>())
{
// Get the Users from the database, with the logged in email address (from Azure)
User user = db.Users.FirstOrDefault(u => u.UPN.Equals(email));
if (user != null)
{
user.LastLogin = DateTime.Now;
db.SaveChanges();
// Add claims
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, user.Role.ToString()),
new Claim(ClaimTypes.Expired, (!user.IsActivated || user.IsBlocked).ToString())
};
// Save the claim
var appIdentity = new ClaimsIdentity(claims);
ctx.Principal.AddIdentity(appIdentity);
}
else
{
**// Send back to Login Page (with error message, maybe?)**
}
}
return Task.CompletedTask;
},
};
});
您可以覆盖默认处理并自己处理响应:
// Send back to Login Page (with error message, maybe?)
ctx.HandleResponse();
ctx.Response.Redirect("/path/to/login");
对 HandleResponse
的调用表示我们要自己处理响应,接下来的调用会设置重定向。有几种发送错误消息的方法。一种方法是向登录 URL.