6

我正在使用Identity Server 4和Implicit Flow,並且希望爲訪問令牌添加一些聲明,新聲明或屬性爲「tenantId」和「langId」。Identity Server 4:添加聲明以訪問令牌

我已經添加了langId作爲我的範圍之一,然後通過身份服務器請求,但我也得到tenantId。這怎麼會發生?

此範圍和客戶端配置的列表:

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 
      }, 
     }; 
    } 

客戶:

return new List<Client> 
     { 
      new Client 
      { 
       ClientName = "angular2client", 
       ClientId = "angular2client", 
       AccessTokenType = AccessTokenType.Jwt, 
       AllowedGrantTypes = GrantTypes.Implicit, 
       AllowAccessTokensViaBrowser = true, 
       RedirectUris = new List<string>(redirectUris.Split(',')), 
       PostLogoutRedirectUris = new List<string>(postLogoutRedirectUris.Split(',')), 
       AllowedCorsOrigins = new List<string>(allowedCorsOrigins.Split(',')), 

       AllowedScopes = new List<string> 
       { 
        "openid", 
        "resourceAPIs", 
        "security_api",   
        "role", 
        "langId" 
       } 
      } 
     }; 

我加入的ProfileService索賠:

public class ProfileService : IdentityServer4.Services.IProfileService 
{ 
    private readonly SecurityCore.ServiceContracts.IUserService _userService; 


    public ProfileService(SecurityCore.ServiceContracts.IUserService userService) 
    { 
     _userService = userService; 
    } 

    public Task GetProfileDataAsync(ProfileDataRequestContext context) 
    { 
     //hardcoded them just for testing purposes 
     List<Claim> claims = new List<Claim>() { new Claim("langId", "en"), new Claim("tenantId", "123") }; 

     context.IssuedClaims = claims; 


     return Task.FromResult(0); 
    } 

這是什麼我正在請求獲得令牌,問題在於我Ÿ請求LANGID,但我得到兩個tenantId訪問令牌LANGID

http://localhost:44312/account/login?returnUrl=%2Fconnect%2Fauthorize%2Flogin%3Fresponse_type%3Did_token%2520token%26client_id%3Dangular2client%26redirect_uri%3Dhttp%253A%252F%252Flocalhost:5002%26scope%3DresourceAPIs%2520notifications_api%2520security_api%2520langId%2520navigation_api%2520openid%26nonce%3DN0.73617935552798141482424408851%26state%3D14824244088510.41368537145696305%26 

解碼訪問令牌:

{ 
    "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" 
    ] 
} 
+0

什麼版本IdentityServer4的這是什麼? – Rafe

+0

「IdentityServer4」:「1.0.0-rc1-update2」, – Coding

+0

你有沒有更新過IS4 1.0 final或version 1.2的機會? – Rafe

回答

5

你應該檢查context.RequestedClaimTypes和fi消除索賠,這是沒有要求。

+0

你是對的,我應該這樣做,但這不是我的問題,因爲如果我沒有請求'langId'範圍在上面的請求url中。返回的訪問令牌既不包含'langId'也不包含'tenantId'(所以這裏的過濾不是問題)。這就是我需要理解的,爲什麼當在問題中請求'langId'時,tenantId被包含在訪問令牌中。 – Coding

+1

這是因爲其他資源範圍沒有任何索賠分配給他們,所以當你刪除langId範圍這個https://github.com/IdentityServer/IdentityServer4/blob/dev/src/IdentityServer4/Services/DefaultClaimsService.cs# L183的狀況沒有發射。 –

16

我正在使用Identityserver身份和實體框架Identityserver4。

這是我的示例代碼,工作得很好,智威湯遜中包含的所有角色,並聲稱

你可以看到如何與ASP.Net核心身份在這裏 http://docs.identityserver.io/en/release/quickstarts/6_aspnet_identity.html https://github.com/IdentityServer/IdentityServer4.Samples/tree/dev/Quickstarts/6_AspNetIdentity

1-身份服務器啓動實施Identityserver4的.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?}"); 
      }); 

     } 

2- IdentityServerConfig.cs

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

     } 
    } 

3 - IdentityProfileService.cs

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

} 

4 - 在我的客戶MVC的核心項目,我加3個的NuGet包

.Microsoft.AspNetCore.Authentication.Cookies

.Microsoft.AspNetCore .Authentication.OpenIdConnect

.IdentityModel

5-這是我的創業公司。CS在我的客戶端的MVC核心項目

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?}"); 
      }); 
     } 

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(); 
+1

乾杯碎肉。我不喜歡很多,但你用這個答案浮起我的船。身份聲稱疼痛避免了。 – no1spirite

+1

我在'IdentityProfileService'中添加了一個聲明,它在令牌中,你知道如何只在特定的客戶端添加,而不是在所有的客戶端? 這是聲明'/ /添加更多這樣的聲明 //claims.Add(新System.Security.Claims.Claim(「平衡」,user.Balance.To()));' –

+0

嗨威廉, 是的,如果您不想爲客戶添加索賠或索賠,則可以檢查「context.Client.ClientId」。我正在使用它來查找我的TenantId在JWS中添加tenantId。 – Mirak

相關問題