Browse Source

Refactor IDS4 and added a test controller.

pull/194/head
Halil İbrahim Kalkan 9 years ago
parent
commit
73d9ba7642
  1. 48
      src/AbpDesk/AbpDesk.Web.Mvc/Controllers/IdentityServerTestController.cs
  2. 9
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiAndIdentityResources.cs
  3. 24
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs
  4. 5
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs
  5. 126
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs
  6. 8
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs
  7. 8
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs
  8. 9
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs
  9. 4
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceStore.cs
  10. 14
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs
  11. 59
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs
  12. 1
      src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs
  13. 27
      src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResourceRepository.cs

48
src/AbpDesk/AbpDesk.Web.Mvc/Controllers/IdentityServerTestController.cs

@ -0,0 +1,48 @@
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
using Client = Volo.Abp.IdentityServer.Clients.Client;
namespace AbpDesk.Web.Mvc.Controllers
{
[Route("identity-server-test")]
public class IdentityServerTestController : AbpController
{
private readonly IClientRepository _clientRepository;
private readonly IApiResourceRepository _apiResourceRepository;
public IdentityServerTestController(IClientRepository clientRepository, IApiResourceRepository apiResourceRepository)
{
_clientRepository = clientRepository;
_apiResourceRepository = apiResourceRepository;
}
[HttpGet]
[Route("create")]
public async Task<IActionResult> CreateClient(string clientId)
{
var apiResource = (await _apiResourceRepository.GetListAsync()).FirstOrDefault(ar => ar.Name == "api1");
if (apiResource == null)
{
apiResource = new ApiResource(GuidGenerator.Create(), "api1");
await _apiResourceRepository.InsertAsync(apiResource);
}
var client = new Client(GuidGenerator.Create(), clientId);
client.AddGrantTypes(GuidGenerator, GrantTypes.ClientCredentials);
client.AddSecret(GuidGenerator, "secret".Sha256());
client.AddAllowedScope(GuidGenerator, "api1"); //TODO: Why not with Id..?
await _clientRepository.InsertAsync(client);
return Content("OK: " + client.Id);
}
}
}

9
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiAndIdentityResources.cs

@ -1,15 +1,14 @@
using System.Threading.Tasks; using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.ApiResources namespace Volo.Abp.IdentityServer.ApiResources
{ {
public class ApiAndIdentityResources public class ApiAndIdentityResources
{ {
public Task<IdentityResource[]> IdentityResources { get; set; } public IdentityResource[] IdentityResources { get; set; }
public Task<ApiResource[]> ApiResources { get; set; } public ApiResource[] ApiResources { get; set; }
public ApiAndIdentityResources(Task<IdentityResource[]> identityResources, Task<ApiResource[]> apiResources) public ApiAndIdentityResources(IdentityResource[] identityResources, ApiResource[] apiResources)
{ {
IdentityResources = identityResources; IdentityResources = identityResources;
ApiResources = apiResources; ApiResources = apiResources;

24
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs

@ -1,12 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.ApiResources namespace Volo.Abp.IdentityServer.ApiResources
{ {
public class ApiResource : AggregateRoot public class ApiResource : AggregateRoot
{ {
public virtual bool Enabled { get; set; } = true; public virtual bool Enabled { get; set; }
public virtual string Name { get; set; } public virtual string Name { get; set; }
@ -14,20 +15,31 @@ namespace Volo.Abp.IdentityServer.ApiResources
public virtual string Description { get; set; } public virtual string Description { get; set; }
public virtual List<ApiSecret> Secrets { get; set; } public virtual List<ApiSecret> Secrets { get; protected set; }
public virtual List<ApiScope> Scopes { get; set; } public virtual List<ApiScope> Scopes { get; protected set; }
public virtual List<ApiResourceClaim> UserClaims { get; set; } public virtual List<ApiResourceClaim> UserClaims { get; protected set; }
protected ApiResource() protected ApiResource()
{ {
} }
public ApiResource(Guid id) public ApiResource(Guid id, [NotNull] string name, string displayName = null, string description = null)
{ {
Check.NotNull(name, nameof(name));
Id = id; Id = id;
Name = name;
DisplayName = displayName;
Description = description;
Enabled = true;
Secrets = new List<ApiSecret>();
Scopes = new List<ApiScope>();
UserClaims = new List<ApiResourceClaim>();
} }
} }
} }

5
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs

@ -1,4 +1,5 @@
using System; using System;
using IdentityServer4;
namespace Volo.Abp.IdentityServer.ApiResources namespace Volo.Abp.IdentityServer.ApiResources
{ {
@ -11,8 +12,8 @@ namespace Volo.Abp.IdentityServer.ApiResources
} }
public ApiSecret(Guid id) public ApiSecret(Guid id, string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null)
: base(id) : base(id, value, expiration, type, description)
{ {
} }

126
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs

@ -1,13 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using IdentityServer4; using IdentityServer4;
using IdentityServer4.Models; using IdentityServer4.Models;
using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
namespace Volo.Abp.IdentityServer.Clients namespace Volo.Abp.IdentityServer.Clients
{ {
//TODO: Move property initializations to ctor.
public class Client : AggregateRoot public class Client : AggregateRoot
{ {
public virtual string ClientId { get; set; } public virtual string ClientId { get; set; }
@ -22,90 +22,146 @@ namespace Volo.Abp.IdentityServer.Clients
public virtual bool Enabled { get; set; } = true; public virtual bool Enabled { get; set; } = true;
public virtual string ProtocolType { get; set; } = IdentityServerConstants.ProtocolTypes.OpenIdConnect; public virtual string ProtocolType { get; set; }
public virtual List<ClientSecret> ClientSecrets { get; set; }
public virtual bool RequireClientSecret { get; set; } = true; public virtual bool RequireClientSecret { get; set; }
public virtual bool RequireConsent { get; set; } = true; public virtual bool RequireConsent { get; set; } = true;
public virtual bool AllowRememberConsent { get; set; } = true; public virtual bool AllowRememberConsent { get; set; }
public virtual bool AlwaysIncludeUserClaimsInIdToken { get; set; } public virtual bool AlwaysIncludeUserClaimsInIdToken { get; set; }
public virtual List<ClientGrantType> AllowedGrantTypes { get; set; }
public virtual bool RequirePkce { get; set; } public virtual bool RequirePkce { get; set; }
public virtual bool AllowPlainTextPkce { get; set; } public virtual bool AllowPlainTextPkce { get; set; }
public virtual bool AllowAccessTokensViaBrowser { get; set; } public virtual bool AllowAccessTokensViaBrowser { get; set; }
public virtual List<ClientRedirectUri> RedirectUris { get; set; }
public virtual List<ClientPostLogoutRedirectUri> PostLogoutRedirectUris { get; set; }
public virtual string FrontChannelLogoutUri { get; set; } public virtual string FrontChannelLogoutUri { get; set; }
public virtual bool FrontChannelLogoutSessionRequired { get; set; } = true; public virtual bool FrontChannelLogoutSessionRequired { get; set; }
public virtual string BackChannelLogoutUri { get; set; } public virtual string BackChannelLogoutUri { get; set; }
public virtual bool BackChannelLogoutSessionRequired { get; set; } = true; public virtual bool BackChannelLogoutSessionRequired { get; set; }
public virtual bool AllowOfflineAccess { get; set; } public virtual bool AllowOfflineAccess { get; set; }
public virtual List<ClientScope> AllowedScopes { get; set; } public virtual int IdentityTokenLifetime { get; set; }
public virtual int IdentityTokenLifetime { get; set; } = 300;
public virtual int AccessTokenLifetime { get; set; } = 3600; public virtual int AccessTokenLifetime { get; set; }
public virtual int AuthorizationCodeLifetime { get; set; } = 300; public virtual int AuthorizationCodeLifetime { get; set; }
public virtual int? ConsentLifetime { get; set; } = null; public virtual int? ConsentLifetime { get; set; }
public virtual int AbsoluteRefreshTokenLifetime { get; set; } = 2592000; public virtual int AbsoluteRefreshTokenLifetime { get; set; }
public virtual int SlidingRefreshTokenLifetime { get; set; } = 1296000; public virtual int SlidingRefreshTokenLifetime { get; set; }
public virtual int RefreshTokenUsage { get; set; } = (int)TokenUsage.OneTimeOnly; public virtual int RefreshTokenUsage { get; set; }
public virtual bool UpdateAccessTokenClaimsOnRefresh { get; set; } public virtual bool UpdateAccessTokenClaimsOnRefresh { get; set; }
public virtual int RefreshTokenExpiration { get; set; } = (int)TokenExpiration.Absolute; public virtual int RefreshTokenExpiration { get; set; }
public virtual int AccessTokenType { get; set; } = (int)0; // AccessTokenType.Jwt; public virtual int AccessTokenType { get; set; }
public virtual bool EnableLocalLogin { get; set; } = true; public virtual bool EnableLocalLogin { get; set; }
public virtual List<ClientIdPRestriction> IdentityProviderRestrictions { get; set; }
public virtual bool IncludeJwtId { get; set; } public virtual bool IncludeJwtId { get; set; }
public virtual List<ClientClaim> Claims { get; set; }
public virtual bool AlwaysSendClientClaims { get; set; } public virtual bool AlwaysSendClientClaims { get; set; }
public virtual string ClientClaimsPrefix { get; set; } = "client_"; public virtual string ClientClaimsPrefix { get; set; }
public virtual string PairWiseSubjectSalt { get; set; } public virtual string PairWiseSubjectSalt { get; set; }
public virtual List<ClientScope> AllowedScopes { get; set; }
public virtual List<ClientSecret> ClientSecrets { get; set; }
public virtual List<ClientGrantType> AllowedGrantTypes { get; set; }
public virtual List<ClientCorsOrigin> AllowedCorsOrigins { get; set; } public virtual List<ClientCorsOrigin> AllowedCorsOrigins { get; set; }
public virtual List<ClientRedirectUri> RedirectUris { get; set; }
public virtual List<ClientPostLogoutRedirectUri> PostLogoutRedirectUris { get; set; }
public virtual List<ClientIdPRestriction> IdentityProviderRestrictions { get; set; }
public virtual List<ClientClaim> Claims { get; set; }
public virtual List<ClientProperty> Properties { get; set; } public virtual List<ClientProperty> Properties { get; set; }
protected Client() protected Client()
{ {
} }
public Client(Guid id) public Client(Guid id, string clientId)
{ {
Id = id; Id = id;
ClientId = clientId;
//TODO: Replace magics with constants?
ProtocolType = IdentityServerConstants.ProtocolTypes.OpenIdConnect;
RequireClientSecret = true;
RequireConsent = true;
AllowRememberConsent = true;
FrontChannelLogoutSessionRequired = true;
BackChannelLogoutSessionRequired = true;
IdentityTokenLifetime = 300;
AccessTokenLifetime = 3600;
AuthorizationCodeLifetime = 300;
AbsoluteRefreshTokenLifetime = 2592000;
SlidingRefreshTokenLifetime = 1296000;
RefreshTokenUsage = (int)TokenUsage.OneTimeOnly;
RefreshTokenExpiration = (int)TokenExpiration.Absolute;
AccessTokenType = (int)IdentityServer4.Models.AccessTokenType.Jwt;
EnableLocalLogin = true;
ClientClaimsPrefix = "client_";
AllowedScopes = new List<ClientScope>();
ClientSecrets = new List<ClientSecret>();
AllowedGrantTypes = new List<ClientGrantType>();
AllowedCorsOrigins = new List<ClientCorsOrigin>(); AllowedCorsOrigins = new List<ClientCorsOrigin>();
RedirectUris = new List<ClientRedirectUri>();
PostLogoutRedirectUris = new List<ClientPostLogoutRedirectUri>();
IdentityProviderRestrictions = new List<ClientIdPRestriction>();
Claims = new List<ClientClaim>();
Properties = new List<ClientProperty>();
}
public virtual void AddGrantType(IGuidGenerator guidGenerator, string grantType)
{
AllowedGrantTypes.Add(
new ClientGrantType(guidGenerator.Create(), Id, grantType)
);
}
public virtual void AddGrantTypes(IGuidGenerator guidGenerator, IEnumerable<string> grantTypes)
{
AllowedGrantTypes.AddRange(
grantTypes.Select(
grantType => new ClientGrantType(guidGenerator.Create(), Id, grantType)
)
);
}
public virtual void AddSecret(IGuidGenerator guidGenerator, string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null)
{
ClientSecrets.Add(
new ClientSecret(guidGenerator.Create(), Id, value, expiration, type, description)
);
}
public virtual void AddAllowedScope(IGuidGenerator guidGenerator, string scope)
{
AllowedScopes.Add(new ClientScope(guidGenerator.Create(), Id, scope));
} }
} }
} }

8
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs

@ -5,18 +5,20 @@ namespace Volo.Abp.IdentityServer.Clients
{ {
public class ClientGrantType : Entity public class ClientGrantType : Entity
{ {
public virtual string GrantType { get; set; } public virtual string GrantType { get; protected set; }
public virtual Guid ClientId { get; set; } public virtual Guid ClientId { get; protected set; }
protected ClientGrantType() protected ClientGrantType()
{ {
} }
public ClientGrantType(Guid id) public ClientGrantType(Guid id, Guid clientId, string grantType)
{ {
Id = id; Id = id;
ClientId = clientId;
GrantType = grantType;
} }
} }
} }

8
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs

@ -5,18 +5,20 @@ namespace Volo.Abp.IdentityServer.Clients
{ {
public class ClientScope : Entity public class ClientScope : Entity
{ {
public virtual string Scope { get; set; } public virtual string Scope { get; protected set; }
public virtual Guid ClientId { get; set; } public virtual Guid ClientId { get; protected set; }
protected ClientScope() protected ClientScope()
{ {
} }
public ClientScope(Guid id) public ClientScope(Guid id, Guid clientId, string scope)
{ {
Id = id; Id = id;
ClientId = clientId;
Scope = scope;
} }
} }
} }

9
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs

@ -1,20 +1,21 @@
using System; using System;
using IdentityServer4;
namespace Volo.Abp.IdentityServer.Clients namespace Volo.Abp.IdentityServer.Clients
{ {
public class ClientSecret : Secret public class ClientSecret : Secret
{ {
public virtual Guid ClientId { get; set; } public virtual Guid ClientId { get; protected set; }
protected ClientSecret() protected ClientSecret()
{ {
} }
public ClientSecret(Guid id) public ClientSecret(Guid id, Guid clientId, string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null)
: base(id) : base(id, value, expiration, type, description)
{ {
Id = id; ClientId = clientId;
} }
} }
} }

4
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceStore.cs

@ -42,8 +42,8 @@ namespace Volo.Abp.IdentityServer.IdentityResources
var result = await _identityResourceRepository.GetAllResourcesAsync(); var result = await _identityResourceRepository.GetAllResourcesAsync();
return new Resources( return new Resources(
result.IdentityResources.Result.Select(y => _objectMapper.Map<IdentityResource, IdentityServer4.Models.IdentityResource>(y)), _objectMapper.Map<IdentityResource[], IdentityServer4.Models.IdentityResource[]>(result.IdentityResources),
result.ApiResources.Result.Select(x => _objectMapper.Map<ApiResources.ApiResource, ApiResource>(x)) _objectMapper.Map<ApiResources.ApiResource[], ApiResource[]>(result.ApiResources)
); );
} }
} }

14
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs

@ -8,22 +8,26 @@ namespace Volo.Abp.IdentityServer
public abstract class Secret : Entity public abstract class Secret : Entity
{ {
public virtual string Description { get; set; } public virtual string Description { get; protected set; }
public virtual string Value { get; set; } public virtual string Value { get; protected set; }
public virtual DateTime? Expiration { get; set; } public virtual DateTime? Expiration { get; protected set; }
public virtual string Type { get; set; } = IdentityServerConstants.SecretTypes.SharedSecret; public virtual string Type { get; protected set; }
protected Secret() protected Secret()
{ {
} }
protected Secret(Guid id) protected Secret(Guid id, string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null)
{ {
Id = id; Id = id;
Value = value;
Expiration = expiration;
Type = type;
Description = description;
} }
} }
} }

59
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs

@ -3,37 +3,38 @@ using IdentityServer4.Models;
namespace Volo.Abp.IdentityServer.Temp namespace Volo.Abp.IdentityServer.Temp
{ {
internal static class IdentityServerConfig //TODO: Remove!
{ //internal static class IdentityServerConfig
public static IEnumerable<ApiResource> GetApiResources() //{
{ // public static IEnumerable<ApiResource> GetApiResources()
return new List<ApiResource> // {
{ // return new List<ApiResource>
new ApiResource("api1", "My API") // {
}; // new ApiResource("api1", "My API")
} // };
// }
public static IEnumerable<IdentityServer4.Models.Client> GetClients() // public static IEnumerable<IdentityServer4.Models.Client> GetClients()
{ // {
return new List<Client> // return new List<Client>
{ // {
new Client // new Client
{ // {
ClientId = "client", // ClientId = "client",
// no interactive user, use the clientid/secret for authentication // // no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials, // AllowedGrantTypes = GrantTypes.ClientCredentials,
// secret for authentication // // secret for authentication
ClientSecrets = // ClientSecrets =
{ // {
new IdentityServer4.Models.Secret("secret".Sha256()) // new IdentityServer4.Models.Secret("secret".Sha256())
}, // },
// scopes that client has access to // // scopes that client has access to
AllowedScopes = { "api1" } // AllowedScopes = { "api1" }
} // }
}; // };
} // }
} //}
} }

1
src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs

@ -171,7 +171,6 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
identityResource.HasIndex(x => x.Name).IsUnique(); identityResource.HasIndex(x => x.Name).IsUnique();
identityResource.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.IdentityResourceId).IsRequired(); identityResource.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.IdentityResourceId).IsRequired();
}); });

27
src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResourceRepository.cs

@ -18,48 +18,46 @@ namespace Volo.Abp.IdentityServer
} }
public Task<List<IdentityResource>> FindIdentityResourcesByScopeAsync(string[] scopeNames) public async Task<List<IdentityResource>> FindIdentityResourcesByScopeAsync(string[] scopeNames)
{ {
var query = from identityResource in DbSet.Include(x => x.UserClaims) var query = from identityResource in DbSet.Include(x => x.UserClaims)
where scopeNames.Contains(identityResource.Name) where scopeNames.Contains(identityResource.Name)
select identityResource; select identityResource;
return query.ToListAsync(); return await query.ToListAsync();
} }
public Task<List<ApiResource>> FindApiResourcesByScopeAsync(string[] scopeNames) public async Task<List<ApiResource>> FindApiResourcesByScopeAsync(string[] scopeNames)
{ {
var names = scopeNames.ToArray();
var query = from api in DbContext.ApiResources var query = from api in DbContext.ApiResources
where api.Scopes.Any(x => names.Contains(x.Name)) where api.Scopes.Any(x => scopeNames.Contains(x.Name))
select api; select api;
var apis = query query = query
.Include(x => x.Secrets) .Include(x => x.Secrets)
.Include(x => x.Scopes) .Include(x => x.Scopes)
.ThenInclude(s => s.UserClaims) .ThenInclude(s => s.UserClaims)
.Include(x => x.UserClaims); .Include(x => x.UserClaims);
return apis.ToListAsync(); return await query.ToListAsync();
} }
public Task<ApiResource> FindApiResourceAsync(string name) public async Task<ApiResource> FindApiResourceAsync(string name)
{ {
var query = from apiResource in DbContext.ApiResources var query = from apiResource in DbContext.ApiResources
where apiResource.Name == name where apiResource.Name == name
select apiResource; select apiResource;
var apis = query query = query
.Include(x => x.Secrets) .Include(x => x.Secrets)
.Include(x => x.Scopes) .Include(x => x.Scopes)
.ThenInclude(s => s.UserClaims) .ThenInclude(s => s.UserClaims)
.Include(x => x.UserClaims); .Include(x => x.UserClaims);
return apis.FirstOrDefaultAsync(); return await query.FirstOrDefaultAsync();
} }
public Task<ApiResources.ApiAndIdentityResources> GetAllResourcesAsync() public async Task<ApiResources.ApiAndIdentityResources> GetAllResourcesAsync()
{ {
var identity = DbContext.IdentityResources var identity = DbContext.IdentityResources
.Include(x => x.UserClaims); .Include(x => x.UserClaims);
@ -70,7 +68,10 @@ namespace Volo.Abp.IdentityServer
.ThenInclude(s => s.UserClaims) .ThenInclude(s => s.UserClaims)
.Include(x => x.UserClaims); .Include(x => x.UserClaims);
return Task.FromResult(new ApiResources.ApiAndIdentityResources(identity.ToArrayAsync(), apis.ToArrayAsync())); return new ApiResources.ApiAndIdentityResources(
await identity.ToArrayAsync(),
await apis.ToArrayAsync()
);
} }
} }
} }

Loading…
Cancel
Save