diff --git a/src/AbpDesk/AbpDesk.Web.Mvc/Controllers/IdentityServerTestController.cs b/src/AbpDesk/AbpDesk.Web.Mvc/Controllers/IdentityServerTestController.cs new file mode 100644 index 0000000000..62ca656721 --- /dev/null +++ b/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 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); + } + } +} diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiAndIdentityResources.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiAndIdentityResources.cs index 5d71532dba..13c049d568 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiAndIdentityResources.cs +++ b/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 { public class ApiAndIdentityResources { - public Task IdentityResources { get; set; } + public IdentityResource[] IdentityResources { get; set; } - public Task ApiResources { get; set; } + public ApiResource[] ApiResources { get; set; } - public ApiAndIdentityResources(Task identityResources, Task apiResources) + public ApiAndIdentityResources(IdentityResource[] identityResources, ApiResource[] apiResources) { IdentityResources = identityResources; ApiResources = apiResources; diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs index 72ab3cb7c1..a3bd2109cb 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs +++ b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using JetBrains.Annotations; using Volo.Abp.Domain.Entities; namespace Volo.Abp.IdentityServer.ApiResources { public class ApiResource : AggregateRoot { - public virtual bool Enabled { get; set; } = true; + public virtual bool Enabled { 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 List Secrets { get; set; } + public virtual List Secrets { get; protected set; } - public virtual List Scopes { get; set; } + public virtual List Scopes { get; protected set; } - public virtual List UserClaims { get; set; } + public virtual List UserClaims { get; protected set; } 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; + Name = name; + DisplayName = displayName; + Description = description; + + Enabled = true; + + Secrets = new List(); + Scopes = new List(); + UserClaims = new List(); } } } diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs index 2e656dcc3d..73355998ec 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs +++ b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs @@ -1,4 +1,5 @@ using System; +using IdentityServer4; namespace Volo.Abp.IdentityServer.ApiResources { @@ -11,8 +12,8 @@ namespace Volo.Abp.IdentityServer.ApiResources } - public ApiSecret(Guid id) - : base(id) + public ApiSecret(Guid id, string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null) + : base(id, value, expiration, type, description) { } diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs index 1abe965748..14db9e7191 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs +++ b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs @@ -1,13 +1,13 @@ using System; using System.Collections.Generic; +using System.Linq; using IdentityServer4; using IdentityServer4.Models; using Volo.Abp.Domain.Entities; +using Volo.Abp.Guids; namespace Volo.Abp.IdentityServer.Clients { - //TODO: Move property initializations to ctor. - public class Client : AggregateRoot { public virtual string ClientId { get; set; } @@ -22,90 +22,146 @@ namespace Volo.Abp.IdentityServer.Clients public virtual bool Enabled { get; set; } = true; - public virtual string ProtocolType { get; set; } = IdentityServerConstants.ProtocolTypes.OpenIdConnect; - - public virtual List ClientSecrets { get; set; } + public virtual string ProtocolType { 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 AllowRememberConsent { get; set; } = true; + public virtual bool AllowRememberConsent { get; set; } public virtual bool AlwaysIncludeUserClaimsInIdToken { get; set; } - public virtual List AllowedGrantTypes { get; set; } - public virtual bool RequirePkce { get; set; } public virtual bool AllowPlainTextPkce { get; set; } public virtual bool AllowAccessTokensViaBrowser { get; set; } - public virtual List RedirectUris { get; set; } - - public virtual List PostLogoutRedirectUris { 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 bool BackChannelLogoutSessionRequired { get; set; } = true; + public virtual bool BackChannelLogoutSessionRequired { get; set; } public virtual bool AllowOfflineAccess { get; set; } - public virtual List AllowedScopes { get; set; } - - public virtual int IdentityTokenLifetime { get; set; } = 300; + public virtual int IdentityTokenLifetime { get; set; } - 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 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 List IdentityProviderRestrictions { get; set; } + public virtual bool EnableLocalLogin { get; set; } public virtual bool IncludeJwtId { get; set; } - public virtual List Claims { 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 List AllowedScopes { get; set; } + + public virtual List ClientSecrets { get; set; } + + public virtual List AllowedGrantTypes { get; set; } + public virtual List AllowedCorsOrigins { get; set; } + public virtual List RedirectUris { get; set; } + + public virtual List PostLogoutRedirectUris { get; set; } + + public virtual List IdentityProviderRestrictions { get; set; } + + public virtual List Claims { get; set; } + public virtual List Properties { get; set; } protected Client() { - + } - public Client(Guid id) + public Client(Guid id, string clientId) { 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(); + ClientSecrets = new List(); + AllowedGrantTypes = new List(); AllowedCorsOrigins = new List(); + RedirectUris = new List(); + PostLogoutRedirectUris = new List(); + IdentityProviderRestrictions = new List(); + Claims = new List(); + Properties = new List(); + } + + public virtual void AddGrantType(IGuidGenerator guidGenerator, string grantType) + { + AllowedGrantTypes.Add( + new ClientGrantType(guidGenerator.Create(), Id, grantType) + ); + } + + public virtual void AddGrantTypes(IGuidGenerator guidGenerator, IEnumerable 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)); } } } \ No newline at end of file diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs index 8b577193ad..13a60333ec 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs +++ b/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 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() { } - public ClientGrantType(Guid id) + public ClientGrantType(Guid id, Guid clientId, string grantType) { Id = id; + ClientId = clientId; + GrantType = grantType; } } } \ No newline at end of file diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs index b7740dd78b..e28d33cacb 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs +++ b/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 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() { } - public ClientScope(Guid id) + public ClientScope(Guid id, Guid clientId, string scope) { Id = id; + ClientId = clientId; + Scope = scope; } } } \ No newline at end of file diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs index a0de719658..ebb58caa8f 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs +++ b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs @@ -1,20 +1,21 @@ using System; +using IdentityServer4; namespace Volo.Abp.IdentityServer.Clients { public class ClientSecret : Secret { - public virtual Guid ClientId { get; set; } + public virtual Guid ClientId { get; protected set; } protected ClientSecret() { } - public ClientSecret(Guid id) - : base(id) + public ClientSecret(Guid id, Guid clientId, string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null) + : base(id, value, expiration, type, description) { - Id = id; + ClientId = clientId; } } } \ No newline at end of file diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceStore.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceStore.cs index abdcec5354..ca16af2512 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceStore.cs +++ b/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(); return new Resources( - result.IdentityResources.Result.Select(y => _objectMapper.Map(y)), - result.ApiResources.Result.Select(x => _objectMapper.Map(x)) + _objectMapper.Map(result.IdentityResources), + _objectMapper.Map(result.ApiResources) ); } } diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs index bf0b83d444..6e7f753124 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs +++ b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs @@ -8,22 +8,26 @@ namespace Volo.Abp.IdentityServer 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(Guid id) + protected Secret(Guid id, string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null) { Id = id; + Value = value; + Expiration = expiration; + Type = type; + Description = description; } } } \ No newline at end of file diff --git a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs index 3421d6c950..6ccfc18ce4 100644 --- a/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs +++ b/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs @@ -3,37 +3,38 @@ using IdentityServer4.Models; namespace Volo.Abp.IdentityServer.Temp { - internal static class IdentityServerConfig - { - public static IEnumerable GetApiResources() - { - return new List - { - new ApiResource("api1", "My API") - }; - } + //TODO: Remove! + //internal static class IdentityServerConfig + //{ + // public static IEnumerable GetApiResources() + // { + // return new List + // { + // new ApiResource("api1", "My API") + // }; + // } - public static IEnumerable GetClients() - { - return new List - { - new Client - { - ClientId = "client", + // public static IEnumerable GetClients() + // { + // return new List + // { + // new Client + // { + // ClientId = "client", - // no interactive user, use the clientid/secret for authentication - AllowedGrantTypes = GrantTypes.ClientCredentials, + // // no interactive user, use the clientid/secret for authentication + // AllowedGrantTypes = GrantTypes.ClientCredentials, - // secret for authentication - ClientSecrets = - { - new IdentityServer4.Models.Secret("secret".Sha256()) - }, + // // secret for authentication + // ClientSecrets = + // { + // new IdentityServer4.Models.Secret("secret".Sha256()) + // }, - // scopes that client has access to - AllowedScopes = { "api1" } - } - }; - } - } + // // scopes that client has access to + // AllowedScopes = { "api1" } + // } + // }; + // } + //} } \ No newline at end of file diff --git a/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs b/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs index ae82b5bb06..277bc160a1 100644 --- a/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs +++ b/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.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.IdentityResourceId).IsRequired(); }); diff --git a/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResourceRepository.cs b/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResourceRepository.cs index 98585fac41..6948147c72 100644 --- a/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResourceRepository.cs +++ b/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResourceRepository.cs @@ -18,48 +18,46 @@ namespace Volo.Abp.IdentityServer } - public Task> FindIdentityResourcesByScopeAsync(string[] scopeNames) + public async Task> FindIdentityResourcesByScopeAsync(string[] scopeNames) { var query = from identityResource in DbSet.Include(x => x.UserClaims) where scopeNames.Contains(identityResource.Name) select identityResource; - return query.ToListAsync(); + return await query.ToListAsync(); } - public Task> FindApiResourcesByScopeAsync(string[] scopeNames) + public async Task> FindApiResourcesByScopeAsync(string[] scopeNames) { - var names = scopeNames.ToArray(); - 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; - var apis = query + query = query .Include(x => x.Secrets) .Include(x => x.Scopes) .ThenInclude(s => s.UserClaims) .Include(x => x.UserClaims); - return apis.ToListAsync(); + return await query.ToListAsync(); } - public Task FindApiResourceAsync(string name) + public async Task FindApiResourceAsync(string name) { var query = from apiResource in DbContext.ApiResources where apiResource.Name == name select apiResource; - var apis = query + query = query .Include(x => x.Secrets) .Include(x => x.Scopes) .ThenInclude(s => s.UserClaims) .Include(x => x.UserClaims); - return apis.FirstOrDefaultAsync(); + return await query.FirstOrDefaultAsync(); } - public Task GetAllResourcesAsync() + public async Task GetAllResourcesAsync() { var identity = DbContext.IdentityResources .Include(x => x.UserClaims); @@ -70,7 +68,10 @@ namespace Volo.Abp.IdentityServer .ThenInclude(s => s.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() + ); } } }