首页 > 解决方案 > .NET 如果从 OIDC 提供的用户在数据库中不可用,如何不进行身份验证

问题描述

因此,我的 .NET Core WebApplication 正在通过 Azure AD 登录用户,并且我有一个包含用户及其角色的数据库。

我已经创建了 OIDC MiddleWare 以从我的数据库中为尝试登录的用户添加声明。

所以流程是:

所以我的问题是:当用户在数据库中不可用或被阻止时,有没有办法拒绝用户的身份验证?

我现在所做的是我设置了一个声明,如果该声明不可用,它将被重定向到拒绝访问页面(通过使用 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;
                },
            };
        });

标签: c#asp.net-coreopenid-connect

解决方案


您可以覆盖默认处理并自己处理响应:

// Send back to Login Page (with error message, maybe?)
ctx.HandleResponse();
ctx.Response.Redirect("/path/to/login");

对我们想要自己处理响应的信号的调用HandleResponse以及以下调用设置重定向。有几种方法可以发送错误消息。一种方法是向登录 URL 提供查询字符串参数。


推荐阅读