azure - 从浏览器应用程序联系我的 ASP.NET Core 3.1 API 时,无法在访问 token 中看到角色声明

标签 azure asp.net-core azure-active-directory authorization auth0

浏览器应用

我有一个浏览器应用(CRA、TypeScript),在成功通过 Azure AD 身份验证后,它会向我的 API 发出请求:

public async acquireAccessToken(): Promise<string | undefined> {
    let res: AuthResponse | undefined = undefined;
    const params: AuthenticationParameters = {
        scopes: ["Users.Read"],
    };

    try {
        res = await this.msal.acquireTokenSilent(params);
    } catch (error) {
        res = await this.msal.acquireTokenPopup(params);
    }

    return !res || !res.accessToken ? undefined : res.accessToken;
}

前面是一个实用方法,用于获取访问 token 以联系 API,实际调用如下:

const token = await acquireAccessToken();
const res = await fetch("/controller/test", {
    method: "GET",
    headers: {
        "Authorization": `Bearer ${token}`
    },
});

console.log(res.text());

其中 msal 是我用作客户端来处理浏览器应用程序中的身份验证和授权的 UserAgentApplication

我在 Azure 中正确设置了所有内容,其中一个注册应用程序用于代表浏览器应用程序,另一个注册应用程序用于描述我需要联系的 API。

API

API 服务器是一个 ASP.NET Core 3.1 C# 应用程序,其 Startup.cs 为:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseAuthentication();
        app.UseAuthorization();
    }
}

我删除了所有额外的代码并保留了与身份验证相关的部分。

我正在联系的控制者是:

[ApiController]
[Route("controller")]
public class MyController : ControllerBase
{
    [HttpGet("test/")]
    [Authorize(Roles = "Admin")]
    public async Task<string> Test()
    {
        return "Ok";
    }

    [HttpGet("test2/")]
    [Authorize]
    public async Task<string> Test2()
    {
        return "Ok";
    }

    [HttpGet("test3/")]
    public async Task<string> Test3()
    {
        return "Ok";
    }
}

azure

Azure 中的设置很简单:除了浏览器应用程序和 API 的两个应用程序注册之外,我还在浏览器应用程序注册中设置了一些自定义角色并将其分配给一些用户。

I authenticate in the browser app using a user who has the Admin app role assigned to it.

<小时/>

问题

当我的客户端应用程序尝试使用这些端点获取数据时:

  • /controller/test3
  • /controller/test2

一切都很好,因为一个不 protected ,另一个使用简单的[Authorize]

但是,当尝试从 /controller/test 获取数据时,我收到 403 (Forbidden)

为什么我无法让角色发挥作用?

<小时/>

更多信息

在获取 test2 时进行调试时,我可以在 Controller 中看到 this.User 存在,并且存在多个声明。在这些说法中,我看不到任何与这个角色有关的内容。我获得的访问 token 具有以下形式:

{
  "aud": "api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "iss": "https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/",
  "iat": 1607034050,
  "nbf": 1607034050,
  "exp": 1607037950,
  "acr": "1",
  "aio": "AWQAm/8RAAAAH1j5tZzINJFi5fsMsgf99gcrnqQA+dOhWBpFmsgy3jsr0pFJ0AxvenqthiNLmRqKzqx6l+9SuLlRniAVCTOoqEE7MonnOetO3h7g1/Bm520rS0qiX/gpCCWYm/UwDlJ+",
  "amr": [
    "pwd"
  ],
  "appid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "appidacr": "0",
  "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="255d5d5d655d5d5d0b5d5d5d" rel="noreferrer noopener nofollow">[email protected]</a>",
  "idp": "https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/",
  "ipaddr": "xxx.xxx.xxx.xxx",
  "name": "XXX",
  "oid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "rh": "0.AAAASupzDdEU8EyBI3R6nFeJQHVORvhJZ2hDjJoEO5yPUcZ0AEU.",
  "scp": "Users.Read",
  "sub": "frR45l2dTAIyXZ-3Yn2mGNbBcBX9CrGisgJ4L8zOCd4",
  "tid": "0d73ea4a-14d1-4cf0-8123-747a9c578940",
  "unique_name": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b2cacacaf2cacaca9ccacaca" rel="noreferrer noopener nofollow">[email protected]</a>",
  "uti": "39dk-rAAP0KiJN5dwhs4AA",
  "ver": "1.0"
}

如您所见,没有与角色相关的声明。

但请注意,我可以成功获取身份验证时获得的用户 token 中的角色。当我使用访问 token 联系 API 时,我也需要该声明流入访问 token 。怎么办?

最佳答案

我发现了你的问题:

您无法在浏览器应用程序的 list 中设置自定义角色。您需要在 api 应用程序的 list 中设置自定义角色,然后将该角色分配给用户。

那么你需要使用 auth code flow获取访问 token ,roles 声明将包含在其中。

<小时/>

事实上,访问 token 是根据 token 的预期接收者(即您的 API)创建的。如果您想访问 api,您必须拥有权限或角色。在你的问题中,这个角色是你自定义的,当你授予用户一个api应用程序的自定义角色时,那么该用户就拥有了可以访问api应用程序的角色。 (注意,这里并不是把客户端应用程序的自定义角色分配给用户,因为需要访问api应用程序,所以需要api应用程序的角色),然后用户就可以登录客户端应用程序并请求来自 api 应用程序的 token 。当您获取token并使用token访问API时,API只需验证您登录的用户是否具有访问的角色即可。

关于azure - 从浏览器应用程序联系我的 ASP.NET Core 3.1 API 时,无法在访问 token 中看到角色声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65135500/

相关文章:

azure - 使用 DevOps 将 .Net Core 部署到 Azure 上的 Linux WebApps

asp.net-core - 我们可以将 Mvc 应用程序开发的 .Net 框架转换为 Mvc Asp.Net Core 2.0 而无需更改代码或更改最少的代码

azure - 访问 Azure AD Graph API 时出现 "Access Token missing or malformed"错误

sql - 使用 Azure ARM 模板导入数据库

azure - 关于azure存储中的私有(private)容器

c# - 如何使用集群内反向代理自动确定在 Kubernetes 中运行的 ASP.NET Core 应用程序的 KnownNetworks?

azure-active-directory - Azure Active Directory B2C AADB2C90051 : No suitable claims providers were found

azure-active-directory - 如何使用 Microsoft Graph API 将成员添加到组

postgresql - Azure 上 Postgresql 数据库的 Azure_superuser 帐户密码

node.js - 如何在特定阶段将数据从 azure cosmos db 备份到 azure blob?