简体   繁体   English

正确的 Core 3.0 API 中间件将 Azure AD B2C 用户连接到我的数据库帐户?

[英]Proper Core 3.0 API middleware to connect Azure AD B2C user to my database account?

I have a.Net Core 3 API that properly authorizes and authenticates the tokens passed to it via Azure AD B2C.我有一个.Net Core 3 API,它可以正确授权和验证通过 Azure AD B2C 传递给它的令牌。 It also has a little bit of custom code built to check the scopes passed in the JWT token to confirm access to endpoints.它还构建了一些自定义代码,用于检查 JWT 令牌中传递的范围,以确认对端点的访问。 (I'm using the Microsoft.AspNetCore.Authentication.AzureADB2C.UI package) Here's the block of middleware that makes this possible: (我正在使用 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)));
     });

This all seems to be working to gaining access to endpoints properly.这一切似乎都在努力正确地访问端点。 These endpoints then expose various information from my SQL database in a model.然后,这些端点会在 model 中公开来自我的 SQL 数据库的各种信息。

However, now I'm trying to bring home the other aspect of my security, by controlling access to particular parts of the data retrieved in these endpoints, based on who the JWT token is actually tied to in my database.但是,现在我试图通过控制对在这些端点中检索到的数据的特定部分的访问,根据 JWT 令牌在我的数据库中实际与谁相关联,将我的安全性的另一个方面带回家。

In my particular case, I have an Accounts table, where I can store the ObjectID from Azure AD B2C that's found in the JWT token and then obtain the Account using that ObjectID at the time of calling.在我的特殊情况下,我有一个 Accounts 表,我可以在其中存储来自 JWT 令牌中的 Azure AD B2C 的 ObjectID,然后在调用时使用该 ObjectID 获取帐户。 I could just do this at the top of an endpoint, but I suspect that this is not the best way to do it.可以在端点的顶部执行此操作,但我怀疑这不是最好的方法。 It seems like I should be building this at the middleware layer in Startup as some kind of handler.看来我应该在 Startup 的中间件层构建它作为某种处理程序。

Can someone confirm for me that this would be the right approach and possibly give me an example of this or at least point me in the right direction?有人可以为我确认这将是正确的方法,并可能给我一个例子,或者至少为我指明正确的方向吗?

Thanks guys for your responses.谢谢你们的回复。 Here's what I landed on for anyone else dealing with this.这是我为其他处理此问题的人所做的。 Shout out to @juunas for his link he sent, which is what started me on the right path.向@juunas 大喊他发送的链接,这让我走上了正确的道路。 That particular solution was not enough because I am using the Azure AD B2C libraries for the authorization/authentication.该特定解决方案还不够,因为我正在使用 Azure AD B2C 库进行授权/身份验证。

Here is the link I found, once I tried implementing the solution from @juunas: https://blog.denious.net/azure-b2c-role-based-authorization-part-1/这是我找到的链接,一旦我尝试从@juunas 实施解决方案: https://blog.denious.net/azure-b2c-role-based-authorization-part-1/

Based on what I discovered in that link, here is what my solution ended up looking like:根据我在该链接中发现的内容,我的解决方案最终看起来像这样:

//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;
                    }
                };
            });

Once that was setup, I was able to do this inside of my endpoint:设置完成后,我就可以在端点内部执行此操作:

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

Note from the link, that I also would be able to do the following within my Authorize attribule on a controller or action: [Authorize(Roles = "Some Role")]请注意链接中的内容,我还可以在 controller 或操作的 Authorize 属性中执行以下操作:[Authorize(Roles = "Some Role")]

Basically you will need to add a custom attribute and include it in the JWT.基本上,您需要添加一个自定义属性并将其包含在 JWT 中。

as described in here also you might need to keep the attributes in sync using graph API by using this Sample如此处所述,您可能还需要使用示例使用图形 API使属性保持同步

I'm struggling a bit with the example as the config in application.json is missing, and google search is a bit confusing due to changes between the .net core versions.作为 application.json 中的配置的示例,我有点挣扎,由于 .net 核心版本之间的变化,谷歌搜索有点混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM