首页 > 解决方案 > 将 Azure AD B2C 用户连接到我的数据库帐户的正确 Core 3.0 API 中间件?

问题描述

我有一个 .Net Core 3 API,可以正确授权和验证通过 Azure AD B2C 传递给它的令牌。它还构建了一些自定义代码,用于检查 JWT 令牌中传递的范围,以确认对端点的访问。(我正在使用 Microsoft.AspNetCore.Authentication.AzureADB2C.UI 包)这是使这成为可能的中间件块:

services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
                .AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options));

var issuer = $"https://{Configuration["AzureAdB2C_Custom:TenantB2CHost"]}/{Configuration["AzureAdB2C:Domain"]}/v2.0/";
services.AddAuthorization(options =>
     {
          options.AddPolicy("api_read", policy => policy.Requirements.Add(new HasScopeRequirement("api_read", issuer)));
          options.AddPolicy("api_write", policy => policy.Requirements.Add(new HasScopeRequirement("api_write", issuer)));
     });

这一切似乎都在努力正确地访问端点。然后,这些端点在模型中公开来自我的 SQL 数据库的各种信息。

但是,现在我正试图通过控制对在这些端点中检索到的数据的特定部分的访问,根据 JWT 令牌在我的数据库中实际绑定的对象,将我的安全性的另一个方面带回家。

在我的特定情况下,我有一个 Accounts 表,我可以在其中存储在 JWT 令牌中找到的来自 Azure AD B2C 的 ObjectID,然后在调用时使用该 ObjectID 获取 Account。我可以在端点的顶部执行此操作,但我怀疑这不是最好的方法。看来我应该在 Startup 的中间件层构建它作为某种处理程序。

有人可以为我确认这将是正确的方法,并可能给我一个例子,或者至少为我指明正确的方向吗?

标签: azureasp.net-coreoauth-2.0asp.net-core-webapiazure-ad-b2c

解决方案


谢谢你们的回复。这是我为其他处理此问题的人所做的。向@juunas 大喊他发送的链接,这让我走上了正确的道路。该特定解决方案还不够,因为我使用 Azure AD B2C 库进行授权/身份验证。

这是我找到的链接,一旦我尝试从@juunas 实施解决方案: https ://blog.denious.net/azure-b2c-role-based-authorization-part-1/

根据我在该链接中发现的内容,我的解决方案最终看起来像这样:

//Azure ADB2C is injected for authentication
        services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
            .AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options));

        services.PostConfigure<JwtBearerOptions>(
            AzureADB2CDefaults.JwtBearerAuthenticationScheme,
            o =>
            {
                o.Events = new JwtBearerEvents
                {
                    OnTokenValidated = ctx =>
                    {
                        //Get user's immutable object id from claims that came from Azure AD
                        string oid = ctx.Principal
                            .FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");

                        //Get My Data EF context
                        var db = ctx.HttpContext.RequestServices.GetRequiredService<MyDataContext>();

                        //Grab the user - found in My Accounts table, tied to OID
                        var user = db.Accounts.Include("AccountType")
                            .Where(a => a.AuthorityId == oid)
                            .FirstOrDefault();

                        if (user != null)
                        {
                            // since we're using AADB2C only, the first identity is the only identity
                            var identity = ctx.Principal.Identities.First();

                            //Place My user type into the claims as a role claim type
                            var extraRoleClaim = new Claim(identity.RoleClaimType, user.AccountType);
                            identity.AddClaim(extraRoleClaim);
                        }

                        return Task.CompletedTask;
                    }
                };
            });

设置完成后,我就可以在端点内部执行此操作:

if (User.IsInRole("Some Role"))
            {
                return Ok();
            }
            else
            {
                return StatusCode(403, "Forbidden - Unacceptable Role");
            }

从链接中注意,我还可以在我的授权属性中对控制器或操作执行以下操作:[Authorize(Roles = "Some Role")]


推荐阅读