Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Identity Server 4:向访问令牌添加声明_C#_Jwt_Identityserver4_Openid Connect_Thinktecture Ident Server - Fatal编程技术网

C# Identity Server 4:向访问令牌添加声明

C# Identity Server 4:向访问令牌添加声明,c#,jwt,identityserver4,openid-connect,thinktecture-ident-server,C#,Jwt,Identityserver4,Openid Connect,Thinktecture Ident Server,我正在使用Identity Server 4和隐式流,并希望向访问令牌添加一些声明,新声明或属性为“tenantId”和“langId” 我已经添加了langId作为我的作用域之一,如下所示,然后通过identity server请求它,但我也得到了租户ID。这怎么会发生 这是作用域和客户端配置的列表: public IEnumerable<Scope> GetScopes() { return new List<Scope>

我正在使用Identity Server 4和隐式流,并希望向访问令牌添加一些声明,新声明或属性为“tenantId”和“langId”

我已经添加了langId作为我的作用域之一,如下所示,然后通过identity server请求它,但我也得到了租户ID。这怎么会发生

这是作用域和客户端配置的列表:

  public IEnumerable<Scope> GetScopes()
    {
        return new List<Scope>
        {
             // standard OpenID Connect scopes
            StandardScopes.OpenId,
            StandardScopes.ProfileAlwaysInclude,
            StandardScopes.EmailAlwaysInclude,

            new Scope
            {
                Name="langId",
                 Description = "Language",
                Type= ScopeType.Resource,
                Claims = new List<ScopeClaim>()
                {
                    new ScopeClaim("langId", true)
                }
            },
            new Scope
            {
                Name = "resourceAPIs",
                Description = "Resource APIs",
                Type= ScopeType.Resource
            },
            new Scope
            {
                Name = "security_api",
                Description = "Security APIs",
                Type= ScopeType.Resource
            },
        };
    }
解码访问令牌:

 {
  "nbf": 1483043742,
  "exp": 1483047342,
  "iss": "http://localhost:44312",
  "aud": "http://localhost:44312/resources",
  "client_id": "angular2client",
  "sub": "1",
  "auth_time": 1483043588,
  "idp": "local",
  "langId": "en",
  "tenantId": "123",
  "scope": [
    "resourceAPIs",     
    "security_api",
    "langId",
    "openid"
  ],
  "amr": [
    "pwd"
  ]
}

您应该检查并过滤掉未请求的声明。

此答案是为.Net core 2上的IdentityServer 4编写的。若要将其用于.Net core 3,此答案可能会对您有所帮助,但您需要测试和更改一些内容。
我正在使用asp.net Identity and Entity Framework和IdentityServer 4

这是我的示例代码,运行良好,JWT包含所有角色和声明

您可以在这里看到如何使用ASP.Net核心标识实现Identityserver4

1-identity server startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.AddMvc();

            services.AddTransient<IEmailSender, AuthMessageSender>();
            services.AddTransient<ISmsSender, AuthMessageSender>();

            //Add IdentityServer services
            //var certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "LocalhostCert.pfx"), "123456");
            services.AddIdentityServer()
                    .AddTemporarySigningCredential()
                    .AddInMemoryIdentityResources(Configs.IdentityServerConfig.GetIdentityResources())
                    .AddInMemoryApiResources(Configs.IdentityServerConfig.GetApiResources())
                    .AddInMemoryClients(Configs.IdentityServerConfig.GetClients())
                    .AddAspNetIdentity<ApplicationUser>()
                    .AddProfileService<Configs.IdentityProfileService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
                //app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseIdentity();

            // Adds IdentityServer
            app.UseIdentityServer();

            // Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Account}/{action=Login}/{id?}");
            });

        }
6-在我的API中,我添加了这个nuget包

.IdentityServer4.AccessTokenValidatio

我的startup.cs是这样的

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            //IdentityServer4.AccessTokenValidation
            app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
            {
                Authority = "http://localhost:5000",
                RequireHttpsMetadata = false,
                ApiName = "ApplicationApi"
            });

            app.UseMvc();
        }
现在我可以在客户端web应用程序和API应用程序中使用[Authorize(Role=“SuperAdmin,Admin”)]

User.IsInRole("Admin")
我也有权获得索赔

HttpContext.User.Claims 

var q = (from p in HttpContext.User.Claims where p.Type == "role" select p.Value).ToList();

var q2 = (from p in HttpContext.User.Claims where p.Type == "sub" select p.Value).First();

经过一些严格的研究,我想提供我自己的答案:

在登录过程中,服务器将发出一个身份验证cookie,其中包含用户的一些声明

然后,客户端将在从cookie提供声明的同时请求访问令牌,配置文件服务将使用cookie声明生成访问令牌声明

接下来,客户端将请求一个id令牌,但这次它将使用来自访问令牌的声明

现在的问题是,identity server的默认配置文件服务仅通过使用access令牌中的声明来填充id令牌的声明,而ASP.Net identity的默认配置文件服务则从数据库存储中查找所有用户声明。这是一个令人困惑的问题

对于identity server实现,哪些声明最终会出现在访问令牌中?与作为API资源的作用域关联的声明,与id令牌中的声明相反,id令牌中的声明与作为标识资源的作用域关联

摘要

没有ASP.NET标识:

  • 登录-identity server发布一个带有一些声明的cookie
  • 访问令牌查询-identity server根据请求的api作用域从cookie添加声明
  • Id令牌查询-identity server根据请求的标识作用域从访问令牌添加声明
  • 使用ASP.NET标识:

  • 登录-identity server发布一个带有一些声明的cookie
  • 访问令牌查询-identity server根据请求的api作用域从cookie添加声明
  • Id令牌查询-identity server根据请求的标识作用域从访问令牌和用户存储中添加声明

  • 你是对的,我应该这样做,但这不是我的问题,因为如果我没有在上面的请求url中请求
    langId
    范围。返回的访问令牌既不包含
    langId
    也不包含
    tenantId
    (因此这里的过滤不是问题)。这就是我需要理解的,为什么在请求问题中的
    langId
    时,访问令牌中包含租户ID。这是因为其他资源作用域没有分配任何声明,所以当您删除langId作用域时,此条件不会触发。这是什么版本的IdentityServer 4?“IdentityServer 4”:“1.0.0-rc1-update2“,您有没有可能为IS4 1.0最终版或1.2版更新此版本?还没有,为什么?有什么问题吗?有关访问令牌,请检查您的ApiResource的UserClaims。资料来源:干杯,垃圾桶。我不爱很多人,但你用这个答案让我的船漂浮。避免了身份声明的痛苦。我正在
    IdentityProfileService
    中添加一个声明,它位于令牌中,您知道如何仅在特定客户端而不是在所有客户端中添加吗?。这是声明
    //添加更多类似的声明//声明.Add(new System.Security.claims.claims(“Balance”,user.Balance.ToString())您好,William,是的,如果您不想添加声明或客户端声明,可以检查“context.client.ClientId”。我用它来查找我的租户,并在JWS中添加租户。@Mirak`GitHub上没有这些代码吗?或者有办法共享这些代码吗?我正在尝试在Identity Server 4中扮演角色,我有点迷路了,这将有助于我了解您的代码easier@AlexandraDamaschin不,我们有自己的私人TFS。我在很久以前就更改了这段代码,因为我们需要支持多租户,我们希望从数据库中读取Identity Server设置,并且我们从Core1.0迁移到了2.0.1。这段代码是我第一次研发Identity Server。
    
    using IdentityServer4;
        using IdentityServer4.Models;
        using System.Collections.Generic;
    
        namespace IdentityAuthority.Configs
        {
    
            public class IdentityServerConfig
            {
    
                // scopes define the resources in your system
                public static IEnumerable<IdentityResource> GetIdentityResources()
                {
                    return new List<IdentityResource>
                    {
                        new IdentityResources.OpenId(),
                        new IdentityResources.Profile()
                    };
                }
    
                // scopes define the API resources
                public static IEnumerable<ApiResource> GetApiResources()
                {
                    //Create api resource list
                    List<ApiResource> apiResources = new List<ApiResource>();
    
                    //Add Application Api API resource
                    ApiResource applicationApi = new ApiResource("ApplicationApi", "Application Api");
                    applicationApi.Description = "Application Api resource.";
                    apiResources.Add(applicationApi);
    
                    //Add Application Api API resource
                    ApiResource definitionApi = new ApiResource("DefinitionApi", "Definition Api");
                    definitionApi.Description = "Definition Api.";
                    apiResources.Add(definitionApi);
    
                    //Add FF API resource
                    ApiResource ffApi = new ApiResource("FFAPI", "Fule .netfx API");
                    ffApi.Description = "Test using .net 4.5 API application with IdentityServer3.AccessTokenValidation";
                    apiResources.Add(ffApi);
    
                    return apiResources;
                }
    
                // client want to access resources (aka scopes)
                public static IEnumerable<Client> GetClients()
                {
                    //Create clients list like webui, console applications and...
                    List<Client> clients = new List<Client>();
    
                    //Add WebUI client
                    Client webUi = new Client();
                    webUi.ClientId = "U2EQlBHfcbuxUo";
                    webUi.ClientSecrets.Add(new Secret("TbXuRy7SSF5wzH".Sha256()));
                    webUi.ClientName = "WebUI";
                    webUi.AllowedGrantTypes = GrantTypes.HybridAndClientCredentials;
                    webUi.RequireConsent = false;
                    webUi.AllowOfflineAccess = true;
                    webUi.AlwaysSendClientClaims = true;
                    webUi.AlwaysIncludeUserClaimsInIdToken = true;
                    webUi.AllowedScopes.Add(IdentityServerConstants.StandardScopes.OpenId);
                    webUi.AllowedScopes.Add(IdentityServerConstants.StandardScopes.Profile);
                    webUi.AllowedScopes.Add("ApplicationApi");
                    webUi.AllowedScopes.Add("DefinitionApi");
                    webUi.AllowedScopes.Add("FFAPI");
                    webUi.ClientUri = "http://localhost:5003";
                    webUi.RedirectUris.Add("http://localhost:5003/signin-oidc");
                    webUi.PostLogoutRedirectUris.Add("http://localhost:5003/signout-callback-oidc");
                    clients.Add(webUi);
    
                    //Add IIS test client
                    Client iisClient = new Client();
                    iisClient.ClientId = "b8zIsVfAl5hqZ3";
                    iisClient.ClientSecrets.Add(new Secret("J0MchGJC8RzY7J".Sha256()));
                    iisClient.ClientName = "IisClient";
                    iisClient.AllowedGrantTypes = GrantTypes.HybridAndClientCredentials;
                    iisClient.RequireConsent = false;
                    iisClient.AllowOfflineAccess = true;
                    iisClient.AlwaysSendClientClaims = true;
                    iisClient.AlwaysIncludeUserClaimsInIdToken = true;
                    iisClient.AllowedScopes.Add(IdentityServerConstants.StandardScopes.OpenId);
                    iisClient.AllowedScopes.Add(IdentityServerConstants.StandardScopes.Profile);
                    iisClient.AllowedScopes.Add("ApplicationApi");
                    iisClient.AllowedScopes.Add("DefinitionApi");
                    iisClient.AllowedScopes.Add("FFAPI");
                    iisClient.ClientUri = "http://localhost:8080";
                    iisClient.RedirectUris.Add("http://localhost:8080/signin-oidc");
                    iisClient.PostLogoutRedirectUris.Add("http://localhost:8080/signout-callback-oidc");
                    clients.Add(iisClient);
    
                    return clients;
                }
    
            }
        }
    
    using IdentityServer4.Services;
    using System;
    using System.Threading.Tasks;
    using IdentityServer4.Models;
    using IdentityAuthority.Models;
    using Microsoft.AspNetCore.Identity;
    using IdentityServer4.Extensions;
    using System.Linq;
    
    namespace IdentityAuthority.Configs
    {
        public class IdentityProfileService : IProfileService
        {
    
            private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
            private readonly UserManager<ApplicationUser> _userManager;
    
            public IdentityProfileService(IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, UserManager<ApplicationUser> userManager)
            {
                _claimsFactory = claimsFactory;
                _userManager = userManager;
            }
    
            public async Task GetProfileDataAsync(ProfileDataRequestContext context)
            {
                var sub = context.Subject.GetSubjectId();
                var user = await _userManager.FindByIdAsync(sub);
                if (user == null)
                {
                    throw new ArgumentException("");
                }
    
                var principal = await _claimsFactory.CreateAsync(user);
                var claims = principal.Claims.ToList();
    
                //Add more claims like this
                //claims.Add(new System.Security.Claims.Claim("MyProfileID", user.Id));
    
                context.IssuedClaims = claims;
            }
    
            public async Task IsActiveAsync(IsActiveContext context)
            {
                var sub = context.Subject.GetSubjectId();
                var user = await _userManager.FindByIdAsync(sub);
                context.IsActive = user != null;
            }
        }
    
    }
    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
            {
    
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                loggerFactory.AddDebug();
    
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    //app.UseBrowserLink();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                }
    
                app.UseStaticFiles();
    
                //Setup OpenId and Identity server
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationScheme = "Cookies",
                    AutomaticAuthenticate = true
                });
    
                app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
                {
                    Authority = "http://localhost:5000",
                    ClientId = "U2EQlBHfcbuxUo",
                    ClientSecret = "TbXuRy7SSF5wzH",
                    AuthenticationScheme = "oidc",
                    SignInScheme = "Cookies",
                    SaveTokens = true,
                    RequireHttpsMetadata = false,
                    GetClaimsFromUserInfoEndpoint = true,
                    ResponseType = "code id_token",
                    Scope = { "ApplicationApi", "DefinitionApi", "FFAPI", "openid", "profile", "offline_access" },
                    TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        NameClaimType = "name",
                        RoleClaimType = "role"
                    }
                });
    
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
                });
            }
    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
            {
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                loggerFactory.AddDebug();
    
                //IdentityServer4.AccessTokenValidation
                app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
                {
                    Authority = "http://localhost:5000",
                    RequireHttpsMetadata = false,
                    ApiName = "ApplicationApi"
                });
    
                app.UseMvc();
            }
    
    User.IsInRole("Admin")
    
    HttpContext.User.Claims 
    
    var q = (from p in HttpContext.User.Claims where p.Type == "role" select p.Value).ToList();
    
    var q2 = (from p in HttpContext.User.Claims where p.Type == "sub" select p.Value).First();