You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Azure Active Directory应用角色显示在Claims中?(Umbraco 11)

解决Umbraco 11 Azure AD应用角色映射到用户组问题

核心问题分析

你当前使用MicrosoftAccount认证方案适配Azure AD,该方案主要面向个人微软账户,无法正确获取Azure AD自定义应用角色(roles声明)。需切换为OpenIdConnect方案,并配置正确的声明映射与权限范围,才能在authorization_code流程中获取到角色信息。

步骤1:替换认证方案为OpenIdConnect

修改UmbracoBuilderExtensions中的认证配置,将AddMicrosoftAccount替换为AddOpenIdConnect,并配置Azure AD专属参数:

namespace Example.Api.Features.Authentication.Extensions;

public static class UmbracoBuilderExtensions
{
    public static IUmbracoBuilder ConfigureAuthentication(this IUmbracoBuilder builder)
    {
        builder.Services.ConfigureOptions<OpenIdConnectBackOfficeExternalLoginProviderOptions>();

        builder.AddBackOfficeExternalLogins(logins =>
        {
            const string schema = OpenIdConnectDefaults.AuthenticationScheme;
                
            logins.AddBackOfficeLogin(
                backOfficeAuthenticationBuilder =>
                {
                    backOfficeAuthenticationBuilder.AddOpenIdConnect(
                        backOfficeAuthenticationBuilder.SchemeForBackOffice(OpenIdConnectBackOfficeExternalLoginProviderOptions.SchemeName) ?? string.Empty,
                        options =>
                        {
                            options.CallbackPath = "/umbraco-signin-microsoft/";
                            options.ClientId = "CLIENT_ID";
                            options.ClientSecret = "CLIENT_SECRET";
                            // 设置Azure AD租户权威地址
                            options.Authority = "https://login.microsoftonline.com/TENANT/v2.0";
                            // 必须包含roles scope以获取应用角色声明
                            options.Scope.Add("roles");
                            options.Scope.Add("openid");
                            options.Scope.Add("profile");
                            options.Scope.Add("email");

                            // 映射roles声明,确保不被默认过滤
                            options.ClaimActions.MapJsonKey("roles", "roles");
                            options.TokenValidationParameters = new TokenValidationParameters
                            {
                                NameClaimType = "name",
                                RoleClaimType = "roles"
                            };

                            // 启用授权码流程
                            options.ResponseType = OpenIdConnectResponseType.Code;
                        });
                });
        });

        return builder;
    }
}

步骤2:在自动关联回调中映射角色到Umbraco用户组

修改OpenIdConnectBackOfficeExternalLoginProviderOptions中的OnAutoLinking和OnExternalLogin方法,读取roles声明并同步到Umbraco用户组:

namespace Example.Api.Features.Configuration;

public class OpenIdConnectBackOfficeExternalLoginProviderOptions : IConfigureNamedOptions<BackOfficeExternalLoginProviderOptions>
{
    public const string SchemeName = "OpenIdConnect";

    public void Configure(string name, BackOfficeExternalLoginProviderOptions options)
    {
        if (name != "Umbraco." + SchemeName)
        {
            return;
        }

        Configure(options);
    }

    public void Configure(BackOfficeExternalLoginProviderOptions options)
    {
        options.AutoLinkOptions = new ExternalSignInAutoLinkOptions(
            autoLinkExternalAccount: true,
            defaultUserGroups: Array.Empty<string>(), // 不再使用默认组,完全由Azure角色控制
            allowManualLinking: false
        )
        {
            OnAutoLinking = (autoLinkUser, loginInfo) =>
            {
                autoLinkUser.IsApproved = true;
                // 清空默认组,根据Azure角色分配Umbraco组
                autoLinkUser.UserGroups.Clear();
                var azureRoles = loginInfo.Principal.Claims
                    .Where(c => c.Type == "roles")
                    .Select(c => c.Value);

                foreach (var role in azureRoles)
                {
                    switch (role)
                    {
                        case "Administrator":
                            autoLinkUser.UserGroups.Add(Constants.Security.AdminGroupAlias);
                            break;
                        case "Editor":
                            autoLinkUser.UserGroups.Add(Constants.Security.EditorGroupAlias);
                            break;
                        // 可添加更多角色映射
                    }
                }
            },
            OnExternalLogin = (user, loginInfo) =>
            {
                // 每次登录同步角色
                user.UserGroups.Clear();
                var azureRoles = loginInfo.Principal.Claims
                    .Where(c => c.Type == "roles")
                    .Select(c => c.Value);

                foreach (var role in azureRoles)
                {
                    switch (role)
                    {
                        case "Administrator":
                            user.UserGroups.Add(Constants.Security.AdminGroupAlias);
                            break;
                        case "Editor":
                            user.UserGroups.Add(Constants.Security.EditorGroupAlias);
                            break;
                    }
                }
                return true;
            }
        };

        options.DenyLocalLogin = true;
        options.AutoRedirectLoginToExternalProvider = true;
    }
}

步骤3:Azure端配置验证

  1. 应用注册Manifest检查:确保appRoles的allowedMemberTypes包含"User",示例:
    "appRoles": [
        {
            "allowedMemberTypes": ["User"],
            "description": "Umbraco管理员",
            "displayName": "Administrator",
            "id": "你的角色ID",
            "isEnabled": true,
            "value": "Administrator"
        }
    ]
    
  2. API权限配置:在应用注册的「API权限」中添加自身应用的权限(选择「我的API」→ 勾选roles权限),并点击「授予管理员同意」。
  3. 企业应用角色分配:确认已在企业应用中将角色分配给对应用户。

验证方式

登录Umbraco后台后,解码ID Token(可使用JWT解码工具),确认roles字段已包含分配的应用角色;同时检查Umbraco用户的组是否与Azure角色匹配。

内容的提问来源于stack exchange,提问作者0Neji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 09:45:28