使用Identity Server 4将Windows / Active Directory组作为角色声明

时间:2018-01-16 08:47:13

标签: asp.net-core-2.0 identityserver4

我根据GitHub上的UI示例项目说明设置了基本的Identity Server。我已将其设置为使用我们的现场AD进行Windows身份验证。这很漂亮。

我的问题是将用户AD组添加到声明中。根据示例项目,我启用了IncludeWindowsGroups选项。这似乎是将声明添加到ClaimsIdentity。但是,在我的MVC客户端上,当我打印出声明时,我只会得到相同的结果4.它们是sidsubidpname。我已经尝试添加其他声明,但我永远不会让任何其他人出现。

我有以下作为我的客户端设置:

return new List<Client>
        {
            // other clients omitted...

            // OpenID Connect implicit flow client (MVC)
            new Client
            {
                ClientId = "mvc",
                ClientName = "MVC Client",
                AllowedGrantTypes = GrantTypes.Implicit,

                // where to redirect to after login
                RedirectUris = { "http://localhost:5002/signin-oidc" },

                // where to redirect to after logout
                PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

                AllowedScopes = new List<string>
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile
                },

                RequireConsent = false
            }
        };

希望我只是缺少一些简单的东西,但我现在正在努力寻找想法,所以任何指针都会非常感激。

1 个答案:

答案 0 :(得分:2)

除了在IdentityServer4项目中设置IncludeWindowsGroups = true之外,我还设法进行了一些更改。请注意,我从2.2.0 tag

开始下载了IdentityServer4 UI快速入门。

在GitHub中,每个this comment都在快速入门用户界面中修改了ExternalController.cs:

// this allows us to collect any additonal claims or properties
// for the specific prtotocols used and store them in the local auth cookie.
// this is typically used to store data needed for signout from those protocols.
var additionalLocalClaims = new List<Claim>();

var roleClaims = claims.Where(c => c.Type == JwtClaimTypes.Role).ToList();
if (roleClaims.Count > 0)
{
    additionalLocalClaims.AddRange(roleClaims);
}

然后我创建了一个配置文件服务,将Windows Auth中的声明复制到要发送回的令牌中:

public class ProfileService : IProfileService
{
    private readonly string[] _claimTypesToMap = {"name", "role"};

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        foreach (var claimType in _claimTypesToMap)
        {
            var claims = context.Subject.Claims.Where(c => c.Type == claimType);
            context.IssuedClaims.AddRange(claims);
        }

        return Task.CompletedTask;
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        context.IsActive = true; //use some sort of actual validation here!
        return Task.CompletedTask;
    }
}

并在Startup.cs中向IdentityServer4注册

 services
    .AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryIdentityResources(StaticConfig.GetIdentityResources())
    .AddInMemoryApiResources(StaticConfig.GetApiResources())
    .AddInMemoryClients(StaticConfig.GetClients())
    .AddTestUsers(StaticConfig.GetUsers())
    .AddProfileService<ProfileService>();

在IdentityServer4的客户端配置中,我将用户声明设置为包含在ID令牌中。我发现,如果我尝试将回调中的声明映射到UserInfo,该上下文将在IdentityServer4中丢失,因此声明将不会映射。

public static class StaticConfig
{
    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
              ...
              AlwaysIncludeUserClaimsInIdToken = true,
              ...
            }
         }
    }
}

最后,在客户端网站的Startup.cs中,我设置了UserInfo回调;我只是确保映射了我的姓名和角色声明。请注意,如果您的个人资料服务返回了任何其他声明类型,则需要通过调用options.ClaimActions上的辅助方法来手动映射它们。

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
    options.SignInScheme = "Cookies";

    options.Authority = "http://localhost:5000";
    options.RequireHttpsMetadata = false;

    options.ClientId = "mvc";
    options.ClientSecret = "secret";
    options.SaveTokens = true;

    options.ResponseType = "code id_token";

    options.TokenValidationParameters = new TokenValidationParameters
    {
        NameClaimType = "name",
        RoleClaimType = "role"
    };

    //map any other app-specific claims we're getting from IdentityServer
    options.ClaimActions.MapUniqueJsonKey("someotherclaimname", "someotherclaimname");
};