From 8ed77e98eb7ae19609f4a2532a2241a644f6848e Mon Sep 17 00:00:00 2001 From: wuweilai <30889371+15168440402@users.noreply.github.com> Date: Mon, 20 Jun 2022 17:11:39 +0800 Subject: [PATCH] feature(oidc):add oidc (#66) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add IClientStore、IResourceStore * Code optimization * feat(oidc):oidc * feat(oidc):oidc * feat(oidc):oidc * feat(oidc):oidc * feat(oidc):oidc * feat(oidc):oidc * feat:update client * feat:update cache * feat(oidc):oidc * feat(oidc):oidc * feat(oidc):oidc * refactor:formatting code * feat(oidc):oidc * feat(oidc):remove AddAllAsync,add ResetAsync * feat(oidc):sln * refactor:refactor code * refactor(code):refactor code * refactor:refactor code * refactor:refactor code * fix:ReUse change to Reuse * refactor(code):refactor code Co-authored-by: Mayue --- Masa.BuildingBlocks.sln | 38 ++- .../Caches/IApiResourceCache.cs | 19 ++ .../Caches/IApiScopeCache.cs | 19 ++ .../Caches/IClientCache.cs | 15 ++ .../Caches/IIdentityResourceCache.cs | 19 ++ ...ingBlocks.Authentication.Oidc.Cache.csproj | 14 ++ .../_Imports.cs | 5 + .../Constants/GrantTypeConsts.cs | 37 +++ .../Constants/GrantTypes.cs | 19 ++ .../Entities/Abstract/Property.cs | 11 + .../Entities/Abstract/Secret.cs | 15 ++ .../Entities/ApiResource.cs | 78 ++++++ .../Entities/ApiResourceClaim.cs | 21 ++ .../Entities/ApiResourceProperty.cs | 18 ++ .../Entities/ApiResourceScope.cs | 21 ++ .../Entities/ApiResourceSecret.cs | 12 + .../Entities/ApiScope.cs | 66 +++++ .../Entities/ApiScopeClaim.cs | 20 ++ .../Entities/ApiScopeProperty.cs | 17 ++ .../Entities/Client.cs | 157 ++++++++++++ .../Entities/ClientClaim.cs | 15 ++ .../Entities/ClientCorsOrigin.cs | 13 + .../Entities/ClientGrantType.cs | 19 ++ .../Entities/ClientIdPRestriction.cs | 13 + .../Entities/ClientPostLogoutRedirectUri.cs | 18 ++ .../Entities/ClientProperty.cs | 17 ++ .../Entities/ClientRedirectUri.cs | 19 ++ .../Entities/ClientScope.cs | 18 ++ .../Entities/ClientSecret.cs | 11 + .../Entities/DeviceFlowCodes.cs | 71 ++++++ .../Entities/IdentityResource.cs | 66 +++++ .../Entities/IdentityResourceClaim.cs | 21 ++ .../Entities/IdentityResourceProperty.cs | 18 ++ .../Entities/PersistedGrant.cs | 25 ++ .../Entities/UserClaim.cs | 22 ++ .../Enums/ClientTypes.cs | 13 + .../Enums/TokenExpiration.cs | 20 ++ .../Enums/TokenUsage.cs | 20 ++ ...ngBlocks.Authentication.Oidc.Domain.csproj | 13 + .../Repositories/IApiResourceRepository.cs | 8 + .../Repositories/IApiScopeRepository.cs | 8 + .../Repositories/IClientRepository.cs | 8 + .../IIdentityResourceRepository.cs | 9 + .../Repositories/IRepositoryBase.cs | 24 ++ .../Repositories/IUserClaimRepository.cs | 9 + .../_import.cs | 11 + .../Constans/GrantType.cs | 19 ++ .../Constans/GrantTypes.cs | 37 +++ .../Constans/StandardIdentityResources.cs | 104 ++++++++ .../Constans/StandardUserClaims.cs | 78 ++++++ .../Enums/AccessTokenType.cs | 13 + .../Enums/TokenExpiration.cs | 13 + .../Enums/TokenUsage.cs | 13 + ...ngBlocks.Authentication.Oidc.Models.csproj | 9 + .../Models/ApiResourceModel.cs | 50 ++++ .../Models/ApiScopeModel.cs | 46 ++++ .../Models/ClientClaimModel.cs | 59 +++++ .../Models/ClientModel.cs | 227 ++++++++++++++++++ .../Models/DeviceCodeModel.cs | 113 +++++++++ .../Models/GrantType.cs | 22 ++ .../Models/IdentityResourceModel.cs | 48 ++++ .../Models/PersistedGrantFilter.cs | 44 ++++ .../Models/PersistedGrantModel.cs | 114 +++++++++ .../Models/ResourceModel.cs | 23 ++ .../Models/ResourcesModel.cs | 45 ++++ .../Models/SecretModel.cs | 40 +++ .../_Imports.cs | 9 + ...gBlocks.Authentication.Oidc.Storage.csproj | 16 ++ .../Stores/IClientStore.cs | 14 ++ .../Stores/IDeviceFlowStore.cs | 45 ++++ .../Stores/IPersistedGrantStore.cs | 45 ++++ .../Stores/IResourceStore.cs | 42 ++++ .../_Imports.cs | 4 + 73 files changed, 2419 insertions(+), 3 deletions(-) create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiResourceCache.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiScopeCache.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IClientCache.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IIdentityResourceCache.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Masa.BuildingBlocks.Authentication.Oidc.Cache.csproj create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/_Imports.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypeConsts.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypes.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Property.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Secret.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResource.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceClaim.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceProperty.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceScope.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceSecret.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScope.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeClaim.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeProperty.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Client.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientClaim.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientCorsOrigin.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientGrantType.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientIdPRestriction.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientPostLogoutRedirectUri.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientProperty.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientRedirectUri.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientScope.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientSecret.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/DeviceFlowCodes.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResource.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceClaim.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceProperty.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/PersistedGrant.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/UserClaim.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/ClientTypes.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenExpiration.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenUsage.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Masa.BuildingBlocks.Authentication.Oidc.Domain.csproj create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiResourceRepository.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiScopeRepository.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IClientRepository.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IIdentityResourceRepository.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IRepositoryBase.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IUserClaimRepository.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/_import.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantType.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantTypes.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardIdentityResources.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardUserClaims.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/AccessTokenType.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenExpiration.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenUsage.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Masa.BuildingBlocks.Authentication.Oidc.Models.csproj create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiResourceModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiScopeModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientClaimModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/DeviceCodeModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/GrantType.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/IdentityResourceModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantFilter.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourceModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourcesModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/SecretModel.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/_Imports.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Masa.BuildingBlocks.Authentication.Oidc.Storage.csproj create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IClientStore.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IDeviceFlowStore.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IPersistedGrantStore.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IResourceStore.cs create mode 100644 src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/_Imports.cs diff --git a/Masa.BuildingBlocks.sln b/Masa.BuildingBlocks.sln index 7b4b77b..e1a955c 100644 --- a/Masa.BuildingBlocks.sln +++ b/Masa.BuildingBlocks.sln @@ -81,11 +81,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Data", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Service.Contracts", "src\Service\Masa.BuildingBlocks.Service.Contracts\Masa.BuildingBlocks.Service.Contracts.csproj", "{775797E2-8576-4050-8649-18AAD00D0A87}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{BAABD8D1-BBB9-4F7B-9FD5-A71602BB4695}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Data.MappingExtensions", "src\Data\Masa.BuildingBlocks.Data.MappingExtensions\Masa.BuildingBlocks.Data.MappingExtensions.csproj", "{42D62996-F3FA-406F-AECD-BEACE557E0DB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Data.MappingExtensions", "src\Data\Masa.BuildingBlocks.Data.MappingExtensions\Masa.BuildingBlocks.Data.MappingExtensions.csproj", "{2281D561-3088-4251-BA84-99D658660CBE}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication", "Authentication", "{7078E83D-778C-4CE0-829F-7F0AD969361E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Identity.IdentityModel", "src\Identity\Masa.BuildingBlocks.Identity.IdentityModel\Masa.BuildingBlocks.Identity.IdentityModel.csproj", "{55344805-2B0A-4180-8F11-A61102E11F79}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Authentication.Oidc.Cache", "src\Authentication\Masa.BuildingBlocks.Authentication.Oidc.Cache\Masa.BuildingBlocks.Authentication.Oidc.Cache.csproj", "{CF05242F-1DBA-40E9-BBC4-7C4D6A69BE2B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Authentication.Oidc.Domain", "src\Authentication\Masa.BuildingBlocks.Authentication.Oidc.Domain\Masa.BuildingBlocks.Authentication.Oidc.Domain.csproj", "{639F5AB4-3648-4AFE-95E3-5909C054E39C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Authentication.Oidc.Models", "src\Authentication\Masa.BuildingBlocks.Authentication.Oidc.Models\Masa.BuildingBlocks.Authentication.Oidc.Models.csproj", "{F77F36FE-82A1-4BEC-8AB2-55F298AAADCD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Masa.BuildingBlocks.Authentication.Oidc.Storage", "src\Authentication\Masa.BuildingBlocks.Authentication.Oidc.Storage\Masa.BuildingBlocks.Authentication.Oidc.Storage.csproj", "{701DF095-CF25-4311-9129-279A1834D8A3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -169,6 +175,26 @@ Global {775797E2-8576-4050-8649-18AAD00D0A87}.Debug|Any CPU.Build.0 = Debug|Any CPU {775797E2-8576-4050-8649-18AAD00D0A87}.Release|Any CPU.ActiveCfg = Release|Any CPU {775797E2-8576-4050-8649-18AAD00D0A87}.Release|Any CPU.Build.0 = Release|Any CPU + {42D62996-F3FA-406F-AECD-BEACE557E0DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42D62996-F3FA-406F-AECD-BEACE557E0DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42D62996-F3FA-406F-AECD-BEACE557E0DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42D62996-F3FA-406F-AECD-BEACE557E0DB}.Release|Any CPU.Build.0 = Release|Any CPU + {CF05242F-1DBA-40E9-BBC4-7C4D6A69BE2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF05242F-1DBA-40E9-BBC4-7C4D6A69BE2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF05242F-1DBA-40E9-BBC4-7C4D6A69BE2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF05242F-1DBA-40E9-BBC4-7C4D6A69BE2B}.Release|Any CPU.Build.0 = Release|Any CPU + {639F5AB4-3648-4AFE-95E3-5909C054E39C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {639F5AB4-3648-4AFE-95E3-5909C054E39C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {639F5AB4-3648-4AFE-95E3-5909C054E39C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {639F5AB4-3648-4AFE-95E3-5909C054E39C}.Release|Any CPU.Build.0 = Release|Any CPU + {F77F36FE-82A1-4BEC-8AB2-55F298AAADCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F77F36FE-82A1-4BEC-8AB2-55F298AAADCD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F77F36FE-82A1-4BEC-8AB2-55F298AAADCD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F77F36FE-82A1-4BEC-8AB2-55F298AAADCD}.Release|Any CPU.Build.0 = Release|Any CPU + {701DF095-CF25-4311-9129-279A1834D8A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {701DF095-CF25-4311-9129-279A1834D8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {701DF095-CF25-4311-9129-279A1834D8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {701DF095-CF25-4311-9129-279A1834D8A3}.Release|Any CPU.Build.0 = Release|Any CPU {2281D561-3088-4251-BA84-99D658660CBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2281D561-3088-4251-BA84-99D658660CBE}.Debug|Any CPU.Build.0 = Debug|Any CPU {2281D561-3088-4251-BA84-99D658660CBE}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -214,6 +240,12 @@ Global {EA5B1CAD-2275-43F3-9A50-7CE1FD94ACDB} = {64FB8703-E922-45DE-9D01-3FE9EFE56727} {4B9BF713-E0BC-4CAB-9D8D-353C18EDC855} = {64FB8703-E922-45DE-9D01-3FE9EFE56727} {775797E2-8576-4050-8649-18AAD00D0A87} = {593A3114-D1E0-47ED-BC37-58E08886175B} + {42D62996-F3FA-406F-AECD-BEACE557E0DB} = {64FB8703-E922-45DE-9D01-3FE9EFE56727} + {7078E83D-778C-4CE0-829F-7F0AD969361E} = {77D17E30-CB7C-4DD7-8CF1-9D5350FF2304} + {CF05242F-1DBA-40E9-BBC4-7C4D6A69BE2B} = {7078E83D-778C-4CE0-829F-7F0AD969361E} + {639F5AB4-3648-4AFE-95E3-5909C054E39C} = {7078E83D-778C-4CE0-829F-7F0AD969361E} + {F77F36FE-82A1-4BEC-8AB2-55F298AAADCD} = {7078E83D-778C-4CE0-829F-7F0AD969361E} + {701DF095-CF25-4311-9129-279A1834D8A3} = {7078E83D-778C-4CE0-829F-7F0AD969361E} {BAABD8D1-BBB9-4F7B-9FD5-A71602BB4695} = {77D17E30-CB7C-4DD7-8CF1-9D5350FF2304} {2281D561-3088-4251-BA84-99D658660CBE} = {64FB8703-E922-45DE-9D01-3FE9EFE56727} {55344805-2B0A-4180-8F11-A61102E11F79} = {BAABD8D1-BBB9-4F7B-9FD5-A71602BB4695} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiResourceCache.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiResourceCache.cs new file mode 100644 index 0000000..92c5a53 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiResourceCache.cs @@ -0,0 +1,19 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Cache.Caches; + +public interface IApiResourceCache +{ + Task> GetListAsync(IEnumerable names); + + Task> GetListAsync(); + + Task SetAsync(ApiResource apiResource); + + Task SetRangeAsync(IEnumerable apiResources); + + Task RemoveAsync(ApiResource apiResource); + + Task ResetAsync(IEnumerable identityResources); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiScopeCache.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiScopeCache.cs new file mode 100644 index 0000000..07002b1 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IApiScopeCache.cs @@ -0,0 +1,19 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Cache.Caches; + +public interface IApiScopeCache +{ + Task> GetListAsync(IEnumerable names); + + Task> GetListAsync(); + + Task SetAsync(ApiScope apiScope); + + Task SetRangeAsync(IEnumerable apiScopes); + + Task RemoveAsync(ApiScope apiScope); + + Task ResetAsync(IEnumerable identityResources); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IClientCache.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IClientCache.cs new file mode 100644 index 0000000..d125c93 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IClientCache.cs @@ -0,0 +1,15 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Cache.Caches; + +public interface IClientCache +{ + Task GetAsync(string clientId); + + Task SetAsync(Client client); + + Task SetRangeAsync(IEnumerable clients); + + Task RemoveAsync(Client client); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IIdentityResourceCache.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IIdentityResourceCache.cs new file mode 100644 index 0000000..7c0ef59 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Caches/IIdentityResourceCache.cs @@ -0,0 +1,19 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Cache.Caches; + +public interface IIdentityResourceCache +{ + Task> GetListAsync(IEnumerable names); + + Task> GetListAsync(); + + Task SetAsync(IdentityResource identityResource); + + Task SetRangeAsync(IEnumerable identityResources); + + Task RemoveAsync(IdentityResource identityResource); + + Task ResetAsync(IEnumerable identityResources); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Masa.BuildingBlocks.Authentication.Oidc.Cache.csproj b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Masa.BuildingBlocks.Authentication.Oidc.Cache.csproj new file mode 100644 index 0000000..efd4054 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/Masa.BuildingBlocks.Authentication.Oidc.Cache.csproj @@ -0,0 +1,14 @@ + + + + net6.0 + enable + enable + + + + + + + + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/_Imports.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/_Imports.cs new file mode 100644 index 0000000..f9859df --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Cache/_Imports.cs @@ -0,0 +1,5 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +global using Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; +global using Masa.BuildingBlocks.Authentication.Oidc.Models.Models; diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypeConsts.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypeConsts.cs new file mode 100644 index 0000000..9627791 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypeConsts.cs @@ -0,0 +1,37 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Constants; + +public class GrantTypeConsts +{ + public static ICollection Implicit => + new[] { GrantTypes.IMPLICIT }; + + public static ICollection ImplicitAndClientCredentials => + new[] { GrantTypes.IMPLICIT, GrantTypes.CLIENT_CREDENTIALS }; + + public static ICollection Code => + new[] { GrantTypes.AUTHORIZATION_CODE }; + + public static ICollection CodeAndClientCredentials => + new[] { GrantTypes.AUTHORIZATION_CODE, GrantTypes.CLIENT_CREDENTIALS }; + + public static ICollection Hybrid => + new[] { GrantTypes.HYBRID }; + + public static ICollection HybridAndClientCredentials => + new[] { GrantTypes.HYBRID, GrantTypes.CLIENT_CREDENTIALS }; + + public static ICollection ClientCredentials => + new[] { GrantTypes.CLIENT_CREDENTIALS }; + + public static ICollection ResourceOwnerPassword => + new[] { GrantTypes.RESOURCE_OWNER_PASSWORD }; + + public static ICollection ResourceOwnerPasswordAndClientCredentials => + new[] { GrantTypes.RESOURCE_OWNER_PASSWORD, GrantTypes.CLIENT_CREDENTIALS }; + + public static ICollection DeviceFlow => + new[] { GrantTypes.DEVICE_FLOW }; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypes.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypes.cs new file mode 100644 index 0000000..d6e49be --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Constants/GrantTypes.cs @@ -0,0 +1,19 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Constants; + +public static class GrantTypes +{ + public const string IMPLICIT = "implicit"; + + public const string HYBRID = "hybrid"; + + public const string AUTHORIZATION_CODE = "authorization_code"; + + public const string CLIENT_CREDENTIALS = "client_credentials"; + + public const string RESOURCE_OWNER_PASSWORD = "password"; + + public const string DEVICE_FLOW = "urn:ietf:params:oauth:grant-type:device_code"; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Property.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Property.cs new file mode 100644 index 0000000..a76ab6f --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Property.cs @@ -0,0 +1,11 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities.Abstract; + +public abstract class Property : Entity +{ + public string Key { get; protected set; } = ""; + + public string Value { get; protected set; } = ""; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Secret.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Secret.cs new file mode 100644 index 0000000..d317f50 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Abstract/Secret.cs @@ -0,0 +1,15 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities.Abstract; + +public abstract class Secret : FullEntity +{ + public string Description { get; protected set; } = string.Empty; + + public string Value { get; protected set; } = string.Empty; + + public DateTime? Expiration { get; protected set; } + + public string Type { get; protected set; } = "SharedSecret"; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResource.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResource.cs new file mode 100644 index 0000000..c953e82 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResource.cs @@ -0,0 +1,78 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiResource : FullAggregateRoot +{ + private List _secrets = new(); + private List _apiScopes = new(); + private List _userClaims = new(); + private List _properties = new(); + + public bool Enabled { get; private set; } + + public string Name { get; private set; } = ""; + + public string DisplayName { get; private set; } = ""; + + public string Description { get; private set; } = ""; + + public string AllowedAccessTokenSigningAlgorithms { get; private set; } = ""; + + public bool ShowInDiscoveryDocument { get; private set; } = true; + + public DateTime? LastAccessed { get; private set; } + + public bool NonEditable { get; private set; } + + public IReadOnlyCollection Secrets => _secrets; + + public IReadOnlyCollection ApiScopes => _apiScopes; + + public IReadOnlyCollection UserClaims => _userClaims; + + public IReadOnlyCollection Properties => _properties; + + public ApiResource(string name, string displayName, string description, string allowedAccessTokenSigningAlgorithms, bool showInDiscoveryDocument, DateTime? lastAccessed, bool nonEditable, bool enabled) + { + Enabled = enabled; + Name = name; + DisplayName = displayName; + Description = description; + AllowedAccessTokenSigningAlgorithms = allowedAccessTokenSigningAlgorithms; + ShowInDiscoveryDocument = showInDiscoveryDocument; + LastAccessed = lastAccessed; + NonEditable = nonEditable; + } + + public void Update(string displayName, string description, string allowedAccessTokenSigningAlgorithms, bool showInDiscoveryDocument, DateTime? lastAccessed, bool nonEditable, bool enabled) + { + Enabled = enabled; + DisplayName = displayName; + Description = description; + AllowedAccessTokenSigningAlgorithms = allowedAccessTokenSigningAlgorithms; + ShowInDiscoveryDocument = showInDiscoveryDocument; + LastAccessed = lastAccessed; + NonEditable = nonEditable; + } + + public void BindUserClaims(List userClaims) + { + _userClaims.Clear(); + _userClaims.AddRange(userClaims.Select(id => new ApiResourceClaim(id))); + } + + public void BindProperties(Dictionary properties) + { + _properties.Clear(); + _properties.AddRange(properties.Select(property => new ApiResourceProperty(property.Key, property.Value))); + } + + public void BindApiScopes(List apiScopes) + { + _apiScopes.Clear(); + _apiScopes.AddRange(apiScopes.Select(id => new ApiResourceScope(id))); + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceClaim.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceClaim.cs new file mode 100644 index 0000000..585e179 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceClaim.cs @@ -0,0 +1,21 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiResourceClaim : Entity +{ + public int UserClaimId { get; private set; } + + public UserClaim UserClaim { get; private set; } = null!; + + public int ApiResourceId { get; private set; } + + public ApiResource ApiResource { get; private set; } = null!; + + public ApiResourceClaim(int userClaimId) + { + UserClaimId = userClaimId; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceProperty.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceProperty.cs new file mode 100644 index 0000000..8dde202 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceProperty.cs @@ -0,0 +1,18 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiResourceProperty : Property +{ + public int ApiResourceId { get; private set; } + + public ApiResource ApiResource { get; private set; } = null!; + + public ApiResourceProperty(string key, string value) + { + Key = key; + Value = value; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceScope.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceScope.cs new file mode 100644 index 0000000..e9f96af --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceScope.cs @@ -0,0 +1,21 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiResourceScope : Entity +{ + public int ApiScopeId { get; private set; } + + public ApiScope ApiScope { get; private set; } = null!; + + public int ApiResourceId { get; private set; } + + public ApiResource ApiResource { get; private set; } = null!; + + public ApiResourceScope(int apiScopeId) + { + ApiScopeId = apiScopeId; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceSecret.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceSecret.cs new file mode 100644 index 0000000..aef6276 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiResourceSecret.cs @@ -0,0 +1,12 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiResourceSecret : Secret +{ + public int ApiResourceId { get; private set; } + + public ApiResource ApiResource { get; private set; } = null!; +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScope.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScope.cs new file mode 100644 index 0000000..b2d6c40 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScope.cs @@ -0,0 +1,66 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiScope : FullAggregateRoot +{ + private List _userClaims = new(); + private List _properties = new(); + + public bool Enabled { get; private set; } + + public string Name { get; private set; } = ""; + + public string DisplayName { get; private set; } = ""; + + public string Description { get; private set; } = ""; + + public bool Required { get; private set; } + + public bool Emphasize { get; private set; } + + public bool ShowInDiscoveryDocument { get; private set; } + + public IReadOnlyCollection UserClaims => _userClaims; + + public IReadOnlyCollection Properties => _properties; + + public ApiScope(string name) : this(name, name, "", true, true, true, true) + { + + } + + public ApiScope(string name, string displayName, string description, bool required, bool emphasize, bool showInDiscoveryDocument, bool enabled) + { + Enabled = enabled; + Name = name; + DisplayName = displayName; + Description = description; + Required = required; + Emphasize = emphasize; + ShowInDiscoveryDocument = showInDiscoveryDocument; + } + + public void Update(string displayName, string description, bool required, bool emphasize, bool showInDiscoveryDocument, bool enabled) + { + Enabled = enabled; + DisplayName = displayName; + Description = description; + Required = required; + Emphasize = emphasize; + ShowInDiscoveryDocument = showInDiscoveryDocument; + } + + public void BindUserClaims(List userClaims) + { + _userClaims.Clear(); + _userClaims.AddRange(userClaims.Select(id => new ApiScopeClaim(id))); + } + + public void BindProperties(Dictionary properties) + { + _properties.Clear(); + _properties.AddRange(properties.Select(property => new ApiScopeProperty(property.Key, property.Value))); + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeClaim.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeClaim.cs new file mode 100644 index 0000000..c1dd4e2 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeClaim.cs @@ -0,0 +1,20 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiScopeClaim : Entity +{ + public int UserClaimId { get; private set; } + + public UserClaim UserClaim { get; private set; } = null!; + + public int ApiScopeId { get; private set; } + + public ApiScope ApiScope { get; private set; } = null!; + + public ApiScopeClaim(int userClaimId) + { + UserClaimId = userClaimId; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeProperty.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeProperty.cs new file mode 100644 index 0000000..9b49e1e --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ApiScopeProperty.cs @@ -0,0 +1,17 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ApiScopeProperty : Property +{ + public int ScopeId { get; private set; } + + public ApiScope Scope { get; private set; } = null!; + + public ApiScopeProperty(string key, string value) + { + Key = key; + Value = value; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Client.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Client.cs new file mode 100644 index 0000000..d7e732c --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/Client.cs @@ -0,0 +1,157 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class Client : FullAggregateRoot +{ + public ClientTypes ClientType { get; private set; } + + public bool Enabled { get; private set; } = true; + + public string ClientId { get; private set; } = string.Empty; + + public string ProtocolType { get; private set; } = "oidc"; + + public List ClientSecrets { get; private set; } = new(); + + public bool RequireClientSecret { get; private set; } = true; + + public string ClientName { get; private set; } = string.Empty; + + public string Description { get; private set; } = string.Empty; + + public string ClientUri { get; private set; } = string.Empty; + + public string LogoUri { get; private set; } = string.Empty; + + public bool RequireConsent { get; private set; } = false; + + public bool AllowRememberConsent { get; private set; } = true; + + public bool AlwaysIncludeUserClaimsInIdToken { get; private set; } + + public List AllowedGrantTypes { get; private set; } = new(); + + public bool RequirePkce { get; private set; } = true; + + public bool AllowPlainTextPkce { get; private set; } + + public bool RequireRequestObject { get; private set; } + + public bool AllowAccessTokensViaBrowser { get; private set; } + + public List RedirectUris { get; private set; } = new(); + + public List PostLogoutRedirectUris { get; private set; } = new(); + + public string FrontChannelLogoutUri { get; private set; } = string.Empty; + + public bool FrontChannelLogoutSessionRequired { get; private set; } = true; + + public string BackChannelLogoutUri { get; private set; } = string.Empty; + + public bool BackChannelLogoutSessionRequired { get; private set; } = true; + + public bool AllowOfflineAccess { get; private set; } + + public List AllowedScopes { get; private set; } = new(); + + public int IdentityTokenLifetime { get; private set; } = 300; + + public string AllowedIdentityTokenSigningAlgorithms { get; private set; } = string.Empty; + + public int AccessTokenLifetime { get; private set; } = 3600; + + public int AuthorizationCodeLifetime { get; private set; } = 300; + + public int? ConsentLifetime { get; private set; } = null; + + public int AbsoluteRefreshTokenLifetime { get; private set; } = 2592000; + + public int SlidingRefreshTokenLifetime { get; private set; } = 1296000; + + public int RefreshTokenUsage { get; private set; } = (int)TokenUsage.OneTimeOnly; + + public bool UpdateAccessTokenClaimsOnRefresh { get; private set; } + + public int RefreshTokenExpiration { get; private set; } = (int)TokenExpiration.Absolute; + + public int AccessTokenType { get; private set; } = 0; // AccessTokenType.Jwt; + + public bool EnableLocalLogin { get; private set; } = true; + + public List IdentityProviderRestrictions { get; private set; } = new(); + + public bool IncludeJwtId { get; private set; } + + public List Claims { get; private set; } = new(); + + public bool AlwaysSendClientClaims { get; private set; } + + public string ClientClaimsPrefix { get; private set; } = "client_"; + + public string PairWiseSubjectSalt { get; private set; } = string.Empty; + + public List AllowedCorsOrigins { get; private set; } = new(); + + public List Properties { get; private set; } = new(); + + public DateTime? LastAccessed { get; private set; } + + public int? UserSsoLifetime { get; private set; } + + public string UserCodeType { get; private set; } = string.Empty; + + public int DeviceCodeLifetime { get; private set; } = 300; + + public bool NonEditable { get; private set; } + + public Client(ClientTypes clientType, string clientId, string clientName) + { + SetClientType(clientType); + ClientId = clientId; + ClientName = clientName; + } + + public void SetClientType(ClientTypes clientType) + { + ClientType = clientType; + switch (clientType) + { + case ClientTypes.Web: + case ClientTypes.Spa: + case ClientTypes.Native: + AllowedGrantTypes = GrantTypeConsts.Code.Select(x => new ClientGrantType(x)).ToList(); + RequirePkce = true; + RequireClientSecret = false; + break; + case ClientTypes.Machine: + AllowedGrantTypes = GrantTypeConsts.ClientCredentials.Select(x => new ClientGrantType(x)).ToList(); + RequireClientSecret = true; + break; + case ClientTypes.Device: + AllowedGrantTypes = GrantTypeConsts.DeviceFlow.Select(x => new ClientGrantType(x)).ToList(); + RequireClientSecret = false; + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + public void SetRedirectUris(List redirectUris) + { + RedirectUris = redirectUris.Select(x => new ClientRedirectUri(x)).ToList(); + } + + public void SetPostLogoutRedirectUris(List postLogoutRedirectUris) + { + PostLogoutRedirectUris = postLogoutRedirectUris.Select(x => new ClientPostLogoutRedirectUri(x)).ToList(); + } + + public void SetAllowedScopes(List allowedScopes) + { + AllowedScopes = allowedScopes.Select(x => new ClientScope(x)).ToList(); + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientClaim.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientClaim.cs new file mode 100644 index 0000000..a95e140 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientClaim.cs @@ -0,0 +1,15 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientClaim : Entity +{ + public string Type { get; private set; } = string.Empty; + + public string Value { get; private set; } = string.Empty; + + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientCorsOrigin.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientCorsOrigin.cs new file mode 100644 index 0000000..9424609 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientCorsOrigin.cs @@ -0,0 +1,13 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientCorsOrigin : Entity +{ + public string Origin { get; private set; } = string.Empty; + + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientGrantType.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientGrantType.cs new file mode 100644 index 0000000..aa6124f --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientGrantType.cs @@ -0,0 +1,19 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientGrantType : Entity +{ + public string GrantType { get; private set; } = string.Empty; + + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; + + public ClientGrantType(string grantType) + { + GrantType = grantType; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientIdPRestriction.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientIdPRestriction.cs new file mode 100644 index 0000000..61ed181 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientIdPRestriction.cs @@ -0,0 +1,13 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientIdPRestriction : Entity +{ + public string Provider { get; private set; } = string.Empty; + + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientPostLogoutRedirectUri.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientPostLogoutRedirectUri.cs new file mode 100644 index 0000000..b50256c --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientPostLogoutRedirectUri.cs @@ -0,0 +1,18 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientPostLogoutRedirectUri : Entity +{ + public string PostLogoutRedirectUri { get; private set; } = string.Empty; + + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; + + public ClientPostLogoutRedirectUri(string postLogoutRedirectUri) + { + PostLogoutRedirectUri = postLogoutRedirectUri; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientProperty.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientProperty.cs new file mode 100644 index 0000000..8d78e46 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientProperty.cs @@ -0,0 +1,17 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientProperty : Property +{ + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; + + public ClientProperty(string key, string value) + { + Key = key; + Value = value; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientRedirectUri.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientRedirectUri.cs new file mode 100644 index 0000000..7d0016b --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientRedirectUri.cs @@ -0,0 +1,19 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientRedirectUri : Entity +{ + public string RedirectUri { get; private set; } = string.Empty; + + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; + + public ClientRedirectUri(string redirectUri) + { + RedirectUri = redirectUri; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientScope.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientScope.cs new file mode 100644 index 0000000..051e242 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientScope.cs @@ -0,0 +1,18 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientScope : Entity +{ + public string Scope { get; private set; } = string.Empty; + + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; + + public ClientScope(string scope) + { + Scope = scope; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientSecret.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientSecret.cs new file mode 100644 index 0000000..415646d --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/ClientSecret.cs @@ -0,0 +1,11 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class ClientSecret : Secret +{ + public int ClientId { get; private set; } + + public Client Client { get; private set; } = null!; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/DeviceFlowCodes.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/DeviceFlowCodes.cs new file mode 100644 index 0000000..5607d73 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/DeviceFlowCodes.cs @@ -0,0 +1,71 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class DeviceFlowCodes : FullAggregateRoot +{ + /// + /// Gets or sets the device code. + /// + /// + /// The device code. + /// + public string DeviceCode { get; private set; } = string.Empty; + + /// + /// Gets or sets the user code. + /// + /// + /// The user code. + /// + public string UserCode { get; private set; } = string.Empty; + + /// + /// Gets or sets the subject identifier. + /// + /// + /// The subject identifier. + /// + public string SubjectId { get; private set; } = string.Empty; + + /// + /// Gets or sets the session identifier. + /// + /// + /// The session identifier. + /// + public string SessionId { get; private set; } = string.Empty; + + /// + /// Gets or sets the client identifier. + /// + /// + /// The client identifier. + /// + public string ClientId { get; private set; } = string.Empty; + + /// + /// Gets the description the user assigned to the device being authorized. + /// + /// + /// The description. + /// + public string Description { get; private set; } = string.Empty; + + /// + /// Gets or sets the expiration. + /// + /// + /// The expiration. + /// + public DateTime? Expiration { get; private set; } + + /// + /// Gets or sets the data. + /// + /// + /// The data. + /// + public string Data { get; private set; } = string.Empty; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResource.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResource.cs new file mode 100644 index 0000000..e947153 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResource.cs @@ -0,0 +1,66 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class IdentityResource : FullAggregateRoot +{ + private List _userClaims = new(); + private List _properties = new(); + + public string Name { get; private set; } = string.Empty; + + public string DisplayName { get; private set; } = string.Empty; + + public string Description { get; private set; } = string.Empty; + + public bool Enabled { get; private set; } = true; + + public bool Required { get; private set; } + + public bool Emphasize { get; private set; } + + public bool ShowInDiscoveryDocument { get; private set; } = true; + + public IReadOnlyCollection UserClaims => _userClaims; + + public IReadOnlyCollection Properties => _properties; + + public bool NonEditable { get; private set; } + + public IdentityResource(string name, string displayName, string description, bool enabled, bool required, bool emphasize, bool showInDiscoveryDocument, bool nonEditable) + { + Name = name; + DisplayName = displayName; + Description = description; + Enabled = enabled; + Required = required; + Emphasize = emphasize; + ShowInDiscoveryDocument = showInDiscoveryDocument; + NonEditable = nonEditable; + } + + public void BindUserClaims(IEnumerable userClaims) + { + _userClaims.Clear(); + _userClaims.AddRange(userClaims.Select(id => new IdentityResourceClaim(id))); + } + + public void BindProperties(Dictionary properties) + { + _properties.Clear(); + _properties.AddRange(properties.Select(property => new IdentityResourceProperty(property.Key, property.Value))); + } + + public void Update(string displayName, string description, bool enabled, bool required, bool emphasize, bool showInDiscoveryDocument, bool nonEditable) + { + DisplayName = displayName; + Description = description; + Enabled = enabled; + Required = required; + Emphasize = emphasize; + ShowInDiscoveryDocument = showInDiscoveryDocument; + NonEditable = nonEditable; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceClaim.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceClaim.cs new file mode 100644 index 0000000..df9b37b --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceClaim.cs @@ -0,0 +1,21 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class IdentityResourceClaim : Entity +{ + public int UserClaimId { get; private set; } + + public UserClaim UserClaim { get; private set; } = null!; + + public int IdentityResourceId { get; private set; } + + public IdentityResource IdentityResource { get; private set; } = null!; + + public IdentityResourceClaim(int userClaimId) + { + UserClaimId = userClaimId; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceProperty.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceProperty.cs new file mode 100644 index 0000000..88b21d1 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/IdentityResourceProperty.cs @@ -0,0 +1,18 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities +{ + public class IdentityResourceProperty : Property + { + public int IdentityResourceId { get; private set; } + + public IdentityResource IdentityResource { get; private set; } = null!; + + public IdentityResourceProperty(string key, string value) + { + Key = key; + Value = value; + } + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/PersistedGrant.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/PersistedGrant.cs new file mode 100644 index 0000000..2ceeced --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/PersistedGrant.cs @@ -0,0 +1,25 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class PersistedGrant : FullAggregateRoot +{ + public string Key { get; private set; } = null!; + + public string Type { get; private set; } = string.Empty; + + public string SubjectId { get; private set; } = string.Empty; + + public string SessionId { get; private set; } = string.Empty; + + public string ClientId { get; private set; } = string.Empty; + + public string Description { get; private set; } = string.Empty; + + public DateTime? Expiration { get; private set; } + + public DateTime? ConsumedTime { get; private set; } + + public string Data { get; private set; } = string.Empty; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/UserClaim.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/UserClaim.cs new file mode 100644 index 0000000..669417c --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Entities/UserClaim.cs @@ -0,0 +1,22 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; + +public class UserClaim : FullAggregateRoot +{ + public string Name { get; private set; } + + public string Description { get; private set; } + + public UserClaim(string name, string description) + { + Name = name; + Description = description; + } + + public void Update(string description) + { + Description = description; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/ClientTypes.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/ClientTypes.cs new file mode 100644 index 0000000..d4882f5 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/ClientTypes.cs @@ -0,0 +1,13 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Enums; + +public enum ClientTypes +{ + Web = 1, + Spa = 2, + Native = 3, + Machine = 4, + Device = 5 +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenExpiration.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenExpiration.cs new file mode 100644 index 0000000..410ac83 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenExpiration.cs @@ -0,0 +1,20 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Enums; + +/// +/// Token expiration types. +/// +public enum TokenExpiration +{ + /// + /// Sliding token expiration + /// + Sliding = 0, + + /// + /// Absolute token expiration + /// + Absolute = 1 +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenUsage.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenUsage.cs new file mode 100644 index 0000000..67eaa80 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Enums/TokenUsage.cs @@ -0,0 +1,20 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Enums; + +/// +/// Token usage types. +/// +public enum TokenUsage +{ + /// + /// Re-use the refresh token handle + /// + Reuse = 0, + + /// + /// Issue a new refresh token handle every time + /// + OneTimeOnly = 1 +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Masa.BuildingBlocks.Authentication.Oidc.Domain.csproj b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Masa.BuildingBlocks.Authentication.Oidc.Domain.csproj new file mode 100644 index 0000000..5f01c06 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Masa.BuildingBlocks.Authentication.Oidc.Domain.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + enable + + + + + + + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiResourceRepository.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiResourceRepository.cs new file mode 100644 index 0000000..c7118c5 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiResourceRepository.cs @@ -0,0 +1,8 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Repositories; + +public interface IApiResourceRepository : IRepositoryBase +{ +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiScopeRepository.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiScopeRepository.cs new file mode 100644 index 0000000..6d5822e --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IApiScopeRepository.cs @@ -0,0 +1,8 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Repositories; + +public interface IApiScopeRepository : IRepositoryBase +{ +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IClientRepository.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IClientRepository.cs new file mode 100644 index 0000000..31c686f --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IClientRepository.cs @@ -0,0 +1,8 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Repositories; + +public interface IClientRepository : IRepositoryBase +{ +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IIdentityResourceRepository.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IIdentityResourceRepository.cs new file mode 100644 index 0000000..f70b7ab --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IIdentityResourceRepository.cs @@ -0,0 +1,9 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Repositories; + +public interface IIdentityResourceRepository : IRepositoryBase +{ + Task AddStandardIdentityResourcesAsync(); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IRepositoryBase.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IRepositoryBase.cs new file mode 100644 index 0000000..a15fcea --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IRepositoryBase.cs @@ -0,0 +1,24 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Repositories; + +public interface IRepositoryBase where TEntity : class, IEntity +{ + Task> GetPaginatedListAsync(int page, int pageSize, Expression>? condition = null); + + Task GetDetailAsync(int id); + + Task> GetListAsync(); + + Task FindAsync(Expression> predicate); + + Task GetCountAsync(Expression> predicate); + + ValueTask AddAsync(TEntity entity); + + Task UpdateAsync(TEntity entity); + + Task RemoveAsync(TEntity entity); +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IUserClaimRepository.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IUserClaimRepository.cs new file mode 100644 index 0000000..2a884f1 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/Repositories/IUserClaimRepository.cs @@ -0,0 +1,9 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Domain.Repositories; + +public interface IUserClaimRepository : IRepositoryBase +{ + Task AddStandardUserClaimsAsync(); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/_import.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/_import.cs new file mode 100644 index 0000000..623152b --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Domain/_import.cs @@ -0,0 +1,11 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +global using Masa.BuildingBlocks.Authentication.Oidc.Domain.Constants; +global using Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities; +global using Masa.BuildingBlocks.Authentication.Oidc.Domain.Entities.Abstract; +global using Masa.BuildingBlocks.Authentication.Oidc.Domain.Enums; +global using Masa.BuildingBlocks.Ddd.Domain.Entities; +global using Masa.BuildingBlocks.Ddd.Domain.Entities.Full; +global using Masa.BuildingBlocks.Ddd.Domain.Repositories; +global using System.Linq.Expressions; diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantType.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantType.cs new file mode 100644 index 0000000..900f0e6 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantType.cs @@ -0,0 +1,19 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Constans; + +public static class GrantType +{ + public const string IMPLICIT = "implicit"; + + public const string HYBRID = "hybrid"; + + public const string AUTHORIZATION_CODE = "authorization_code"; + + public const string CLIENT_CREDENTIALS = "client_credentials"; + + public const string RESOURCE_OWNER_PASSWORD = "password"; + + public const string DEVICE_FLOW = "urn:ietf:params:oauth:grant-type:device_code"; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantTypes.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantTypes.cs new file mode 100644 index 0000000..30d7ad3 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/GrantTypes.cs @@ -0,0 +1,37 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Constans; + +public class GrantTypes +{ + public static ICollection Implicit => + new[] { GrantType.Implicit }; + + public static ICollection ImplicitAndClientCredentials => + new[] { GrantType.Implicit, GrantType.ClientCredentials }; + + public static ICollection Code => + new[] { GrantType.AuthorizationCode }; + + public static ICollection CodeAndClientCredentials => + new[] { GrantType.AuthorizationCode, GrantType.ClientCredentials }; + + public static ICollection Hybrid => + new[] { GrantType.Hybrid }; + + public static ICollection HybridAndClientCredentials => + new[] { GrantType.Hybrid, GrantType.ClientCredentials }; + + public static ICollection ClientCredentials => + new[] { GrantType.ClientCredentials }; + + public static ICollection ResourceOwnerPassword => + new[] { GrantType.ResourceOwnerPassword }; + + public static ICollection ResourceOwnerPasswordAndClientCredentials => + new[] { GrantType.ResourceOwnerPassword, GrantType.ClientCredentials }; + + public static ICollection DeviceFlow => + new[] { GrantType.DeviceFlow }; +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardIdentityResources.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardIdentityResources.cs new file mode 100644 index 0000000..86f8594 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardIdentityResources.cs @@ -0,0 +1,104 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Constans; + +public class StandardIdentityResources +{ + [Description("Your user identifier")] + public static IdentityResourceModel OpenId = new() + { + Name = "openId", + DisplayName = "Your user identifier", + Description = "Your user identifier", + Required = true, + UserClaims = new List() + { + StandardUserClaims.Subject + } + }; + + [Description("Your address")] + public static IdentityResourceModel Address = new() + { + Name = "address", + DisplayName = "Your address", + Description = "Your address", + Emphasize = true, + UserClaims = new List() + { + StandardUserClaims.Address + } + }; + + [Description("Your email address")] + public static IdentityResourceModel Email = new() + { + Name = "email", + DisplayName = "Your email address", + Description = "Your email address", + Emphasize = true, + UserClaims = new List() + { + StandardUserClaims.Email, + StandardUserClaims.EmailVerified, + } + }; + + [Description("Your phone number")] + public static IdentityResourceModel Phone = new() + { + Name = "phone", + DisplayName = "Your phone number", + Description = "Your phone number", + Emphasize = true, + UserClaims = new List() + { + StandardUserClaims.PhoneNumber, + StandardUserClaims.PhoneNumberVerified + } + }; + + [Description("User profile")] + public static IdentityResourceModel Profile = new() + { + Name = "profile", + DisplayName = "User profile", + Description = "Your user profile information (first name, last name, etc.)", + Emphasize = true, + UserClaims = new List() + { + StandardUserClaims.Name, + StandardUserClaims.FamilyName, + StandardUserClaims.GivenName, + StandardUserClaims.MiddleName, + StandardUserClaims.NickName, + StandardUserClaims.PreferredUserName, + StandardUserClaims.Profile, + StandardUserClaims.Picture, + StandardUserClaims.WebSite, + StandardUserClaims.Gender, + StandardUserClaims.BirthDate, + StandardUserClaims.ZoneInfo, + StandardUserClaims.Locale, + StandardUserClaims.UpdatedAt + } + }; + + static List? _identityResources; + + public static List IdentityResources => _identityResources ??= GetIdentityResources(); + + static List GetIdentityResources() + { + var identityResources = new List(); + var fields = typeof(StandardIdentityResources).GetFields(BindingFlags.Static | BindingFlags.Public); + foreach (var field in fields) + { + var idrs = (IdentityResourceModel)(field.GetValue(null) ?? throw new Exception("Error standard identity resources data")); + identityResources.Add(idrs); + } + + return identityResources; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardUserClaims.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardUserClaims.cs new file mode 100644 index 0000000..f6b2d8e --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Constans/StandardUserClaims.cs @@ -0,0 +1,78 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Constans; + +public static class StandardUserClaims +{ + [Description("subject 的缩写,唯一标识,一般为用户 ID")] + public static readonly string Subject = "sub"; + [Description("姓名")] + public static readonly string Name = "name"; + [Description("名字")] + public static readonly string GivenName = "given_name"; + [Description("姓")] + public static readonly string FamilyName = "family_name"; + [Description("中间名")] + public static readonly string MiddleName = "middle_name"; + [Description("昵称")] + public static readonly string NickName = "nickname"; + [Description("希望被称呼的名字")] + public static readonly string PreferredUserName = "preferred_username"; + [Description("基础资料")] + public static readonly string Profile = "profile"; + [Description("头像")] + public static readonly string Picture = "picture"; + [Description("网站链接")] + public static readonly string WebSite = "website"; + [Description("电子邮箱")] + public static readonly string Email = "email"; + [Description("邮箱是否被认证")] + public static readonly string EmailVerified = "email_verified"; + [Description("性别")] + public static readonly string Gender = "gender"; + [Description("生日")] + public static readonly string BirthDate = "birthdate"; + [Description("时区")] + public static readonly string ZoneInfo = "zoneinfo"; + [Description("区域")] + public static readonly string Locale = "locale"; + [Description("手机号")] + public static readonly string PhoneNumber = "phone_number"; + [Description("认证手机号")] + public static readonly string PhoneNumberVerified = "phone_number_verified"; + [Description("地址")] + public static readonly string Address = "address"; + [Description("详细地址")] + public static readonly string Formatted = "formatted"; + [Description("街道地址")] + public static readonly string StreetAddress = "street_address"; + [Description("城市")] + public static readonly string Locality = "locality"; + [Description("省")] + public static readonly string Region = "region"; + [Description("邮编")] + public static readonly string PostalCode = "postal_code"; + [Description("国家")] + public static readonly string Country = "country"; + [Description("信息更新时间")] + public static readonly string UpdatedAt = "updated_at"; + + static Dictionary? _claims; + + public static Dictionary Claims => _claims ??= GetClaims(); + + static Dictionary GetClaims() + { + var claims = new Dictionary(); + var fileds = typeof(StandardUserClaims).GetFields(BindingFlags.Static | BindingFlags.Public); + foreach (var filed in fileds) + { + var value = filed.GetValue(null)?.ToString() ?? ""; + var description = filed.GetCustomAttribute()?.Description ?? ""; + claims.Add(value, description); + } + + return claims; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/AccessTokenType.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/AccessTokenType.cs new file mode 100644 index 0000000..f49e96f --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/AccessTokenType.cs @@ -0,0 +1,13 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Enums; + +public enum AccessTokenType +{ + [Description("Self-contained Json Web Token")] + Jwt, + [Description("Reference token")] + Reference +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenExpiration.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenExpiration.cs new file mode 100644 index 0000000..8a3e0dd --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenExpiration.cs @@ -0,0 +1,13 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Enums; + +public enum TokenExpiration +{ + [Description("Sliding token expiration")] + Sliding, + [Description("Absolute token expiration")] + Absolute +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenUsage.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenUsage.cs new file mode 100644 index 0000000..52ffd7e --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Enums/TokenUsage.cs @@ -0,0 +1,13 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Enums; + +public enum TokenUsage +{ + [Description("Re-use the refresh token handle")] + Reuse, + [Description("Issue a new refresh token handle every time")] + OneTimeOnly +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Masa.BuildingBlocks.Authentication.Oidc.Models.csproj b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Masa.BuildingBlocks.Authentication.Oidc.Models.csproj new file mode 100644 index 0000000..132c02c --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Masa.BuildingBlocks.Authentication.Oidc.Models.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiResourceModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiResourceModel.cs new file mode 100644 index 0000000..7e27dd8 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiResourceModel.cs @@ -0,0 +1,50 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class ApiResourceModel : ResourceModel +{ + public ICollection? Scopes { get; set; } + + public ICollection? ApiSecrets { get; set; } + + public ICollection? AllowedAccessTokenSigningAlgorithms { get; set; } + + public ApiResourceModel() + { + + } + + public ApiResourceModel( + string name, + string? displayName = null, + ICollection? userClaims = null) + { + Name = name; + DisplayName = displayName ?? name; + if (userClaims is not null) UserClaims = userClaims; + } + + public ApiResourceModel( + string name, + string displayName, + string? description, + bool enabled, + bool showInDiscoveryDocument, + ICollection? userClaims, + ICollection? scopes, + IDictionary properties, + ICollection? apiSecrets, + ICollection? allowedAccessTokenSigningAlgorithms) : this(name, displayName, userClaims) + { + Description = description; + Enabled = enabled; + ShowInDiscoveryDocument = showInDiscoveryDocument; + Scopes = scopes; + Properties = properties; + ApiSecrets = apiSecrets; + AllowedAccessTokenSigningAlgorithms = allowedAccessTokenSigningAlgorithms; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiScopeModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiScopeModel.cs new file mode 100644 index 0000000..5842921 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ApiScopeModel.cs @@ -0,0 +1,46 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class ApiScopeModel : ResourceModel +{ + public bool Required { get; set; } + + public bool Emphasize { get; set; } + + public ApiScopeModel() + { + + } + + public ApiScopeModel( + string name, + string? displayName = null, + ICollection? userClaims = null) + { + Name = name; + DisplayName = displayName ?? name; + if (userClaims is not null) UserClaims = userClaims; + } + + public ApiScopeModel( + string name, + string displayName, + string? description, + bool enabled, + bool showInDiscoveryDocument, + bool required, + bool emphasize, + ICollection? userClaims, + Dictionary properties) : this(name, displayName, userClaims) + { + Description = description; + Enabled = enabled; + ShowInDiscoveryDocument = showInDiscoveryDocument; + Required = required; + Emphasize = emphasize; + Properties = properties; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientClaimModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientClaimModel.cs new file mode 100644 index 0000000..7b37e0d --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientClaimModel.cs @@ -0,0 +1,59 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class ClientClaimModel +{ + /// + /// The claim type + /// + public string Type { get; set; } + + /// + /// The claim value + /// + public string Value { get; set; } + + /// + /// The claim value type + /// + public string ValueType { get; set; } = ClaimValueTypes.String; + + /// + /// ctor + /// + public ClientClaimModel(string type, string value, string? valueType = null) + { + Type = type; + Value = value; + if (valueType is not null) ValueType = valueType; + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + + hash = hash * 23 + Value.GetHashCode(); + hash = hash * 23 + Type.GetHashCode(); + hash = hash * 23 + ValueType.GetHashCode(); + return hash; + } + } + + public override bool Equals(object? obj) + { + if (obj is null) return false; + if (obj is ClientClaimModel c) + { + return string.Equals(Type, c.Type, StringComparison.Ordinal) && + string.Equals(Value, c.Value, StringComparison.Ordinal) && + string.Equals(ValueType, c.ValueType, StringComparison.Ordinal); + } + + return false; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientModel.cs new file mode 100644 index 0000000..d9522b5 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ClientModel.cs @@ -0,0 +1,227 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class ClientModel +{ + private IEnumerable? _allowedGrantTypes; + private IEnumerable? _apiScopes; + + public string ClientId { get; set; } + + public string ClientName { get; set; } + + public string Description { get; set; } + + public string ClientUri { get; set; } + + public string LogoUri { get; set; } + + public IEnumerable ClientSecrets { get; set; } + + public IEnumerable RedirectUris { get; set; } + + public IEnumerable PostLogoutRedirectUris { get; set; } + + public IEnumerable AllowedGrantTypes + { + get + { + if (_allowedGrantTypes is null) throw new Exception("Please set Client.GrantTypes"); + ValidateGrantTypes(_allowedGrantTypes); + return _allowedGrantTypes.Distinct(); + } + set + { + ValidateGrantTypes(value); + _allowedGrantTypes = value; + } + } + + public IEnumerable AllowedScopes + { + get => _apiScopes?.Distinct() ?? throw new Exception("Please set Client.AllowedScopes"); + set => _apiScopes = value; + } + + /// + /// Signing algorithm for identity token. If empty, will use the server default signing + /// + public IEnumerable? AllowedIdentityTokenSigningAlgorithms { get; set; } + + /// + /// Allows settings claims for the client (will be included in the access token) + /// + public ICollection? Claims { get; set; } + + /// + /// Gets or sets the allowed CORS origins for JavaScript clients. + /// + public ICollection? AllowedCorsOrigins { get; set; } + + /// + /// Gets or sets the custom properties for the client. + /// + public IDictionary Properties { get; set; } = new Dictionary(); + + /// + /// Specifies which external IdPs can be used with this client (if list is empty + /// all IdPs are allowed). Defaults to empty. + /// + public ICollection IdentityProviderRestrictions { get; set; } = new HashSet(); + + public bool RequireConsent { get; set; } + + public bool RequireClientSecret { get; set; } = true; + + public bool Enabled { get; set; } = true; + + public bool AllowRememberConsent { get; set; } = true; + + public bool RequirePkce { get; set; } = true; + + public bool AllowPlainTextPkce { get; set; } + + public bool RequireRequestObject { get; set; } + + public bool AllowAccessTokensViaBrowser { get; set; } + + public bool AllowOfflineAccess { get; set; } + + public bool AlwaysIncludeUserClaimsInIdToken { get; set; } + + public bool BackChannelLogoutSessionRequired { get; set; } = true; + + /// + /// Gets or sets a value indicating whether JWT access tokens should include an identifier. + /// + public bool IncludeJwtId { get; set; } = true; + + /// + /// Gets or sets a value indicating whether client claims should be always included + /// in the access tokens - or only for client credentials flow. Defaults to false + /// + public bool AlwaysSendClientClaims { get; set; } + + /// + /// Gets or sets a value indicating whether the local login is allowed for this client.Defaults to true. + /// + public bool EnableLocalLogin { get; set; } = true; + + /// + /// Gets or sets a value indicating whether the access token (and its claims) should + /// be updated on a refresh token request. Defaults to false. + /// + public bool UpdateAccessTokenClaimsOnRefresh { get; set; } + + /// + /// Lifetime of identity token in seconds (defaults to 300 seconds / 5 minutes) + /// + public int IdentityTokenLifetime { get; set; } = 300; + + /// + /// Lifetime of access token in seconds (defaults to 3600 seconds / 1 hour) + /// + public int AccessTokenLifetime { get; set; } = 3600; + + /// + /// Lifetime of authorization code in seconds (defaults to 300 seconds / 5 minutes) + /// + public int AuthorizationCodeLifetime { get; set; } = 300; + + /// + /// Maximum lifetime of a refresh token in seconds (defaults to 2592000 seconds / 30 days) + /// + public int AbsoluteRefreshTokenLifetime { get; set; } = 2592000; + + /// + /// Sliding lifetime of a refresh token in seconds (defaults to 1296000 seconds / 15 days) + /// + public int SlidingRefreshTokenLifetime { get; set; } = 1296000; + + /// + /// Lifetime of a user consent in seconds. Defaults to null (no expiration) + /// + public int? ConsentLifetime { get; set; } + + /// + /// The maximum duration (in seconds) since the last time the user authenticated. + /// + public int? UserSsoLifetime { get; set; } + + /// + /// Gets or sets the device code lifetime. + /// + public int DeviceCodeLifetime { get; set; } = 300; + + /// + /// Absolute: the refresh token will expire on a fixed point in time (specified by + /// the AbsoluteRefreshTokenLifetime) Sliding: when refreshing the token, the lifetime + /// of the refresh token will be renewed(by the amount specified in SlidingRefreshTokenLifetime). + /// he lifetime will not exceed AbsoluteRefreshTokenLifetime. + /// + public TokenExpiration RefreshTokenExpiration { get; set; } = TokenExpiration.Absolute; + + /// + /// ReUse:the refresh token handle will stay the same when refreshing tokens + /// OneTimeOnly:the refresh token handle will be updated when refreshing tokens + /// Default value OneTimeOnly + /// + public TokenUsage RefreshTokenUsage { get; set; } = TokenUsage.OneTimeOnly; + + public AccessTokenType AccessTokenType { get; set; } + + public string ProtocolType { get; set; } = "oidc"; + + public string? FrontChannelLogoutUri { get; set; } + + public bool FrontChannelLogoutSessionRequired { get; set; } = true; + + public string? BackChannelLogoutUri { get; set; } + + /// + /// Gets or sets a value to prefix it on client claim types. Defaults to client_. + /// + public string ClientClaimsPrefix { get; set; } = "client_"; + + /// + /// Gets or sets a salt value used in pair-wise subjectId generation for users of + /// this client. + /// + public string? PairWiseSubjectSalt { get; set; } + + /// + /// Gets or sets the type of the device flow user code. + /// + public string? UserCodeType { get; set; } + + public ClientModel(string clientId, string clientName, string description, string clientUri, string logoUri, IEnumerable redirectUris, IEnumerable postLogoutRedirectUris, IEnumerable allowedGrantTypes, IEnumerable allowedScopes) + { + ClientId = clientId; + ClientName = clientName; + Description = description; + ClientUri = clientUri; + LogoUri = logoUri; + RedirectUris = redirectUris; + PostLogoutRedirectUris = postLogoutRedirectUris; + AllowedGrantTypes = allowedGrantTypes; + AllowedScopes = allowedScopes; + } + + private static void ValidateGrantTypes(IEnumerable grantTypes) + { + if (grantTypes.Any(grantType => grantType.Contains(' '))) + throw new InvalidOperationException("Grant types cannot contain spaces"); + + if (grantTypes.Count() != 1) + { + foreach (var (value1, value2) in GrantType.DisallowGrantTypeCombinations) + { + if (grantTypes.Contains(value1, StringComparer.Ordinal) && grantTypes.Contains(value2, StringComparer.Ordinal)) + throw new InvalidOperationException($"Grant types list cannot contain both {value1} and {value2}"); + } + } + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/DeviceCodeModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/DeviceCodeModel.cs new file mode 100644 index 0000000..a8762ad --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/DeviceCodeModel.cs @@ -0,0 +1,113 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +/// +/// Represents data needed for device flow. +/// +public class DeviceCodeModel +{ + /// + /// Gets or sets the creation time. + /// + /// + /// The creation time. + /// + public DateTime CreationTime { get; set; } + + /// + /// Gets or sets the lifetime. + /// + /// + /// The lifetime. + /// + public int Lifetime { get; set; } + + /// + /// Gets or sets the client identifier. + /// + /// + /// The client identifier. + /// + public string ClientId { get; set; } + + /// + /// Gets the description the user assigned to the device being authorized. + /// + /// + /// The description. + /// + public string Description { get; set; } + + /// + /// Gets or sets a value indicating whether this instance is open identifier. + /// + /// + /// true if this instance is open identifier; otherwise, false. + /// + public bool IsOpenId { get; set; } + + /// + /// Gets or sets a value indicating whether this instance is authorized. + /// + /// + /// true if this instance is authorized; otherwise, false. + /// + public bool IsAuthorized { get; set; } + + /// + /// Gets or sets the requested scopes. + /// + /// + /// The authorized scopes. + /// + public IEnumerable RequestedScopes { get; set; } + + /// + /// Gets or sets the authorized scopes. + /// + /// + /// The authorized scopes. + /// + public IEnumerable AuthorizedScopes { get; set; } + + /// + /// Gets or sets the subject. + /// + /// + /// The subject. + /// + public ClaimsPrincipal Subject { get; set; } + + /// + /// Gets or sets the session identifier. + /// + /// + /// The session identifier. + /// + public string SessionId { get; set; } + + public DeviceCodeModel( + DateTime creationTime, + int lifetime, + string clientId, + string description, + bool isOpenId, + bool isAuthorized, + IEnumerable requestedScopes, + IEnumerable authorizedScopes, + ClaimsPrincipal subject, string sessionId) + { + CreationTime = creationTime; + Lifetime = lifetime; + ClientId = clientId; + Description = description; + IsOpenId = isOpenId; + IsAuthorized = isAuthorized; + RequestedScopes = requestedScopes; + AuthorizedScopes = authorizedScopes; + Subject = subject; + SessionId = sessionId; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/GrantType.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/GrantType.cs new file mode 100644 index 0000000..5e74f68 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/GrantType.cs @@ -0,0 +1,22 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class GrantType +{ + public const string Implicit = "implicit"; + public const string Hybrid = "hybrid"; + public const string AuthorizationCode = "authorization_code"; + public const string ClientCredentials = "client_credentials"; + public const string ResourceOwnerPassword = "password"; + public const string DeviceFlow = "urn:ietf:params:oauth:grant-type:device_code"; + + public static List<(string, string)> DisallowGrantTypeCombinations = new() + { + (Implicit, AuthorizationCode), + (Implicit, Hybrid), + (AuthorizationCode, Hybrid), + }; +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/IdentityResourceModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/IdentityResourceModel.cs new file mode 100644 index 0000000..523a33b --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/IdentityResourceModel.cs @@ -0,0 +1,48 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class IdentityResourceModel : ResourceModel +{ + public bool Required { get; set; } + + public bool Emphasize { get; set; } + + public override ICollection UserClaims { get; set; } + + public IdentityResourceModel() + { + } + + public IdentityResourceModel(string name, string displayName, ICollection userClaims) + { + Name = name; + DisplayName = displayName; + UserClaims = userClaims; + } + + public IdentityResourceModel(string name, ICollection userClaims) : this(name, name, userClaims) + { + } + + public IdentityResourceModel( + string name, + string displayName, + string? description, + bool enabled, + bool showInDiscoveryDocument, + bool required, + bool emphasize, + ICollection userClaims, + IDictionary properties) : this(name, displayName, userClaims) + { + Description = description; + Enabled = enabled; + ShowInDiscoveryDocument = showInDiscoveryDocument; + Required = required; + Emphasize = emphasize; + Properties = properties; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantFilter.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantFilter.cs new file mode 100644 index 0000000..b59ec20 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantFilter.cs @@ -0,0 +1,44 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +/// +/// Represents a filter used when accessing the persisted grants store. +/// Setting multiple properties is interpreted as a logical 'AND' to further filter the query. +/// At least one value must be supplied. +/// +public class PersistedGrantFilter +{ + /// + /// Subject id of the user. + /// + public string SubjectId { get; set; } + + /// + /// Session id used for the grant. + /// + public string SessionId { get; set; } + + /// + /// Client id the grant was issued to. + /// + public string ClientId { get; set; } + + /// + /// The type of grant. + /// + public string Type { get; set; } + + public PersistedGrantFilter( + string subjectId, + string sessionId, + string clientId, + string type) + { + SubjectId = subjectId; + SessionId = sessionId; + ClientId = clientId; + Type = type; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantModel.cs new file mode 100644 index 0000000..8616114 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/PersistedGrantModel.cs @@ -0,0 +1,114 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +/// +/// A model for a persisted grant +/// +public class PersistedGrantModel +{ + /// + /// Gets or sets the key. + /// + /// + /// The key. + /// + public string Key { get; set; } + + /// + /// Gets the type. + /// + /// + /// The type. + /// + public string Type { get; set; } + + /// + /// Gets the subject identifier. + /// + /// + /// The subject identifier. + /// + public string SubjectId { get; set; } + + /// + /// Gets the session identifier. + /// + /// + /// The session identifier. + /// + public string SessionId { get; set; } + + /// + /// Gets the client identifier. + /// + /// + /// The client identifier. + /// + public string ClientId { get; set; } + + /// + /// Gets the description the user assigned to the device being authorized. + /// + /// + /// The description. + /// + public string Description { get; set; } + + /// + /// Gets or sets the creation time. + /// + /// + /// The creation time. + /// + public DateTime CreationTime { get; set; } + + /// + /// Gets or sets the expiration. + /// + /// + /// The expiration. + /// + public DateTime? Expiration { get; set; } + + /// + /// Gets or sets the consumed time. + /// + /// + /// The consumed time. + /// + public DateTime? ConsumedTime { get; set; } + + /// + /// Gets or sets the data. + /// + /// + /// The data. + /// + public string Data { get; set; } + + public PersistedGrantModel( + string key, + string type, + string subjectId, + string sessionId, + string clientId, + string description, + DateTime creationTime, + DateTime? expiration, + DateTime? consumedTime, + string data) + { + Key = key; + Type = type; + SubjectId = subjectId; + SessionId = sessionId; + ClientId = clientId; + Description = description; + CreationTime = creationTime; + Expiration = expiration; + ConsumedTime = consumedTime; + Data = data; + } +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourceModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourceModel.cs new file mode 100644 index 0000000..a9da1fd --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourceModel.cs @@ -0,0 +1,23 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public abstract class ResourceModel +{ + public bool Enabled { get; set; } = true; + + public string Name { get; set; } = ""; + + public string DisplayName { get; set; } = ""; + + public string? Description { get; set; } + + public bool ShowInDiscoveryDocument { get; set; } = true; + + [DisallowNull] + public virtual ICollection UserClaims { get; set; } = new HashSet(); + + public IDictionary Properties { get; set; } = new Dictionary(); +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourcesModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourcesModel.cs new file mode 100644 index 0000000..44df9f5 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/ResourcesModel.cs @@ -0,0 +1,45 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class ResourcesModel +{ + /// + /// Gets or sets a value indicating whether [offline access]. + /// + public bool OfflineAccess { get; set; } + + public IEnumerable IdentityResources { get; set; } = new HashSet(); + + public IEnumerable ApiResources { get; set; } = new HashSet(); + + public IEnumerable ApiScopes { get; set; } = new HashSet(); + + public ResourcesModel() + { + } + + public ResourcesModel(ResourcesModel other) + : this(other.IdentityResources, other.ApiResources, other.ApiScopes) + { + OfflineAccess = other.OfflineAccess; + } + + public ResourcesModel(IEnumerable identityResources, IEnumerable apiResources, IEnumerable apiScopes) + { + if (identityResources?.Any() == true) + { + IdentityResources = new HashSet(identityResources.ToArray()); + } + if (apiResources?.Any() == true) + { + ApiResources = new HashSet(apiResources.ToArray()); + } + if (apiScopes?.Any() == true) + { + ApiScopes = new HashSet(apiScopes.ToArray()); + } + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/SecretModel.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/SecretModel.cs new file mode 100644 index 0000000..77406b3 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/Models/SecretModel.cs @@ -0,0 +1,40 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Models.Models; + +public class SecretModel +{ + public string? Value { get; set; } + + public string? Description { get; set; } + + public DateTime? Expiration { get; set; } + + public string Type { get; set; } = "SharedSecret"; + + public SecretModel(string? value = null, string? description = null, DateTime? expiration = null) + { + Value = value; + Description = description; + Expiration = expiration; + } + + public override int GetHashCode() + { + return (17 * 23 + (Value?.GetHashCode() ?? 0)) * 23 + Type.GetHashCode(); + } + + public override bool Equals(object? obj) + { + if (obj is null) return false; + if (obj is SecretModel secret) + { + if (secret == this) return true; + return string.Equals(secret.Type, Type, StringComparison.Ordinal) && string.Equals(secret.Value, Value, StringComparison.Ordinal); + } + + return false; + } +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/_Imports.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/_Imports.cs new file mode 100644 index 0000000..e5b4332 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Models/_Imports.cs @@ -0,0 +1,9 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +global using Masa.BuildingBlocks.Authentication.Oidc.Models.Enums; +global using Masa.BuildingBlocks.Authentication.Oidc.Models.Models; +global using System.ComponentModel; +global using System.Diagnostics.CodeAnalysis; +global using System.Reflection; +global using System.Security.Claims; diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Masa.BuildingBlocks.Authentication.Oidc.Storage.csproj b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Masa.BuildingBlocks.Authentication.Oidc.Storage.csproj new file mode 100644 index 0000000..ed98caa --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Masa.BuildingBlocks.Authentication.Oidc.Storage.csproj @@ -0,0 +1,16 @@ + + + + net6.0 + enable + enable + + $(WarningsAsErrors);CS8600;CS8601;CS8602;CS8603;CS8604;CS8609;CS8610;CS8614;CS8616;CS8618;CS8619;CS8620;CS8622;CS8625 + + + + + + + + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IClientStore.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IClientStore.cs new file mode 100644 index 0000000..976845a --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IClientStore.cs @@ -0,0 +1,14 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Storage.Stores; + +public interface IClientStore +{ + /// + /// Finds a client by id + /// + /// The client id + /// The client + Task FindClientByIdAsync(string clientId); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IDeviceFlowStore.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IDeviceFlowStore.cs new file mode 100644 index 0000000..4875f3e --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IDeviceFlowStore.cs @@ -0,0 +1,45 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Storage.Stores; + +/// +/// Interface for the device flow store +/// +public interface IDeviceFlowStore +{ + /// + /// Stores the device authorization request. + /// + /// The device code. + /// The user code. + /// The data. + /// + Task StoreDeviceAuthorizationAsync(string deviceCode, string userCode, DeviceCodeModel data); + + /// + /// Finds device authorization by user code. + /// + /// The user code. + /// + Task FindByUserCodeAsync(string userCode); + + /// + /// Finds device authorization by device code. + /// + /// The device code. + Task FindByDeviceCodeAsync(string deviceCode); + + /// + /// Updates device authorization, searching by user code. + /// + /// The user code. + /// The data. + Task UpdateByUserCodeAsync(string userCode, DeviceCodeModel data); + + /// + /// Removes the device authorization, searching by device code. + /// + /// The device code. + Task RemoveByDeviceCodeAsync(string deviceCode); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IPersistedGrantStore.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IPersistedGrantStore.cs new file mode 100644 index 0000000..b08e71f --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IPersistedGrantStore.cs @@ -0,0 +1,45 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Storage.Stores; + +/// +/// Interface for persisting any type of grant. +/// +public interface IPersistedGrantStore +{ + /// + /// Stores the grant. + /// + /// The grant. + /// + Task StoreAsync(PersistedGrantModel grant); + + /// + /// Gets the grant. + /// + /// The key. + /// + Task GetAsync(string key); + + /// + /// Gets all grants based on the filter. + /// + /// The filter. + /// + Task> GetAllAsync(PersistedGrantFilter filter); + + /// + /// Removes the grant by key. + /// + /// The key. + /// + Task RemoveAsync(string key); + + /// + /// Removes all grants based on the filter. + /// + /// The filter. + /// + Task RemoveAllAsync(PersistedGrantFilter filter); +} diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IResourceStore.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IResourceStore.cs new file mode 100644 index 0000000..45aebca --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/Stores/IResourceStore.cs @@ -0,0 +1,42 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.BuildingBlocks.Authentication.Oidc.Storage.Stores; + +public interface IResourceStore +{ + /// + /// Gets identity resources by scope name. + /// + /// + /// + Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames); + + /// + /// Gets API scopes by scope name. + /// + /// + /// + Task> FindApiScopesByNameAsync(IEnumerable scopeNames); + + /// + /// Gets API resources by scope name. + /// + /// + /// + Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames); + + /// + /// Gets API resources by API resource name. + /// + /// + /// + Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames); + + /// + /// Gets all resources. + /// + /// + Task GetAllResourcesAsync(); +} + diff --git a/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/_Imports.cs b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/_Imports.cs new file mode 100644 index 0000000..c045e84 --- /dev/null +++ b/src/Authentication/Masa.BuildingBlocks.Authentication.Oidc.Storage/_Imports.cs @@ -0,0 +1,4 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +global using Masa.BuildingBlocks.Authentication.Oidc.Models.Models;