Browse Source

Added identityserver module

pull/451/head
Yunus Emre Kalkan 8 years ago
parent
commit
348d255da3
  1. 1
      build-all.ps1
  2. 2
      build-test-all.ps1
  3. 53
      modules/identityserver/Volo.Abp.IdentityServer.sln
  4. 16
      modules/identityserver/common.props
  5. 20
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo.Abp.IdentityServer.Domain.Shared.csproj
  6. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/AbpIdentityServerDomainSharedModule.cs
  7. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiResourceConsts.cs
  8. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiScopeConsts.cs
  9. 8
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientClaimConsts.cs
  10. 25
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientConsts.cs
  11. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientCorsOriginConsts.cs
  12. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientGrantTypeConsts.cs
  13. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientIdPRestrictionConsts.cs
  14. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUriConsts.cs
  15. 8
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPropertyConsts.cs
  16. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientRedirectUriConsts.cs
  17. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientScopeConsts.cs
  18. 10
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Grants/PersistedGrantConsts.cs
  19. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceConsts.cs
  20. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/SecretConsts.cs
  21. 7
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/UserClaimConsts.cs
  22. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj
  23. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj.DotSettings
  24. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs
  25. 48
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs
  26. 9
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerConsts.cs
  27. 47
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs
  28. 17
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerOptions.cs
  29. 76
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs
  30. 26
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResourceClaim.cs
  31. 64
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScope.cs
  32. 32
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScopeClaim.cs
  33. 36
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs
  34. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/IApiResourceRepository.cs
  35. 42
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs
  36. 33
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs
  37. 196
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs
  38. 86
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientAutoMapperProfile.cs
  39. 30
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientClaim.cs
  40. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientCorsOrigin.cs
  41. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs
  42. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientIdPRestriction.cs
  43. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUri.cs
  44. 33
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientProperty.cs
  45. 31
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientRedirectUri.cs
  46. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs
  47. 36
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs
  48. 24
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientStore.cs
  49. 17
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/IClientRepository.cs
  50. 34
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/IPersistentGrantRepository.cs
  51. 32
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrant.cs
  52. 72
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrantStore.cs
  53. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IIdentityResourceRepository.cs
  54. 26
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityClaim.cs
  55. 60
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResource.cs
  56. 27
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Jwt/JwtTokenMiddleware.cs
  57. 59
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs
  58. 37
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs
  59. 37
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs
  60. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/UserClaim.cs
  61. 22
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj
  62. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj.DotSettings
  63. 55
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/AbpIdentityServerEfCoreQueryableExtensions.cs
  64. 59
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs
  65. 34
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs
  66. 28
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/AbpIdentityServerEntityFrameworkCoreModule.cs
  67. 50
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IIdentityServerDbContext.cs
  68. 66
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs
  69. 228
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs
  70. 60
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs
  71. 47
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs
  72. 33
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests.csproj
  73. 10
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityApplicationTestBase.cs
  74. 129
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs
  75. 53
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityServerTestEntityFrameworkCoreModule.cs
  76. 39
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs
  77. 90
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs
  78. 130
      modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs

1
build-all.ps1

@ -10,6 +10,7 @@ $solutionPaths = (
"modules/permission-management",
"modules/setting-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",
"modules/account",
"modules/docs",

2
build-test-all.ps1

@ -10,6 +10,7 @@ $solutionsPaths = (
"modules/permission-management",
"modules/setting-management",
"modules/identity",
"modules/identityserver",
"modules/tenant-management",
"modules/account",
"modules/docs",
@ -54,6 +55,7 @@ $testProjectPaths = (
"modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests",
"modules/identity/test/Volo.Abp.Identity.Domain.Tests",
"modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests",
"modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests",
"modules/identity/test/Volo.Abp.Identity.MongoDB.Tests",
"modules/identity/test/Volo.Abp.Identity.Application.Tests",
"modules/permission-management/test/Volo.Abp.PermissionManagement.Tests",

53
modules/identityserver/Volo.Abp.IdentityServer.sln

@ -0,0 +1,53 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2047
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.Domain", "src\Volo.Abp.IdentityServer.Domain\Volo.Abp.IdentityServer.Domain.csproj", "{A3B81AEE-EE96-4F75-856B-55B25D8822E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.Domain.Shared", "src\Volo.Abp.IdentityServer.Domain.Shared\Volo.Abp.IdentityServer.Domain.Shared.csproj", "{FC035412-78AD-424C-BECE-B19D04C7B5A6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.EntityFrameworkCore", "src\Volo.Abp.IdentityServer.EntityFrameworkCore\Volo.Abp.IdentityServer.EntityFrameworkCore.csproj", "{F352D620-1CBF-4658-953F-70BA73B458F1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2C792EC1-BA27-44ED-B7CC-D0939553F1B2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.IdentityServer.EntityFrameworkCore.Tests", "test\Volo.Abp.IdentityServer.EntityFrameworkCore.Tests\Volo.Abp.IdentityServer.EntityFrameworkCore.Tests.csproj", "{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3B81AEE-EE96-4F75-856B-55B25D8822E2}.Release|Any CPU.Build.0 = Release|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC035412-78AD-424C-BECE-B19D04C7B5A6}.Release|Any CPU.Build.0 = Release|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F352D620-1CBF-4658-953F-70BA73B458F1}.Release|Any CPU.Build.0 = Release|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A3B81AEE-EE96-4F75-856B-55B25D8822E2} = {59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}
{FC035412-78AD-424C-BECE-B19D04C7B5A6} = {59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}
{F352D620-1CBF-4658-953F-70BA73B458F1} = {59A0FC0F-EA6D-477B-84A7-3B1E41B4C858}
{8B8FBA95-4FA2-4438-A387-7C5EC7A89E82} = {2C792EC1-BA27-44ED-B7CC-D0939553F1B2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {45562023-C330-4060-A583-2BA10F472D3D}
EndGlobalSection
EndGlobal

16
modules/identityserver/common.props

@ -0,0 +1,16 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>0.3.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>http://www.aspnetboilerplate.com/images/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>http://abp.io</PackageProjectUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/volosoft/abp/</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SourceLink.Create.CommandLine" Version="2.8.1" PrivateAssets="All" />
</ItemGroup>
</Project>

20
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo.Abp.IdentityServer.Domain.Shared.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.Domain.Shared</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.Domain.Shared</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/AbpIdentityServerDomainSharedModule.cs

@ -0,0 +1,9 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerDomainSharedModule : AbpModule
{
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiResourceConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiResourceConsts
{
public const int NameMaxLength = 200;
public const int DisplayNameMaxLength = 200;
public const int DescriptionMaxLength = 1000;
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/ApiResources/ApiScopeConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiScopeConsts
{
public const int NameMaxLength = 196;
public const int DisplayNameMaxLength = 128;
public const int DescriptionMaxLength = 256;
}
}

8
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientClaimConsts.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientClaimConsts
{
public const int TypeMaxLength = 250;
public const int ValueMaxLength = 250;
}
}

25
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientConsts.cs

@ -0,0 +1,25 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientConsts
{
public const int ClientIdMaxLength = 200;
public const int ProtocolTypeMaxLength = 200;
public const int ClientNameMaxLength = 200;
public const int ClientUriMaxLength = 2000;
public const int LogoUriMaxLength = 2000;
public const int DescriptionMaxLength = 1000;
public const int FrontChannelLogoutUriMaxLength = 2000;
public const int BackChannelLogoutUriMaxLength = 2000;
public const int ClientClaimsPrefixMaxLength = 200;
public const int PairWiseSubjectSaltMaxLength = 200;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientCorsOriginConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientCorsOriginConsts
{
public const int OriginMaxLength = 150;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientGrantTypeConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientGrantTypeConsts
{
public const int GrantTypeMaxLength = 196;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientIdPRestrictionConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientIdPRestrictionConsts
{
public const int ProviderMaxLength = 64;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUriConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientPostLogoutRedirectUriConsts
{
public const int PostLogoutRedirectUriMaxLength = 2000;
}
}

8
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientPropertyConsts.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientPropertyConsts
{
public const int KeyMaxLength = 250;
public const int ValueMaxLength = 2000;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientRedirectUriConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientRedirectUriConsts
{
public const int RedirectUriMaxLength = 2000;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Clients/ClientScopeConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientScopeConsts
{
public const int ScopeMaxLength = 196;
}
}

10
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Grants/PersistedGrantConsts.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.IdentityServer.Grants
{
public class PersistedGrantConsts
{
public const int KeyMaxLength = 200;
public const int TypeMaxLength = 50;
public const int SubjectIdMaxLength = 200;
public const int ClientIdMaxLength = 200;
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer.IdentityResources
{
public class IdentityResourceConsts
{
public const int NameMaxLength = 200;
public const int DisplayNameMaxLength = 200;
public const int DescriptionMaxLength = 1000;
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/SecretConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer
{
public class SecretConsts
{
public const int TypeMaxLength = 32;
public const int ValueMaxLength = 196;
public const int DescriptionMaxLength = 256;
}
}

7
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/UserClaimConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.IdentityServer
{
public class UserClaimConsts
{
public const int TypeMaxLength = 196;
}
}

28
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.Domain</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.Domain</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.IdentityServer.Domain.Shared\Volo.Abp.IdentityServer.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\modules\identity\src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Security\Volo.Abp.Security.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IdentityServer4" Version="2.2.0" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" />
</ItemGroup>
</Project>

2
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo.Abp.IdentityServer.Domain.csproj.DotSettings

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

28
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpClaimsService.cs

@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using IdentityServer4.Services;
using Microsoft.Extensions.Logging;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.IdentityServer
{
public class AbpClaimsService : DefaultClaimsService
{
public AbpClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger)
: base(profile, logger)
{
}
protected override IEnumerable<Claim> GetOptionalClaims(ClaimsPrincipal subject)
{
var tenantClaim = subject.FindFirst(AbpClaimTypes.TenantId);
if (tenantClaim == null)
{
return base.GetOptionalClaims(subject);
}
return base.GetOptionalClaims(subject).Union(new[] { tenantClaim });
}
}
}

48
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs

@ -0,0 +1,48 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using IdentityModel;
using IdentityServer4.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.AspNetIdentity;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.IdentityServer
{
public static class AbpIdentityServerBuilderExtensions
{
public static IIdentityServerBuilder AddAbpIdentityServer(
this IIdentityServerBuilder builder,
Action<AbpIdentityServerOptions> optionsAction = null)
{
var options = new AbpIdentityServerOptions();
optionsAction?.Invoke(options);
//TODO: AspNet Identity integration lines. Can be extracted to a extension method
builder.AddAspNetIdentity<IdentityUser>();
builder.AddProfileService<AbpProfileService>();
builder.AddResourceOwnerValidator<AbpResourceOwnerPasswordValidator>();
builder.Services.Replace(ServiceDescriptor.Transient<IClaimsService, AbpClaimsService>());
if (options.UpdateAbpClaimTypes)
{
AbpClaimTypes.UserId = JwtClaimTypes.Subject;
AbpClaimTypes.UserName = JwtClaimTypes.Name;
AbpClaimTypes.Role = JwtClaimTypes.Role;
AbpClaimTypes.Email = JwtClaimTypes.Email;
}
if (options.UpdateJwtSecurityTokenHandlerDefaultInboundClaimTypeMap)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.UserId] = AbpClaimTypes.UserId;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.UserName] = AbpClaimTypes.UserName;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.Role] = AbpClaimTypes.Role;
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap[AbpClaimTypes.Email] = AbpClaimTypes.Email;
}
return builder;
}
}
}

9
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerConsts.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.IdentityServer
{
public static class AbpIdentityServerConsts
{
public const string DefaultDbTablePrefix = "IdentityServer";
public const string DefaultDbSchema = null;
}
}

47
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs

@ -0,0 +1,47 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Domain;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
namespace Volo.Abp.IdentityServer
{
[DependsOn(typeof(AbpIdentityServerDomainSharedModule))]
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpAutoMapperModule))]
[DependsOn(typeof(AbpIdentityDomainModule))]
[DependsOn(typeof(AbpSecurityModule))]
public class AbpIdentityServerDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<ClientAutoMapperProfile>(validate: true);
});
AddIdentityServer(context.Services);
}
private static void AddIdentityServer(IServiceCollection services)
{
var identityServerBuilder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
});
identityServerBuilder
.AddDeveloperSigningCredential() //TODO: Should be able to change this!
.AddClientStore<ClientStore>()
.AddResourceStore<ResourceStore>()
.AddAbpIdentityServer();
services.ExecutePreConfiguredActions(identityServerBuilder);
}
}
}

17
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerOptions.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerOptions
{
/// <summary>
/// Updates <see cref="JwtSecurityTokenHandler.DefaultInboundClaimTypeMap"/> to be compatible with identity server claims.
/// Default: true.
/// </summary>
public bool UpdateJwtSecurityTokenHandlerDefaultInboundClaimTypeMap { get; set; } = true;
/// <summary>
/// Updates <see cref="AbpClaimTypes"/> to be compatible with identity server claims.
/// Default: true.
/// </summary>
public bool UpdateAbpClaimTypes { get; set; } = true;
}
}

76
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResource.cs

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using IdentityServer4;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiResource : AggregateRoot<Guid>
{
[NotNull]
public virtual string Name { get; protected set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual bool Enabled { get; set; }
public virtual List<ApiSecret> Secrets { get; protected set; }
public virtual List<ApiScope> Scopes { get; protected set; }
public virtual List<ApiResourceClaim> UserClaims { get; protected set; }
protected ApiResource()
{
}
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<ApiSecret>();
Scopes = new List<ApiScope>();
UserClaims = new List<ApiResourceClaim>();
Scopes.Add(new ApiScope(id, name, displayName, description));
}
public virtual void AddSecret(
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null)
{
Secrets.Add(new ApiSecret(Id, value, expiration, type, description));
}
public virtual void AddScope(
[NotNull] string name,
string displayName = null,
string description = null,
bool required = false,
bool emphasize = false,
bool showInDiscoveryDocument = true)
{
Scopes.Add(new ApiScope(Id, name, displayName, description, required, emphasize, showInDiscoveryDocument));
}
public virtual void AddUserClaim([NotNull] string type)
{
UserClaims.Add(new ApiResourceClaim(Id, type));
}
}
}

26
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiResourceClaim.cs

@ -0,0 +1,26 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiResourceClaim : UserClaim
{
public virtual Guid ApiResourceId { get; set; }
protected ApiResourceClaim()
{
}
protected internal ApiResourceClaim(Guid apiResourceId, [NotNull] string type)
: base(type)
{
ApiResourceId = apiResourceId;
}
public override object[] GetKeys()
{
return new object[] {ApiResourceId, Type};
}
}
}

64
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScope.cs

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiScope : Entity
{
public virtual Guid ApiResourceId { get; protected set; }
[NotNull]
public virtual string Name { get; protected set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual bool Required { get; set; }
public virtual bool Emphasize { get; set; }
public virtual bool ShowInDiscoveryDocument { get; set; }
public virtual List<ApiScopeClaim> UserClaims { get; protected set; }
protected ApiScope()
{
}
protected internal ApiScope(
Guid apiResourceId,
[NotNull] string name,
string displayName = null,
string description = null,
bool required = false,
bool emphasize = false,
bool showInDiscoveryDocument = true)
{
Check.NotNull(name, nameof(name));
ApiResourceId = apiResourceId;
Name = name;
DisplayName = displayName ?? name;
Description = description;
Required = required;
Emphasize = emphasize;
ShowInDiscoveryDocument = showInDiscoveryDocument;
UserClaims = new List<ApiScopeClaim>();
}
public virtual void AddUserClaim([NotNull] string type)
{
UserClaims.Add(new ApiScopeClaim(ApiResourceId, Name, type));
}
public override object[] GetKeys()
{
return new object[] { ApiResourceId, Name };
}
}
}

32
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiScopeClaim.cs

@ -0,0 +1,32 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiScopeClaim : UserClaim
{
public Guid ApiResourceId { get; protected set; }
[NotNull]
public string Name { get; protected set; }
protected ApiScopeClaim()
{
}
protected internal ApiScopeClaim(Guid apiResourceId, [NotNull] string name, [NotNull] string type)
: base(type)
{
Check.NotNull(name, nameof(name));
ApiResourceId = apiResourceId;
Name = name;
}
public override object[] GetKeys()
{
return new object[] { ApiResourceId, Name, Type };
}
}
}

36
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/ApiSecret.cs

@ -0,0 +1,36 @@
using System;
using IdentityServer4;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiSecret : Secret
{
public virtual Guid ApiResourceId { get; protected set; }
protected ApiSecret()
{
}
protected internal ApiSecret(
Guid apiResourceId,
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null
) : base(
value,
expiration,
type,
description)
{
ApiResourceId = apiResourceId;
}
public override object[] GetKeys()
{
return new object[] { ApiResourceId, Type, Value };
}
}
}

28
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ApiResources/IApiResourceRepository.cs

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.ApiResources
{
public interface IApiResourceRepository : IBasicRepository<ApiResource, Guid>
{
Task<ApiResource> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
Task<List<ApiResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<ApiResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default
);
}
}

42
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs

@ -0,0 +1,42 @@
using System.Threading.Tasks;
using System.Security.Principal;
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace Volo.Abp.IdentityServer.AspNetIdentity
{
public class AbpProfileService : ProfileService<IdentityUser>
{
private readonly ICurrentTenant _currentTenant;
public AbpProfileService(
IdentityUserManager userManager,
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
ICurrentTenant currentTenant)
: base(userManager, claimsFactory)
{
_currentTenant = currentTenant;
}
[UnitOfWork]
public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
using (_currentTenant.Change(context.Subject.FindTenantId()))
{
await base.GetProfileDataAsync(context);
}
}
[UnitOfWork]
public override async Task IsActiveAsync(IsActiveContext context)
{
using (_currentTenant.Change(context.Subject.FindTenantId()))
{
await base.IsActiveAsync(context);
}
}
}
}

33
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

@ -0,0 +1,33 @@
using System.Threading.Tasks;
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Volo.Abp.Identity;
using Volo.Abp.Uow;
namespace Volo.Abp.IdentityServer.AspNetIdentity
{
public class AbpResourceOwnerPasswordValidator : ResourceOwnerPasswordValidator<IdentityUser>
{
public AbpResourceOwnerPasswordValidator(
IdentityUserManager userManager,
SignInManager<IdentityUser> signInManager,
IEventService events,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger
) : base(
userManager,
signInManager,
events,
logger)
{
}
[UnitOfWork]
public override async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
await base.ValidateAsync(context);
}
}
}

196
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/Client.cs

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using IdentityServer4;
using IdentityServer4.Models;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
namespace Volo.Abp.IdentityServer.Clients
{
public class Client : AggregateRoot<Guid>
{
public virtual string ClientId { get; set; }
public virtual string ClientName { get; set; }
public virtual string Description { get; set; }
public virtual string ClientUri { get; set; }
public virtual string LogoUri { get; set; }
public virtual bool Enabled { get; set; } = true;
public virtual string ProtocolType { get; set; }
public virtual bool RequireClientSecret { get; set; }
public virtual bool RequireConsent { get; set; }
public virtual bool AllowRememberConsent { get; set; }
public virtual bool AlwaysIncludeUserClaimsInIdToken { get; set; }
public virtual bool RequirePkce { get; set; }
public virtual bool AllowPlainTextPkce { get; set; }
public virtual bool AllowAccessTokensViaBrowser { get; set; }
public virtual string FrontChannelLogoutUri { get; set; }
public virtual bool FrontChannelLogoutSessionRequired { get; set; }
public virtual string BackChannelLogoutUri { get; set; }
public virtual bool BackChannelLogoutSessionRequired { get; set; }
public virtual bool AllowOfflineAccess { get; set; }
public virtual int IdentityTokenLifetime { get; set; }
public virtual int AccessTokenLifetime { get; set; }
public virtual int AuthorizationCodeLifetime { get; set; }
public virtual int? ConsentLifetime { get; set; }
public virtual int AbsoluteRefreshTokenLifetime { get; set; }
public virtual int SlidingRefreshTokenLifetime { get; set; }
public virtual int RefreshTokenUsage { get; set; }
public virtual bool UpdateAccessTokenClaimsOnRefresh { get; set; }
public virtual int RefreshTokenExpiration { get; set; }
public virtual int AccessTokenType { get; set; }
public virtual bool EnableLocalLogin { get; set; }
public virtual bool IncludeJwtId { get; set; }
public virtual bool AlwaysSendClientClaims { get; set; }
public virtual string ClientClaimsPrefix { 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<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; }
protected Client()
{
}
public Client(Guid id, [NotNull] string clientId)
{
Check.NotNull(clientId, nameof(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<ClientScope>();
ClientSecrets = new List<ClientSecret>();
AllowedGrantTypes = new List<ClientGrantType>();
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([NotNull] string grantType)
{
AllowedGrantTypes.Add(new ClientGrantType(Id, grantType));
}
public virtual void AddGrantTypes(IEnumerable<string> grantTypes)
{
AllowedGrantTypes.AddRange(
grantTypes.Select(
grantType => new ClientGrantType(Id, grantType)
)
);
}
public virtual void AddSecret([NotNull] string value, DateTime? expiration = null, string type = IdentityServerConstants.SecretTypes.SharedSecret, string description = null)
{
ClientSecrets.Add(new ClientSecret(Id, value, expiration, type, description));
}
public virtual void AddScope([NotNull] string scope)
{
AllowedScopes.Add(new ClientScope(Id, scope));
}
public virtual void AddCorsOrigin([NotNull] string origin)
{
AllowedCorsOrigins.Add(new ClientCorsOrigin(Id, origin));
}
public virtual void AddRedirectUri([NotNull] string redirectUri)
{
RedirectUris.Add(new ClientRedirectUri(Id, redirectUri));
}
public virtual void AddPostLogoutRedirectUri([NotNull] string postLogoutRedirectUri)
{
PostLogoutRedirectUris.Add(new ClientPostLogoutRedirectUri(Id, postLogoutRedirectUri));
}
public virtual void AddIdentityProviderRestriction([NotNull] string provider)
{
IdentityProviderRestrictions.Add(new ClientIdPRestriction(Id, provider));
}
public virtual void AddProperty([NotNull] string key)
{
Properties.Add(new ClientProperty(Id, key));
}
public virtual void AddClaim(IGuidGenerator guidGenerator, [NotNull] string type, string value)
{
Claims.Add(new ClientClaim(guidGenerator.Create(), Id, type, value));
}
}
}

86
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientAutoMapperProfile.cs

@ -0,0 +1,86 @@
using System.Collections.Generic;
using System.Security.Claims;
using AutoMapper;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientAutoMapperProfile : Profile
{
public ClientAutoMapperProfile()
{
//TODO: Reverse maps will not used probably. Remove those will not used
CreateMap<Client, IdentityServer4.Models.Client>();
CreateMap<ClientCorsOrigin, string>()
.ConstructUsing(src => src.Origin)
.ReverseMap()
.ForMember(dest => dest.Origin, opt => opt.MapFrom(src => src));
CreateMap<ApiResource, IdentityServer4.Models.ApiResource>()
.ForMember(dest => dest.ApiSecrets, opt => opt.MapFrom(src => src.Secrets));
//TODO: Why PersistedGrant mapping is in this profile?
CreateMap<PersistedGrant, IdentityServer4.Models.PersistedGrant>().ReverseMap();
CreateMap<IdentityResource, IdentityServer4.Models.IdentityResource>();
CreateMap<UserClaim, string>()
.ConstructUsing(src => src.Type)
.ReverseMap()
.ForMember(dest => dest.Type, opt => opt.MapFrom(src => src));
CreateMap<ApiSecret, IdentityServer4.Models.Secret>();
CreateMap<ApiScope, IdentityServer4.Models.Scope>();
CreateMap<ClientProperty, KeyValuePair<string, string>>()
.ReverseMap();
CreateMap<Client, IdentityServer4.Models.Client>()
.ForMember(dest => dest.ProtocolType, opt => opt.Condition(srs => srs != null))
.ReverseMap();
CreateMap<ClientCorsOrigin, string>()
.ConstructUsing(src => src.Origin)
.ReverseMap()
.ForMember(dest => dest.Origin, opt => opt.MapFrom(src => src));
CreateMap<ClientIdPRestriction, string>()
.ConstructUsing(src => src.Provider)
.ReverseMap()
.ForMember(dest => dest.Provider, opt => opt.MapFrom(src => src));
CreateMap<ClientClaim, Claim>(MemberList.None)
.ConstructUsing(src => new Claim(src.Type, src.Value))
.ReverseMap();
CreateMap<ClientScope, string>()
.ConstructUsing(src => src.Scope)
.ReverseMap()
.ForMember(dest => dest.Scope, opt => opt.MapFrom(src => src));
CreateMap<ClientPostLogoutRedirectUri, string>()
.ConstructUsing(src => src.PostLogoutRedirectUri)
.ReverseMap()
.ForMember(dest => dest.PostLogoutRedirectUri, opt => opt.MapFrom(src => src));
CreateMap<ClientRedirectUri, string>()
.ConstructUsing(src => src.RedirectUri)
.ReverseMap()
.ForMember(dest => dest.RedirectUri, opt => opt.MapFrom(src => src));
CreateMap<ClientGrantType, string>()
.ConstructUsing(src => src.GrantType)
.ReverseMap()
.ForMember(dest => dest.GrantType, opt => opt.MapFrom(src => src));
CreateMap<ClientSecret, IdentityServer4.Models.Secret>(MemberList.Destination)
.ForMember(dest => dest.Type, opt => opt.Condition(srs => srs != null))
.ReverseMap();
}
}
}

30
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientClaim.cs

@ -0,0 +1,30 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientClaim : Entity<Guid>
{
public virtual Guid ClientId { get; set; }
public virtual string Type { get; set; }
public virtual string Value { get; set; }
protected ClientClaim()
{
}
protected internal ClientClaim(Guid id, Guid clientId, [NotNull] string type, string value)
{
Check.NotNull(type, nameof(type));
Id = id;
ClientId = clientId;
Type = type;
Value = value;
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientCorsOrigin.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientCorsOrigin : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string Origin { get; protected set; }
protected ClientCorsOrigin()
{
}
protected internal ClientCorsOrigin(Guid clientId, [NotNull] string origin)
{
Check.NotNull(origin, nameof(origin));
ClientId = clientId;
Origin = origin;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Origin };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientGrantType.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientGrantType : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string GrantType { get; protected set; }
protected ClientGrantType()
{
}
protected internal ClientGrantType(Guid clientId, [NotNull] string grantType)
{
Check.NotNull(grantType, nameof(grantType));
ClientId = clientId;
GrantType = grantType;
}
public override object[] GetKeys()
{
return new object[] { ClientId, GrantType };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientIdPRestriction.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientIdPRestriction : Entity
{
public virtual Guid ClientId { get; set; }
public virtual string Provider { get; set; }
protected ClientIdPRestriction()
{
}
protected internal ClientIdPRestriction(Guid clientId, [NotNull] string provider)
{
Check.NotNull(provider, nameof(provider));
ClientId = clientId;
Provider = provider;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Provider };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientPostLogoutRedirectUri.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientPostLogoutRedirectUri : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string PostLogoutRedirectUri { get; protected set; }
protected ClientPostLogoutRedirectUri()
{
}
protected internal ClientPostLogoutRedirectUri(Guid clientId, [NotNull] string postLogoutRedirectUri)
{
Check.NotNull(postLogoutRedirectUri, nameof(postLogoutRedirectUri));
ClientId = clientId;
PostLogoutRedirectUri = postLogoutRedirectUri;
}
public override object[] GetKeys()
{
return new object[] { ClientId, PostLogoutRedirectUri };
}
}
}

33
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientProperty.cs

@ -0,0 +1,33 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientProperty : Entity
{
public virtual Guid ClientId { get; set; }
public virtual string Key { get; set; }
public virtual string Value { get; set; }
protected ClientProperty()
{
}
protected internal ClientProperty(Guid clientId, [NotNull] string key)
{
Check.NotNull(key, nameof(key));
ClientId = clientId;
Key = key;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Key };
}
}
}

31
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientRedirectUri.cs

@ -0,0 +1,31 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientRedirectUri : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string RedirectUri { get; protected set; }
protected ClientRedirectUri()
{
}
protected internal ClientRedirectUri(Guid clientId, [NotNull] string redirectUri)
{
Check.NotNull(redirectUri, nameof(redirectUri));
ClientId = clientId;
RedirectUri = redirectUri;
}
public override object[] GetKeys()
{
return new object[] { ClientId, RedirectUri };
}
}
}

28
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientScope.cs

@ -0,0 +1,28 @@
using System;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientScope : Entity
{
public virtual Guid ClientId { get; protected set; }
public virtual string Scope { get; protected set; }
protected ClientScope()
{
}
protected internal ClientScope(Guid clientId, string scope)
{
ClientId = clientId;
Scope = scope;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Scope };
}
}
}

36
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientSecret.cs

@ -0,0 +1,36 @@
using System;
using IdentityServer4;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientSecret : Secret
{
public virtual Guid ClientId { get; protected set; }
protected ClientSecret()
{
}
protected internal ClientSecret(
Guid clientId,
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null
) : base(
value,
expiration,
type,
description)
{
ClientId = clientId;
}
public override object[] GetKeys()
{
return new object[] { ClientId, Type, Value };
}
}
}

24
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientStore.cs

@ -0,0 +1,24 @@
using System.Threading.Tasks;
using IdentityServer4.Stores;
using Volo.Abp.ObjectMapping;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientStore : IClientStore
{
private readonly IClientRepository _clientRepository;
private readonly IObjectMapper _objectMapper;
public ClientStore(IClientRepository clientRepository, IObjectMapper objectMapper)
{
_clientRepository = clientRepository;
_objectMapper = objectMapper;
}
public virtual async Task<IdentityServer4.Models.Client> FindClientByIdAsync(string clientId)
{
var client = await _clientRepository.FindByCliendIdAsync(clientId);
return _objectMapper.Map<Client, IdentityServer4.Models.Client>(client);
}
}
}

17
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/IClientRepository.cs

@ -0,0 +1,17 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.Clients
{
public interface IClientRepository : IBasicRepository<Client, Guid>
{
Task<Client> FindByCliendIdAsync(
[NotNull] string clientId,
bool includeDetails = true,
CancellationToken cancellationToken = default
);
}
}

34
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/IPersistentGrantRepository.cs

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.Grants
{
public interface IPersistentGrantRepository : IBasicRepository<PersistedGrant, Guid>
{
Task<PersistedGrant> FindByKeyAsync(
string key,
CancellationToken cancellationToken = default
);
Task<List<PersistedGrant>> GetListBySubjectIdAsync(
string key,
CancellationToken cancellationToken = default
);
Task DeleteAsync(
string subjectId,
string clientId,
CancellationToken cancellationToken = default
);
Task DeleteAsync(
string subjectId,
string clientId,
string type,
CancellationToken cancellationToken = default
);
}
}

32
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrant.cs

@ -0,0 +1,32 @@
using System;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.Grants
{
public class PersistedGrant : AggregateRoot<Guid>
{
public virtual string Key { get; set; }
public virtual string Type { get; set; }
public virtual string SubjectId { get; set; }
public virtual string ClientId { get; set; }
public virtual DateTime CreationTime { get; set; }
public virtual DateTime? Expiration { get; set; }
public virtual string Data { get; set; }
protected PersistedGrant()
{
}
public PersistedGrant(Guid id)
{
Id = id;
}
}
}

72
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Grants/PersistedGrantStore.cs

@ -0,0 +1,72 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Stores;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.ObjectMapping;
namespace Volo.Abp.IdentityServer.Grants
{
public class PersistedGrantStore : IPersistedGrantStore, ITransientDependency
{
private readonly IPersistentGrantRepository _persistentGrantRepository;
private readonly IObjectMapper _objectMapper;
private readonly IGuidGenerator _guidGenerator;
public PersistedGrantStore(IPersistentGrantRepository persistentGrantRepository, IObjectMapper objectMapper, IGuidGenerator guidGenerator)
{
_persistentGrantRepository = persistentGrantRepository;
_objectMapper = objectMapper;
_guidGenerator = guidGenerator;
}
public virtual async Task StoreAsync(IdentityServer4.Models.PersistedGrant grant)
{
var entity = _objectMapper.Map<IdentityServer4.Models.PersistedGrant, PersistedGrant>(grant);
var existing = await _persistentGrantRepository.FindByKeyAsync(grant.Key);
if (existing == null)
{
entity.Id = _guidGenerator.Create();
await _persistentGrantRepository.InsertAsync(entity);
}
else
{
await _persistentGrantRepository.UpdateAsync(entity);
}
}
public virtual async Task<IdentityServer4.Models.PersistedGrant> GetAsync(string key)
{
var persistedGrant = await _persistentGrantRepository.FindByKeyAsync(key);
return _objectMapper.Map<PersistedGrant, IdentityServer4.Models.PersistedGrant>(persistedGrant);
}
public virtual async Task<IEnumerable<IdentityServer4.Models.PersistedGrant>> GetAllAsync(string subjectId)
{
var persistedGrants = await _persistentGrantRepository.GetListBySubjectIdAsync(subjectId);
return persistedGrants.Select(x => _objectMapper.Map<PersistedGrant, IdentityServer4.Models.PersistedGrant>(x));
}
public virtual async Task RemoveAsync(string key)
{
var persistedGrant = await _persistentGrantRepository.FindByKeyAsync(key);
if (persistedGrant == null)
{
return;
}
await _persistentGrantRepository.DeleteAsync(persistedGrant);
}
public virtual async Task RemoveAllAsync(string subjectId, string clientId)
{
await _persistentGrantRepository.DeleteAsync(subjectId, clientId);
}
public virtual async Task RemoveAllAsync(string subjectId, string clientId, string type)
{
await _persistentGrantRepository.DeleteAsync(subjectId, clientId, type);
}
}
}

22
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IIdentityResourceRepository.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.IdentityServer.IdentityResources
{
public interface IIdentityResourceRepository : IBasicRepository<IdentityResource, Guid>
{
Task<List<IdentityResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default
);
Task<List<IdentityResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default
);
}
}

26
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityClaim.cs

@ -0,0 +1,26 @@
using System;
using JetBrains.Annotations;
namespace Volo.Abp.IdentityServer.IdentityResources
{
public class IdentityClaim : UserClaim
{
public virtual Guid IdentityResourceId { get; set; }
protected IdentityClaim()
{
}
protected internal IdentityClaim(Guid identityResourceId, [NotNull] string type)
: base(type)
{
IdentityResourceId = identityResourceId;
}
public override object[] GetKeys()
{
return new object[] { IdentityResourceId, Type };
}
}
}

60
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/IdentityResources/IdentityResource.cs

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer.IdentityResources
{
public class IdentityResource : AggregateRoot<Guid>
{
public virtual string Name { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual bool Enabled { get; set; }
public virtual bool Required { get; set; }
public virtual bool Emphasize { get; set; }
public virtual bool ShowInDiscoveryDocument { get; set; }
public virtual List<IdentityClaim> UserClaims { get; set; }
protected IdentityResource()
{
}
public IdentityResource(
Guid id,
[NotNull] string name,
string displayName = null,
string description = null,
bool enabled = true,
bool required = false,
bool emphasize = false,
bool showInDiscoveryDocument = true)
{
Check.NotNull(name, nameof(name));
Id = id;
Name = name;
DisplayName = displayName;
Description = description;
Enabled = enabled;
Required = required;
Emphasize = emphasize;
ShowInDiscoveryDocument = showInDiscoveryDocument;
UserClaims = new List<IdentityClaim>();
}
public virtual void AddUserClaim([NotNull] string type)
{
UserClaims.Add(new IdentityClaim(Id, type));
}
}
}

27
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Jwt/JwtTokenMiddleware.cs

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
namespace Volo.Abp.IdentityServer.Jwt
{
//TODO: Should we move this to another package..?
public static class JwtTokenMiddleware
{
public static IApplicationBuilder UseJwtTokenMiddleware(this IApplicationBuilder app, string schema)
{
return app.Use(async (ctx, next) =>
{
if (ctx.User.Identity?.IsAuthenticated != true)
{
var result = await ctx.AuthenticateAsync(schema);
if (result.Succeeded && result.Principal != null)
{
ctx.User = result.Principal;
}
}
await next();
});
}
}
}

59
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/ResourceStore.cs

@ -0,0 +1,59 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.ObjectMapping;
using ApiResource = IdentityServer4.Models.ApiResource;
using IdentityResource = Volo.Abp.IdentityServer.IdentityResources.IdentityResource;
namespace Volo.Abp.IdentityServer
{
public class ResourceStore : IResourceStore
{
private readonly IIdentityResourceRepository _identityResourceRepository;
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IObjectMapper _objectMapper;
public ResourceStore(
IIdentityResourceRepository identityResourceRepository,
IObjectMapper objectMapper,
IApiResourceRepository apiResourceRepository)
{
_identityResourceRepository = identityResourceRepository;
_objectMapper = objectMapper;
_apiResourceRepository = apiResourceRepository;
}
public virtual async Task<IEnumerable<IdentityServer4.Models.IdentityResource>> FindIdentityResourcesByScopeAsync(IEnumerable<string> scopeNames)
{
var resource = await _identityResourceRepository.GetListByScopesAsync(scopeNames.ToArray(), includeDetails: true);
return _objectMapper.Map<List<IdentityResource>, List<IdentityServer4.Models.IdentityResource>>(resource);
}
public virtual async Task<IEnumerable<ApiResource>> FindApiResourcesByScopeAsync(IEnumerable<string> scopeNames)
{
var resources = await _apiResourceRepository.GetListByScopesAsync(scopeNames.ToArray(), includeDetails: true);
return resources.Select(x => _objectMapper.Map<ApiResources.ApiResource, ApiResource>(x));
}
public virtual async Task<ApiResource> FindApiResourceAsync(string name)
{
var resource = await _apiResourceRepository.FindByNameAsync(name);
return _objectMapper.Map<ApiResources.ApiResource, ApiResource>(resource);
}
public virtual async Task<Resources> GetAllResourcesAsync()
{
var identityResources = await _identityResourceRepository.GetListAsync(includeDetails: true);
var apiResources = await _apiResourceRepository.GetListAsync(includeDetails: true);
return new Resources(
_objectMapper.Map<List<IdentityResource>, IdentityServer4.Models.IdentityResource[]>(identityResources),
_objectMapper.Map<List<ApiResources.ApiResource>, ApiResource[]>(apiResources)
);
}
}
}

37
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Secret.cs

@ -0,0 +1,37 @@
using System;
using IdentityServer4;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer
{
public abstract class Secret : Entity
{
public virtual string Type { get; protected set; }
public virtual string Value { get; set; }
public virtual string Description { get; set; }
public virtual DateTime? Expiration { get; set; }
protected Secret()
{
}
protected Secret(
[NotNull] string value,
DateTime? expiration = null,
string type = IdentityServerConstants.SecretTypes.SharedSecret,
string description = null)
{
Check.NotNull(value, nameof(value));
Value = value;
Expiration = expiration;
Type = type;
Description = description;
}
}
}

37
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Temp/IdentityServerConfig.cs

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

22
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/UserClaim.cs

@ -0,0 +1,22 @@
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.IdentityServer
{
public abstract class UserClaim : Entity
{
public virtual string Type { get; protected set; }
protected UserClaim()
{
}
protected UserClaim([NotNull] string type)
{
Check.NotNull(type, nameof(type));
Type = type;
}
}
}

22
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.EntityFrameworkCore</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.EntityFrameworkCore</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.IdentityServer.Domain\Volo.Abp.IdentityServer.Domain.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.EntityFrameworkCore\Volo.Abp.EntityFrameworkCore.csproj" />
</ItemGroup>
</Project>

2
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo.Abp.IdentityServer.EntityFrameworkCore.csproj.DotSettings

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp71</s:String></wpf:ResourceDictionary>

55
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/AbpIdentityServerEfCoreQueryableExtensions.cs

@ -0,0 +1,55 @@
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer
{
public static class AbpIdentityServerEfCoreQueryableExtensions
{
public static IQueryable<ApiResource> IncludeDetails(this IQueryable<ApiResource> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
.Include(x => x.Secrets)
.Include(x => x.UserClaims)
.Include(x => x.Scopes)
.ThenInclude(s => s.UserClaims);
}
public static IQueryable<IdentityResource> IncludeDetails(this IQueryable<IdentityResource> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
.Include(x => x.UserClaims);
}
public static IQueryable<Client> IncludeDetails(this IQueryable<Client> queryable, bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
.Include(x => x.AllowedGrantTypes)
.Include(x => x.RedirectUris)
.Include(x => x.PostLogoutRedirectUris)
.Include(x => x.AllowedScopes)
.Include(x => x.ClientSecrets)
.Include(x => x.Claims)
.Include(x => x.IdentityProviderRestrictions)
.Include(x => x.AllowedCorsOrigins)
.Include(x => x.Properties);
}
}
}

59
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/ApiResources/ApiResourceRepository.cs

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
namespace Volo.Abp.IdentityServer.ApiResources
{
public class ApiResourceRepository : EfCoreRepository<IIdentityServerDbContext, ApiResource, Guid>, IApiResourceRepository
{
public ApiResourceRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<ApiResource> FindByNameAsync(
string name,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
var query = from apiResource in DbSet.IncludeDetails(includeDetails)
where apiResource.Name == name
select apiResource;
return await query
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<ApiResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var query = from api in DbSet.IncludeDetails(includeDetails)
where api.Scopes.Any(x => scopeNames.Contains(x.Name))
select api;
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<ApiResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await DbSet
.IncludeDetails(includeDetails)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public override IQueryable<ApiResource> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

34
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Clients/ClientRepository.cs

@ -0,0 +1,34 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientRepository : EfCoreRepository<IIdentityServerDbContext, Client, Guid>, IClientRepository
{
public ClientRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public virtual async Task<Client> FindByCliendIdAsync(
string clientId,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await DbSet
.IncludeDetails(includeDetails)
.FirstOrDefaultAsync(x => x.ClientId == clientId, GetCancellationToken(cancellationToken));
}
public override IQueryable<Client> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

28
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/AbpIdentityServerEntityFrameworkCoreModule.cs

@ -0,0 +1,28 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.Modularity;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
[DependsOn(typeof(AbpIdentityServerDomainModule))]
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class AbpIdentityServerEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<IdentityServerDbContext>(options =>
{
options.AddDefaultRepositories<IIdentityServerDbContext>();
options.AddRepository<Client, ClientRepository>();
options.AddRepository<ApiResource, ApiResourceRepository>();
options.AddRepository<IdentityResource, IdentityResourceRepository>();
options.AddRepository<PersistedGrant, PersistentGrantRepository>();
});
}
}
}

50
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IIdentityServerDbContext.cs

@ -0,0 +1,50 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
[ConnectionStringName("AbpIdentityServer")]
public interface IIdentityServerDbContext : IEfCoreDbContext
{
DbSet<ApiResource> ApiResources { get; set; }
DbSet<ApiSecret> ApiSecrets { get; set; }
DbSet<ApiResourceClaim> ApiResourceClaims { get; set; }
DbSet<ApiScope> ApiScopes { get; set; }
DbSet<ApiScopeClaim> ApiScopeClaims { get; set; }
DbSet<IdentityResource> IdentityResources { get; set; }
DbSet<IdentityClaim> IdentityClaims { get; set; }
DbSet<Client> Clients { get; set; }
DbSet<ClientGrantType> ClientGrantTypes { get; set; }
DbSet<ClientRedirectUri> ClientRedirectUris { get; set; }
DbSet<ClientPostLogoutRedirectUri> ClientPostLogoutRedirectUris { get; set; }
DbSet<ClientScope> ClientScopes { get; set; }
DbSet<ClientSecret> ClientSecrets { get; set; }
DbSet<ClientClaim> ClientClaims { get; set; }
DbSet<ClientIdPRestriction> ClientIdPRestrictions { get; set; }
DbSet<ClientCorsOrigin> ClientCorsOrigins { get; set; }
DbSet<ClientProperty> ClientProperties { get; set; }
DbSet<PersistedGrant> PersistedGrants { get; set; }
}
}

66
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContext.cs

@ -0,0 +1,66 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
[ConnectionStringName("AbpIdentityServer")]
public class IdentityServerDbContext : AbpDbContext<IdentityServerDbContext>, IIdentityServerDbContext
{
public static string TablePrefix { get; set; } = AbpIdentityServerConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = AbpIdentityServerConsts.DefaultDbSchema;
public DbSet<ApiResource> ApiResources { get; set; }
public DbSet<ApiSecret> ApiSecrets { get; set; }
public DbSet<ApiResourceClaim> ApiResourceClaims { get; set; }
public DbSet<ApiScope> ApiScopes { get; set; }
public DbSet<ApiScopeClaim> ApiScopeClaims { get; set; }
public DbSet<IdentityResource> IdentityResources { get; set; }
public DbSet<IdentityClaim> IdentityClaims { get; set; }
public DbSet<Client> Clients { get; set; }
public DbSet<ClientGrantType> ClientGrantTypes { get; set; }
public DbSet<ClientRedirectUri> ClientRedirectUris { get; set; }
public DbSet<ClientPostLogoutRedirectUri> ClientPostLogoutRedirectUris { get; set; }
public DbSet<ClientScope> ClientScopes { get; set; }
public DbSet<ClientSecret> ClientSecrets { get; set; }
public DbSet<ClientClaim> ClientClaims { get; set; }
public DbSet<ClientIdPRestriction> ClientIdPRestrictions { get; set; }
public DbSet<ClientCorsOrigin> ClientCorsOrigins { get; set; }
public DbSet<ClientProperty> ClientProperties { get; set; }
public DbSet<PersistedGrant> PersistedGrants { get; set; }
public IdentityServerDbContext(DbContextOptions<IdentityServerDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureIdentityServer(TablePrefix, Schema);
}
}
}

228
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs

@ -0,0 +1,228 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
{
public static class IdentityServerDbContextModelCreatingExtensions
{
public static void ConfigureIdentityServer(
this ModelBuilder builder,
[CanBeNull] string tablePrefix = AbpIdentityServerConsts.DefaultDbTablePrefix,
[CanBeNull] string schema = AbpIdentityServerConsts.DefaultDbSchema)
{
Check.NotNull(builder, nameof(builder));
if (tablePrefix == null)
{
tablePrefix = "";
}
builder.Entity<Client>(client =>
{
client.ToTable(tablePrefix + "Clients", schema);
client.Property(x => x.ClientId).HasMaxLength(ClientConsts.ClientIdMaxLength).IsRequired();
client.Property(x => x.ProtocolType).HasMaxLength(ClientConsts.ProtocolTypeMaxLength).IsRequired();
client.Property(x => x.ClientName).HasMaxLength(ClientConsts.ClientNameMaxLength);
client.Property(x => x.ClientUri).HasMaxLength(ClientConsts.ClientUriMaxLength);
client.Property(x => x.LogoUri).HasMaxLength(ClientConsts.LogoUriMaxLength);
client.Property(x => x.Description).HasMaxLength(ClientConsts.DescriptionMaxLength);
client.Property(x => x.FrontChannelLogoutUri).HasMaxLength(ClientConsts.FrontChannelLogoutUriMaxLength);
client.Property(x => x.BackChannelLogoutUri).HasMaxLength(ClientConsts.BackChannelLogoutUriMaxLength);
client.Property(x => x.ClientClaimsPrefix).HasMaxLength(ClientConsts.ClientClaimsPrefixMaxLength);
client.Property(x => x.PairWiseSubjectSalt).HasMaxLength(ClientConsts.PairWiseSubjectSaltMaxLength);
client.HasMany(x => x.AllowedScopes).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.ClientSecrets).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.AllowedGrantTypes).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.AllowedCorsOrigins).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.RedirectUris).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.PostLogoutRedirectUris).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.IdentityProviderRestrictions).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.Claims).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasMany(x => x.Properties).WithOne().HasForeignKey(x => x.ClientId).IsRequired();
client.HasIndex(x => x.ClientId).IsUnique();
});
builder.Entity<ClientGrantType>(grantType =>
{
grantType.ToTable(tablePrefix + "ClientGrantTypes", schema);
grantType.HasKey(x => new { x.ClientId, x.GrantType });
grantType.Property(x => x.GrantType).HasMaxLength(ClientGrantTypeConsts.GrantTypeMaxLength).IsRequired();
});
builder.Entity<ClientRedirectUri>(redirectUri =>
{
redirectUri.ToTable(tablePrefix + "ClientRedirectUris", schema);
redirectUri.HasKey(x => new { x.ClientId, x.RedirectUri });
redirectUri.Property(x => x.RedirectUri).HasMaxLength(ClientRedirectUriConsts.RedirectUriMaxLength).IsRequired();
});
builder.Entity<ClientPostLogoutRedirectUri>(postLogoutRedirectUri =>
{
postLogoutRedirectUri.ToTable(tablePrefix + "ClientPostLogoutRedirectUris", schema);
postLogoutRedirectUri.HasKey(x => new { x.ClientId, x.PostLogoutRedirectUri });
postLogoutRedirectUri.Property(x => x.PostLogoutRedirectUri).HasMaxLength(ClientPostLogoutRedirectUriConsts.PostLogoutRedirectUriMaxLength).IsRequired();
});
builder.Entity<ClientScope>(scope =>
{
scope.ToTable(tablePrefix + "ClientScopes", schema);
scope.HasKey(x => new { x.ClientId, x.Scope });
scope.Property(x => x.Scope).HasMaxLength(ClientScopeConsts.ScopeMaxLength).IsRequired();
});
builder.Entity<ClientSecret>(secret =>
{
secret.ToTable(tablePrefix + "ClientSecrets", schema);
secret.HasKey(x => new { x.ClientId, x.Type, x.Value });
secret.Property(x => x.Type).HasMaxLength(SecretConsts.TypeMaxLength).IsRequired();
secret.Property(x => x.Value).HasMaxLength(SecretConsts.ValueMaxLength).IsRequired();
secret.Property(x => x.Description).HasMaxLength(SecretConsts.DescriptionMaxLength);
});
builder.Entity<ClientClaim>(claim =>
{
claim.ToTable(tablePrefix + "ClientClaims", schema);
claim.Property(x => x.Type).HasMaxLength(ClientClaimConsts.TypeMaxLength).IsRequired();
claim.Property(x => x.Value).HasMaxLength(ClientClaimConsts.ValueMaxLength).IsRequired();
});
builder.Entity<ClientIdPRestriction>(idPRestriction =>
{
idPRestriction.ToTable(tablePrefix + "ClientIdPRestrictions", schema);
idPRestriction.HasKey(x => new { x.ClientId, x.Provider });
idPRestriction.Property(x => x.Provider).HasMaxLength(ClientIdPRestrictionConsts.ProviderMaxLength).IsRequired();
});
builder.Entity<ClientCorsOrigin>(corsOrigin =>
{
corsOrigin.ToTable(tablePrefix + "ClientCorsOrigins", schema);
corsOrigin.HasKey(x => new { x.ClientId, x.Origin });
corsOrigin.Property(x => x.Origin).HasMaxLength(ClientCorsOriginConsts.OriginMaxLength).IsRequired();
});
builder.Entity<ClientProperty>(property =>
{
property.ToTable(tablePrefix + "ClientProperties", schema);
property.HasKey(x => new { x.ClientId, x.Key });
property.Property(x => x.Key).HasMaxLength(ClientPropertyConsts.KeyMaxLength).IsRequired();
property.Property(x => x.Value).HasMaxLength(ClientPropertyConsts.ValueMaxLength).IsRequired();
});
builder.Entity<PersistedGrant>(grant =>
{
grant.ToTable(tablePrefix + "PersistedGrants", schema);
grant.Property(x => x.Key).HasMaxLength(PersistedGrantConsts.KeyMaxLength).ValueGeneratedNever();
grant.Property(x => x.Type).HasMaxLength(PersistedGrantConsts.TypeMaxLength).IsRequired();
grant.Property(x => x.SubjectId).HasMaxLength(PersistedGrantConsts.SubjectIdMaxLength);
grant.Property(x => x.ClientId).HasMaxLength(PersistedGrantConsts.ClientIdMaxLength).IsRequired();
grant.Property(x => x.CreationTime).IsRequired();
grant.Property(x => x.Data).IsRequired();
grant.HasKey(x => x.Key); //TODO: What about Id!!!
grant.HasIndex(x => new { x.SubjectId, x.ClientId, x.Type });
});
builder.Entity<IdentityResource>(identityResource =>
{
identityResource.ToTable(tablePrefix + "IdentityResources", schema);
identityResource.Property(x => x.Name).HasMaxLength(IdentityResourceConsts.NameMaxLength).IsRequired();
identityResource.Property(x => x.DisplayName).HasMaxLength(IdentityResourceConsts.DisplayNameMaxLength);
identityResource.Property(x => x.Description).HasMaxLength(IdentityResourceConsts.DescriptionMaxLength);
identityResource.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.IdentityResourceId).IsRequired();
});
builder.Entity<IdentityClaim>(claim =>
{
claim.ToTable(tablePrefix + "IdentityClaims", schema);
claim.HasKey(x => new { x.IdentityResourceId, x.Type });
claim.Property(x => x.Type).HasMaxLength(UserClaimConsts.TypeMaxLength).IsRequired();
});
builder.Entity<ApiResource>(apiResource =>
{
apiResource.ToTable(tablePrefix + "ApiResources", schema);
apiResource.Property(x => x.Name).HasMaxLength(ApiResourceConsts.NameMaxLength).IsRequired();
apiResource.Property(x => x.DisplayName).HasMaxLength(ApiResourceConsts.DisplayNameMaxLength);
apiResource.Property(x => x.Description).HasMaxLength(ApiResourceConsts.DescriptionMaxLength);
apiResource.HasMany(x => x.Secrets).WithOne().HasForeignKey(x => x.ApiResourceId).IsRequired();
apiResource.HasMany(x => x.Scopes).WithOne().HasForeignKey(x => x.ApiResourceId).IsRequired();
apiResource.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => x.ApiResourceId).IsRequired();
});
builder.Entity<ApiSecret>(apiSecret =>
{
apiSecret.ToTable(tablePrefix + "ApiSecrets", schema);
apiSecret.HasKey(x => new { x.ApiResourceId, x.Type, x.Value });
apiSecret.Property(x => x.Type).HasMaxLength(SecretConsts.TypeMaxLength).IsRequired();
apiSecret.Property(x => x.Value).HasMaxLength(SecretConsts.ValueMaxLength).IsRequired();
apiSecret.Property(x => x.Description).HasMaxLength(SecretConsts.DescriptionMaxLength);
});
builder.Entity<ApiResourceClaim>(apiClaim =>
{
apiClaim.ToTable(tablePrefix + "ApiClaims", schema);
apiClaim.HasKey(x => new { x.ApiResourceId, x.Type });
apiClaim.Property(x => x.Type).HasMaxLength(UserClaimConsts.TypeMaxLength).IsRequired();
});
builder.Entity<ApiScope>(apiScope =>
{
apiScope.ToTable(tablePrefix + "ApiScopes", schema);
apiScope.HasKey(x => new { x.ApiResourceId, x.Name });
apiScope.Property(x => x.Name).HasMaxLength(ApiScopeConsts.NameMaxLength).IsRequired();
apiScope.Property(x => x.DisplayName).HasMaxLength(ApiScopeConsts.DisplayNameMaxLength);
apiScope.Property(x => x.Description).HasMaxLength(ApiScopeConsts.DescriptionMaxLength);
apiScope.HasMany(x => x.UserClaims).WithOne().HasForeignKey(x => new { x.ApiResourceId, x.Name }).IsRequired();
});
builder.Entity<ApiScopeClaim>(apiScopeClaim =>
{
apiScopeClaim.ToTable(tablePrefix + "ApiScopeClaims", schema);
apiScopeClaim.HasKey(x => new { x.ApiResourceId, x.Name, x.Type });
apiScopeClaim.Property(x => x.Type).HasMaxLength(UserClaimConsts.TypeMaxLength).IsRequired();
apiScopeClaim.Property(x => x.Name).HasMaxLength(ApiScopeConsts.NameMaxLength).IsRequired();
});
}
}
}

60
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/Grants/PersistedGrantRepository.cs

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
namespace Volo.Abp.IdentityServer.Grants
{
public class PersistentGrantRepository : EfCoreRepository<IIdentityServerDbContext, PersistedGrant, Guid>, IPersistentGrantRepository
{
public PersistentGrantRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider) : base(dbContextProvider)
{
}
public Task<PersistedGrant> FindByKeyAsync(
string key,
CancellationToken cancellationToken = default)
{
return DbSet
.FirstOrDefaultAsync(x => x.Key == key, GetCancellationToken(cancellationToken));
}
public Task<List<PersistedGrant>> GetListBySubjectIdAsync(
string subjectId,
CancellationToken cancellationToken = default)
{
return DbSet
.Where(x => x.SubjectId == subjectId)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task DeleteAsync(
string subjectId,
string clientId,
CancellationToken cancellationToken = default)
{
await DeleteAsync(
x => x.SubjectId == subjectId && x.ClientId == clientId,
cancellationToken: GetCancellationToken(cancellationToken)
);
}
public async Task DeleteAsync(
string subjectId,
string clientId,
string type,
CancellationToken cancellationToken = default)
{
await DeleteAsync(
x => x.SubjectId == subjectId && x.ClientId == clientId && x.Type == type,
cancellationToken: GetCancellationToken(cancellationToken)
);
}
}
}

47
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/IdentityResources/IdentityResourceRepository.cs

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
namespace Volo.Abp.IdentityServer.IdentityResources
{
public class IdentityResourceRepository : EfCoreRepository<IIdentityServerDbContext, IdentityResource, Guid>, IIdentityResourceRepository
{
public IdentityResourceRepository(IDbContextProvider<IIdentityServerDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<List<IdentityResource>> GetListByScopesAsync(
string[] scopeNames,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
var query = from identityResource in DbSet.IncludeDetails(includeDetails)
where scopeNames.Contains(identityResource.Name)
select identityResource;
return await query.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<List<IdentityResource>> GetListAsync(
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return await DbSet
.IncludeDetails(includeDetails)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public override IQueryable<IdentityResource> WithDetails()
{
return GetQueryable().IncludeDetails();
}
}
}

33
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests.csproj

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>Volo.Abp.IdentityServer.EntityFrameworkCore.Tests</AssemblyName>
<PackageId>Volo.Abp.IdentityServer.EntityFrameworkCore.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.IdentityServer.EntityFrameworkCore\Volo.Abp.IdentityServer.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\modules\identity\src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\..\..\..\abp\framework\src\Volo.Abp.TestBase\Volo.Abp.TestBase.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.1.0" />
<PackageReference Include="NSubstitute" Version="3.1.0" />
<PackageReference Include="Shouldly" Version="3.0.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.extensibility.execution" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
</ItemGroup>
</Project>

10
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityApplicationTestBase.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerTestBase : AbpIntegratedTest<AbpIdentityServerTestEntityFrameworkCoreModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

129
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs

@ -0,0 +1,129 @@
using IdentityServer4.Models;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
using Client = Volo.Abp.IdentityServer.Clients.Client;
using IdentityResource = Volo.Abp.IdentityServer.IdentityResources.IdentityResource;
using PersistedGrant = Volo.Abp.IdentityServer.Grants.PersistedGrant;
namespace Volo.Abp.IdentityServer
{
public class AbpIdentityServerTestDataBuilder : ITransientDependency
{
private readonly IGuidGenerator _guidGenerator;
private readonly IClientRepository _clientRepository;
private readonly IPersistentGrantRepository _persistentGrantRepository;
private readonly IApiResourceRepository _apiResourceRepository;
private readonly IIdentityResourceRepository _identityResourceRepository;
public AbpIdentityServerTestDataBuilder(
IClientRepository clientRepository,
IGuidGenerator guidGenerator,
IPersistentGrantRepository persistentGrantRepository,
IApiResourceRepository apiResourceRepository,
IIdentityResourceRepository identityResourceRepository)
{
_clientRepository = clientRepository;
_guidGenerator = guidGenerator;
_persistentGrantRepository = persistentGrantRepository;
_apiResourceRepository = apiResourceRepository;
_identityResourceRepository = identityResourceRepository;
}
public void Build()
{
AddClients();
AddPersistentGrants();
AddApiResources();
AddIdentityResources();
}
private void AddClients()
{
var client42 = new Client(_guidGenerator.Create(), "42")
{
ProtocolType = "TestProtocol-42"
};
client42.AddCorsOrigin("Origin1");
client42.AddScope("api1");
_clientRepository.Insert(client42);
}
private void AddPersistentGrants()
{
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "38",
ClientId = "TestClientId-38",
Type = "TestType-38",
SubjectId = "TestSubject",
Data = "TestData-38"
});
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "37",
ClientId = "TestClientId-37",
Type = "TestType-37",
SubjectId = "TestSubject",
Data = "TestData-37"
});
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "36",
ClientId = "TestClientId-X",
Type = "TestType-36",
SubjectId = "TestSubject-X",
Data = "TestData-36"
});
_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())
{
Key = "35",
ClientId = "TestClientId-X",
Type = "TestType-35",
SubjectId = "TestSubject-X",
Data = "TestData-35"
});
}
private void AddApiResources()
{
var apiResource = new ApiResource(_guidGenerator.Create(), "Test-ApiResource-Name-1")
{
Enabled = true,
Description = "Test-ApiResource-Description-1",
DisplayName = "Test-ApiResource-DisplayName-1"
};
apiResource.AddSecret("secret".Sha256());
apiResource.AddScope("Test-ApiResource-ApiScope-Name-1", "Test-ApiResource-ApiScope-DisplayName-1");
apiResource.AddUserClaim("Test-ApiResource-Claim-Type-1");
_apiResourceRepository.Insert(apiResource);
}
private void AddIdentityResources()
{
var identityResource = new IdentityResource(_guidGenerator.Create(), "Test-Identity-Resource-Name-1")
{
Description = "Test-Identity-Resource-Description-1",
DisplayName = "Test-Identity-Resource-DisplayName-1",
Required = true,
Emphasize = true
};
identityResource.AddUserClaim("Test-Identity-Resource-1-IdentityClaim-Type-1");
_identityResourceRepository.Insert(identityResource);
}
}
}

53
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/AbpIdentityServerTestEntityFrameworkCoreModule.cs

@ -0,0 +1,53 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Autofac;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Modularity;
using Volo.Abp.Uow;
namespace Volo.Abp.IdentityServer
{
[DependsOn(typeof(AbpAutofacModule))]
[DependsOn(typeof(AbpIdentityServerEntityFrameworkCoreModule))]
[DependsOn(typeof(AbpIdentityEntityFrameworkCoreModule))]
public class AbpIdentityServerTestEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddEntityFrameworkInMemoryDatabase();
var databaseName = Guid.NewGuid().ToString();
context.Services.Configure<AbpDbContextOptions>(options =>
{
options.Configure(abpDbContextConfigurationContext =>
{
abpDbContextConfigurationContext.DbContextOptions.UseInMemoryDatabase(databaseName);
});
});
context.Services.Configure<UnitOfWorkDefaultOptions>(options =>
{
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
SeedTestData(context);
}
private static void SeedTestData(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())
{
scope.ServiceProvider
.GetRequiredService<AbpIdentityServerTestDataBuilder>()
.Build();
}
}
}
}

39
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs

@ -0,0 +1,39 @@
using System.Threading.Tasks;
using IdentityServer4.Stores;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Xunit;
namespace Volo.Abp.IdentityServer.Clients
{
public class ClientStore_Tests : AbpIdentityServerTestBase
{
private readonly IClientStore _clientStore;
public ClientStore_Tests()
{
_clientStore = ServiceProvider.GetRequiredService<IClientStore>();
}
[Fact]
public async Task FindClientByIdAsync_Should_Return_Null_If_Not_Found()
{
var client = await _clientStore.FindClientByIdAsync("non-existing-id");
client.ShouldBeNull();
}
[Fact]
public async Task FindClientByIdAsync_Should_Return_The_Client_If_Found()
{
//Act
var client = await _clientStore.FindClientByIdAsync("42");
//Assert
client.ShouldNotBeNull();
client.ClientId.ShouldBe("42");
client.ProtocolType.ShouldBe("TestProtocol-42");
client.AllowedCorsOrigins.ShouldContain("Origin1");
client.AllowedScopes.ShouldContain("api1");
}
}
}

90
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs

@ -0,0 +1,90 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Xunit;
namespace Volo.Abp.IdentityServer.Clients
{
public class IdentityResourceStore_Tests : AbpIdentityServerTestBase
{
private readonly IResourceStore _resourceStore;
public IdentityResourceStore_Tests()
{
_resourceStore = ServiceProvider.GetRequiredService<IResourceStore>();
}
[Fact]
public async Task FindApiResourceAsync_Should_Return_Null_If_Not_Found()
{
//Act
var resource = await _resourceStore.FindApiResourceAsync("non-existing-name");
//Assert
resource.ShouldBeNull();
}
[Fact]
public async Task FindApiResourceAsync_Should_Return_If_Found()
{
//Act
var apiResource = await _resourceStore.FindApiResourceAsync("Test-ApiResource-Name-1");
//Assert
apiResource.ShouldNotBe(null);
apiResource.Name.ShouldBe("Test-ApiResource-Name-1");
apiResource.Description.ShouldBe("Test-ApiResource-Description-1");
apiResource.DisplayName.ShouldBe("Test-ApiResource-DisplayName-1");
}
[Fact]
public async Task FindApiResourcesByScopeAsync_Should_Return_If_Found()
{
//Act
var apiResources = (await _resourceStore.FindApiResourcesByScopeAsync(new List<string>
{
"Test-ApiResource-ApiScope-Name-1"
})).ToList();
//Assert
apiResources.ShouldNotBe(null);
apiResources[0].Scopes.Count.ShouldBe(2);
}
[Fact]
public async Task FindIdentityResourcesByScopeAsync_Should_Return_For_Given_Scopes()
{
//Act
var identityResourcesByScope = await _resourceStore.FindIdentityResourcesByScopeAsync(new List<string>
{
"Test-Identity-Resource-Name-1"
});
//Assert
var resourcesByScope = identityResourcesByScope as IdentityResource[] ?? identityResourcesByScope.ToArray();
resourcesByScope.Length.ShouldBe(1);
resourcesByScope.First().DisplayName.ShouldBe("Test-Identity-Resource-DisplayName-1");
resourcesByScope.First().Description.ShouldBe("Test-Identity-Resource-Description-1");
resourcesByScope.First().Required.ShouldBe(true);
}
[Fact]
public async Task GetAllResourcesAsync_Should_Return()
{
//Act
var resources = await _resourceStore.GetAllResourcesAsync();
//Assert
resources.ShouldNotBe(null);
resources.ApiResources.Count.ShouldBe(1);
resources.ApiResources.First().Name.ShouldBe("Test-ApiResource-Name-1");
resources.IdentityResources.First().Name.ShouldBe("Test-Identity-Resource-Name-1");
resources.IdentityResources.First().Required.ShouldBe(true);
}
}
}

130
modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs

@ -0,0 +1,130 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Xunit;
namespace Volo.Abp.IdentityServer.Clients
{
public class PersistentGrantStore_Tests : AbpIdentityServerTestBase
{
private readonly IPersistedGrantStore _persistedGrantStore;
public PersistentGrantStore_Tests()
{
_persistedGrantStore = ServiceProvider.GetRequiredService<IPersistedGrantStore>();
}
[Fact]
public async Task FindClientByIdAsync_Should_Return_Null_If_Not_Found()
{
var persistentGrant = await _persistedGrantStore.GetAsync("not-existing-id");
persistentGrant.ShouldBeNull();
}
[Fact]
public async Task FindPersistentGrantByIdAsync_Should_Return_The_PersistentGrant_If_Found()
{
//Act
var client = await _persistedGrantStore.GetAsync("38");
//Assert
client.ShouldNotBeNull();
client.ClientId.ShouldBe("TestClientId-38");
client.SubjectId.ShouldBe("TestSubject");
client.Data.ShouldContain("TestData-38");
client.Type.ShouldContain("TestType-38");
}
[Fact]
public async Task StoreAsync_Should_Store_PersistedGrant()
{
//Act
await _persistedGrantStore.StoreAsync(new PersistedGrant
{
Key = "39",
ClientId = "TestClientId-39",
Type = "TestType-39",
SubjectId = "TestSubject",
Data = "TestData-39",
Expiration = new DateTime(2018, 1, 6, 21, 22, 23),
CreationTime = new DateTime(2018, 1, 5, 19, 20, 21)
});
//Assert
var persistedGrant = await _persistedGrantStore.GetAsync("39");
persistedGrant.Key.ShouldBe("39");
persistedGrant.ClientId.ShouldBe("TestClientId-39");
persistedGrant.Type.ShouldBe("TestType-39");
persistedGrant.SubjectId.ShouldBe("TestSubject");
persistedGrant.Data.ShouldBe("TestData-39");
persistedGrant.Expiration.HasValue.ShouldBe(true);
persistedGrant.Expiration.Value.Year.ShouldBe(2018);
persistedGrant.Expiration.Value.Month.ShouldBe(1);
persistedGrant.Expiration.Value.Day.ShouldBe(6);
persistedGrant.Expiration.Value.Hour.ShouldBe(21);
persistedGrant.Expiration.Value.Minute.ShouldBe(22);
persistedGrant.Expiration.Value.Second.ShouldBe(23);
persistedGrant.CreationTime.Year.ShouldBe(2018);
persistedGrant.CreationTime.Month.ShouldBe(1);
persistedGrant.CreationTime.Day.ShouldBe(5);
persistedGrant.CreationTime.Hour.ShouldBe(19);
persistedGrant.CreationTime.Minute.ShouldBe(20);
persistedGrant.CreationTime.Second.ShouldBe(21);
}
[Fact]
public async Task GetAllAsync_Should_Get_All_PersistedGrants_For_A_Given_SubjectId()
{
//Act
var persistentGrants = await _persistedGrantStore.GetAllAsync("TestSubject");
//Assert
var persistedGrants = persistentGrants as PersistedGrant[] ?? persistentGrants.ToArray();
persistedGrants.ShouldNotBe(null);
persistedGrants.Length.ShouldBe(2);
persistedGrants[0].SubjectId.ShouldBe("TestSubject");
persistedGrants[1].SubjectId.ShouldBe("TestSubject");
}
[Fact]
public async Task RemoveAsync_Should_Remove_PeristedGrant()
{
//Arrange
await _persistedGrantStore.StoreAsync(new PersistedGrant
{
Key = "#1P3R"
});
//Act
await _persistedGrantStore.RemoveAsync("#1P3R");
//Assert
var persistedGrant = await _persistedGrantStore.GetAsync("#1P3R");
persistedGrant.ShouldBe(null);
}
[Fact]
public async Task RemoveAllAsync_Should_RemoveAll_PeristedGrants_For_A_Given_Subject_And_ClientId()
{
//Arrange
var persistedGrantsWithTestSubjectX = await _persistedGrantStore.GetAllAsync("TestSubject-X");
var persistedGrantsWithTestSubjectXBeforeLength = persistedGrantsWithTestSubjectX.ToArray().Length;
//Act
await _persistedGrantStore.RemoveAllAsync("TestSubject-X", "TestClientId-X");
//Assert
persistedGrantsWithTestSubjectXBeforeLength.ShouldBe(2);
var persistedGrants = (await _persistedGrantStore.GetAllAsync("TestClientId-37")).ToArray();
persistedGrants.ShouldNotBe(null);
persistedGrants.Length.ShouldBe(0);
}
}
}
Loading…
Cancel
Save