diff --git a/Update-OctopusReferences.ps1 b/Update-OctopusReferences.ps1 new file mode 100644 index 0000000..f12a077 --- /dev/null +++ b/Update-OctopusReferences.ps1 @@ -0,0 +1,8 @@ +# Run this script after installing a new version of Octopus Server, but before starting it (due to file lock and dependency load issues). + +$OctopusServerBinaryLocation = "E:\Program Files\Octopus Deploy\Octopus" # Make sure this points to where you install the Octopus Server binaries +$OctopusServerCustomExtensionsLocation = "C:\ProgramData\Octopus\CustomExtensions\" # This should always point to where the Octopus Server CustomExtenions folder lives + +Copy-Item "$OctopusServerBinaryLocation\Octopus.Data.dll" -Destination "$OctopusServerCustomExtensionsLocation" -Force +Copy-Item "$OctopusServerBinaryLocation\Octopus.Server.Extensibility.Authentication.dll" -Destination "$OctopusServerCustomExtensionsLocation" -Force +Copy-Item "$OctopusServerBinaryLocation\BuiltInExtensions\Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.dll" -Destination "$OctopusServerCustomExtensionsLocation" -Force diff --git a/source/Client.AzureAD/Client.AzureAD.csproj b/source/Client.AzureAD/Client.AzureAD.csproj index 0fee24f..9d89ea7 100644 --- a/source/Client.AzureAD/Client.AzureAD.csproj +++ b/source/Client.AzureAD/Client.AzureAD.csproj @@ -24,5 +24,9 @@ - + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Client.dll + + diff --git a/source/Client.AzureAD/Configuration/AzureADConfigurationResource.cs b/source/Client.AzureAD/Configuration/AzureADConfigurationResource.cs index 6e37802..68cf93b 100644 --- a/source/Client.AzureAD/Configuration/AzureADConfigurationResource.cs +++ b/source/Client.AzureAD/Configuration/AzureADConfigurationResource.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using Octopus.Client.Extensibility.Attributes; using Octopus.Client.Extensibility.Authentication.OpenIDConnect.Configuration; +using Octopus.Client.Model; namespace Octopus.Client.Extensibility.Authentication.AzureAD.Configuration { @@ -16,5 +17,10 @@ public AzureADConfigurationResource() [Description("Tell Octopus how to find the roles/groups in the security token from Azure Active Directory (usually \"roles\" or \"groups\")")] [Writeable] public string RoleClaimType { get; set; } + + [DisplayName("Client Access Key")] + [Description("The Azure app registration secret access key. This is used for authenticating against the Azure GraphAPI for group overage lookups. If left blank it will disable Azure GraphAPI lookups. [Learn more](https://github.com/StephenShamakian/OpenIDConnectAuthenticationProviders#readme)")] + [Writeable] + public SensitiveValue ClientKey { get; set; } } } \ No newline at end of file diff --git a/source/Client.GoogleApps/Client.GoogleApps.csproj b/source/Client.GoogleApps/Client.GoogleApps.csproj deleted file mode 100644 index 1751093..0000000 --- a/source/Client.GoogleApps/Client.GoogleApps.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - net6.0 - Octopus.Client.Extensibility.Authentication.GoogleApps - Octopus.Client.Extensibility.Authentication.GoogleApps - en-US - Octopus Deploy - Octopus Deploy Pty. Ltd. - Octopus Deploy Client Extensibility - Octopus Deploy Client Extensibility for Google Apps - Octopus.Client.Extensibility.Authentication.GoogleApps - icon.png - LICENSE.txt - https://github.com/OctopusDeploy/OpenIDConnectAuthenticationProviders - - - - - - - - - - - - diff --git a/source/Client.GoogleApps/Configuration/GoogleAppsConfigurationResource.cs b/source/Client.GoogleApps/Configuration/GoogleAppsConfigurationResource.cs deleted file mode 100644 index adb9c28..0000000 --- a/source/Client.GoogleApps/Configuration/GoogleAppsConfigurationResource.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.ComponentModel; -using Octopus.Client.Extensibility.Attributes; -using Octopus.Client.Extensibility.Authentication.OpenIDConnect.Configuration; - -namespace Octopus.Client.Extensibility.Authentication.GoogleApps.Configuration -{ - [Description("Sign in to your Octopus Server with Google Apps. [Learn more](https://g.octopushq.com/AuthGoogleApps).")] - public class GoogleAppsConfigurationResource : OpenIDConnectConfigurationResource - { - public GoogleAppsConfigurationResource() - { - Id = "authentication-googleapps"; - } - - [DisplayName("Hosted Domain")] - [Description("Tell Octopus which Google Apps domain to trust")] - [Writeable] - public string HostedDomain { get; set; } - } -} \ No newline at end of file diff --git a/source/Client.OctopusID/Client.OctopusID.csproj b/source/Client.OctopusID/Client.OctopusID.csproj deleted file mode 100644 index 62e81e2..0000000 --- a/source/Client.OctopusID/Client.OctopusID.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - net6.0 - Octopus.Client.Extensibility.Authentication.OctopusID - Octopus.Client.Extensibility.Authentication.OctopusID - en-US - Octopus Deploy - Octopus Deploy Pty. Ltd. - Octopus Deploy Client Extensibility - Octopus Deploy Client Extensibility for OctopusID - Octopus.Client.Extensibility.Authentication.OctopusID - icon.png - LICENSE.txt - https://github.com/OctopusDeploy/OpenIDConnectAuthenticationProviders - - - - - - - - - - - - diff --git a/source/Client.OctopusID/Configuration/OctopusIDConfigurationResource.cs b/source/Client.OctopusID/Configuration/OctopusIDConfigurationResource.cs deleted file mode 100644 index 2df8795..0000000 --- a/source/Client.OctopusID/Configuration/OctopusIDConfigurationResource.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel; -using Octopus.Client.Extensibility.Attributes; -using Octopus.Client.Extensibility.Authentication.OpenIDConnect.Configuration; - -namespace Octopus.Client.Extensibility.Authentication.OctopusID.Configuration -{ - [Description("Sign in to your Octopus Server with your Octopus ID. [Learn more](https://g.octopushq.com/AuthOctopusID).")] - public class OctopusIDConfigurationResource : OpenIDConnectConfigurationResource - { - public OctopusIDConfigurationResource() - { - Id = "authentication-octopusid"; - } - } -} \ No newline at end of file diff --git a/source/Client.Okta/Client.Okta.csproj b/source/Client.Okta/Client.Okta.csproj deleted file mode 100644 index c3956d5..0000000 --- a/source/Client.Okta/Client.Okta.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - net6.0 - Octopus.Client.Extensibility.Authentication.Okta - Octopus.Client.Extensibility.Authentication.Okta - en-US - Octopus Deploy - Octopus Deploy Pty. Ltd. - Octopus Deploy Client Extensibility - Octopus Deploy Client Extensibility for Okta - Octopus.Client.Extensibility.Authentication.Okta - icon.png - LICENSE.txt - https://github.com/OctopusDeploy/OpenIDConnectAuthenticationProviders - - - - - - - - - - - - diff --git a/source/Client.Okta/Configuration/OktaConfigurationResource.cs b/source/Client.Okta/Configuration/OktaConfigurationResource.cs deleted file mode 100644 index aa640c1..0000000 --- a/source/Client.Okta/Configuration/OktaConfigurationResource.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel; -using Octopus.Client.Extensibility.Attributes; -using Octopus.Client.Extensibility.Authentication.OpenIDConnect.Configuration; - -namespace Octopus.Client.Extensibility.Authentication.Okta.Configuration -{ - [Description("Sign in to your Octopus Server with Okta. [Learn more](https://g.octopushq.com/AuthOkta).")] - public class OktaConfigurationResource : OpenIDConnectConfigurationResource - { - public OktaConfigurationResource() - { - Id = "authentication-od"; - } - - [DisplayName("Role Claim Type")] - [Description("Tell Octopus how to find the roles in the security token from Okta")] - [Writeable] - public string RoleClaimType { get; set; } - - [DisplayName("Username Claim Type")] - [Description("Tell Octopus how to find the value for the Octopus Username in the Okta token. Defaults to \"preferred_username\" if left blank.")] - [Writeable] - public string UsernameClaimType { get; set; } - } -} \ No newline at end of file diff --git a/source/Client.OpenIDConnect/Client.OpenIDConnect.csproj b/source/Client.OpenIDConnect/Client.OpenIDConnect.csproj index 3a9c2c6..ceb15fa 100644 --- a/source/Client.OpenIDConnect/Client.OpenIDConnect.csproj +++ b/source/Client.OpenIDConnect/Client.OpenIDConnect.csproj @@ -15,13 +15,13 @@ https://github.com/OctopusDeploy/OpenIDConnectAuthenticationProviders - - - - - + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Client.dll + + diff --git a/source/OpenIDConnectAuthenticationProvider.sln b/source/OpenIDConnectAuthenticationProvider.sln index 7705cab..f878e6f 100644 --- a/source/OpenIDConnectAuthenticationProvider.sln +++ b/source/OpenIDConnectAuthenticationProvider.sln @@ -13,26 +13,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server.OpenIDConnect.Common EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server.AzureAD", "Server.AzureAD\Server.AzureAD.csproj", "{8CBCE54C-D501-4ED8-A716-DE64AE5198DA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server.GoogleApps", "Server.GoogleApps\Server.GoogleApps.csproj", "{6796E715-F1FA-445D-AF1F-F6C9023A8D07}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server.Okta", "Server.Okta\Server.Okta.csproj", "{3C7C3079-DF0E-484F-8556-10B18127450B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C354DA8E-D532-4DAE-8D61-E4F50A0139C8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{00680371-A6E1-435F-9966-2450C2723E91}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client.OpenIDConnect", "Client.OpenIDConnect\Client.OpenIDConnect.csproj", "{2B189A86-73DB-495F-B2B7-104672DB1580}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client.AzureAD", "Client.AzureAD\Client.AzureAD.csproj", "{A0DD0DD3-B040-45D7-A4E3-C4601C63D8B9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client.GoogleApps", "Client.GoogleApps\Client.GoogleApps.csproj", "{30B0B7CB-8DF3-4DA0-9956-83CCCAD8694F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client.Okta", "Client.Okta\Client.Okta.csproj", "{580B0996-346B-44F5-8411-C9F8EA04869D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server.OctopusID", "Server.OctopusID\Server.OctopusID.csproj", "{F0421EFD-B724-4A4F-BC0D-9394B4EE520E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.OctopusID", "Client.OctopusID\Client.OctopusID.csproj", "{4186AB53-9506-4932-AF33-A5D013DA590C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "..\build\_build.csproj", "{C9D46DEE-82B4-48B1-968D-5E2B64B96B18}" EndProject Global @@ -51,18 +35,6 @@ Global {8CBCE54C-D501-4ED8-A716-DE64AE5198DA}.Debug|Any CPU.Build.0 = Debug|Any CPU {8CBCE54C-D501-4ED8-A716-DE64AE5198DA}.Release|Any CPU.ActiveCfg = Release|Any CPU {8CBCE54C-D501-4ED8-A716-DE64AE5198DA}.Release|Any CPU.Build.0 = Release|Any CPU - {6796E715-F1FA-445D-AF1F-F6C9023A8D07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6796E715-F1FA-445D-AF1F-F6C9023A8D07}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6796E715-F1FA-445D-AF1F-F6C9023A8D07}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6796E715-F1FA-445D-AF1F-F6C9023A8D07}.Release|Any CPU.Build.0 = Release|Any CPU - {3C7C3079-DF0E-484F-8556-10B18127450B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C7C3079-DF0E-484F-8556-10B18127450B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C7C3079-DF0E-484F-8556-10B18127450B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C7C3079-DF0E-484F-8556-10B18127450B}.Release|Any CPU.Build.0 = Release|Any CPU - {00680371-A6E1-435F-9966-2450C2723E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {00680371-A6E1-435F-9966-2450C2723E91}.Debug|Any CPU.Build.0 = Debug|Any CPU - {00680371-A6E1-435F-9966-2450C2723E91}.Release|Any CPU.ActiveCfg = Release|Any CPU - {00680371-A6E1-435F-9966-2450C2723E91}.Release|Any CPU.Build.0 = Release|Any CPU {2B189A86-73DB-495F-B2B7-104672DB1580}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2B189A86-73DB-495F-B2B7-104672DB1580}.Debug|Any CPU.Build.0 = Debug|Any CPU {2B189A86-73DB-495F-B2B7-104672DB1580}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -71,28 +43,11 @@ Global {A0DD0DD3-B040-45D7-A4E3-C4601C63D8B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {A0DD0DD3-B040-45D7-A4E3-C4601C63D8B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0DD0DD3-B040-45D7-A4E3-C4601C63D8B9}.Release|Any CPU.Build.0 = Release|Any CPU - {30B0B7CB-8DF3-4DA0-9956-83CCCAD8694F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {30B0B7CB-8DF3-4DA0-9956-83CCCAD8694F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {30B0B7CB-8DF3-4DA0-9956-83CCCAD8694F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {30B0B7CB-8DF3-4DA0-9956-83CCCAD8694F}.Release|Any CPU.Build.0 = Release|Any CPU - {580B0996-346B-44F5-8411-C9F8EA04869D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {580B0996-346B-44F5-8411-C9F8EA04869D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {580B0996-346B-44F5-8411-C9F8EA04869D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {580B0996-346B-44F5-8411-C9F8EA04869D}.Release|Any CPU.Build.0 = Release|Any CPU - {F0421EFD-B724-4A4F-BC0D-9394B4EE520E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F0421EFD-B724-4A4F-BC0D-9394B4EE520E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0421EFD-B724-4A4F-BC0D-9394B4EE520E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0421EFD-B724-4A4F-BC0D-9394B4EE520E}.Release|Any CPU.Build.0 = Release|Any CPU - {4186AB53-9506-4932-AF33-A5D013DA590C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4186AB53-9506-4932-AF33-A5D013DA590C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4186AB53-9506-4932-AF33-A5D013DA590C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4186AB53-9506-4932-AF33-A5D013DA590C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {00680371-A6E1-435F-9966-2450C2723E91} = {C354DA8E-D532-4DAE-8D61-E4F50A0139C8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6EC7C479-5684-490E-B66E-D85F4F015923} diff --git a/source/Server.AzureAD/AzureADApi.cs b/source/Server.AzureAD/AzureADApi.cs index 91ca208..76d3eb4 100644 --- a/source/Server.AzureAD/AzureADApi.cs +++ b/source/Server.AzureAD/AzureADApi.cs @@ -11,12 +11,31 @@ namespace Octopus.Server.Extensibility.Authentication.AzureAD class AzureADApi : OpenIDConnectModule { public AzureADApi( - IAzureADConfigurationStore configurationStore, AzureADAuthenticationProvider authenticationProvider) + IAzureADConfigurationStore configurationStore, + AzureADAuthenticationProvider authenticationProvider) : base(configurationStore, authenticationProvider) { - Add("POST", authenticationProvider.AuthenticateUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("POST", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("GET", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); + Add( + "POST", + authenticationProvider.AuthenticateUri, + RouteCategory.Raw, + new AnonymousWhenEnabledEndpointInvocation(), + null, + "OpenIDConnect"); + Add( + "POST", + configurationStore.RedirectUri, + RouteCategory.Raw, + new AnonymousWhenEnabledEndpointInvocation(), + null, + "OpenIDConnect"); + Add( + "GET", + configurationStore.RedirectUri, + RouteCategory.Raw, + new AnonymousWhenEnabledEndpointInvocation(), + null, + "OpenIDConnect"); } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/AzureADAuthenticationProvider.cs b/source/Server.AzureAD/AzureADAuthenticationProvider.cs index 598bb39..b659041 100644 --- a/source/Server.AzureAD/AzureADAuthenticationProvider.cs +++ b/source/Server.AzureAD/AzureADAuthenticationProvider.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; namespace Octopus.Server.Extensibility.Authentication.AzureAD @@ -10,6 +9,7 @@ namespace Octopus.Server.Extensibility.Authentication.AzureAD class AzureADAuthenticationProvider : OpenIDConnectAuthenticationProvider { public const string ProviderName = "Azure AD"; + public AzureADAuthenticationProvider(ISystemLog log, IAzureADConfigurationStore configurationStore) : base(log, configurationStore) { } @@ -21,11 +21,19 @@ protected override IEnumerable ReasonsWhyConfigIsIncomplete() { var issuer = ConfigurationStore.GetIssuer(); if (string.IsNullOrWhiteSpace(issuer)) + { yield return $"No {IdentityProviderName} issuer specified"; + } + if (!Uri.IsWellFormedUriString(issuer, UriKind.Absolute)) + { yield return $"The {IdentityProviderName} issuer must be an absolute URI (expected format: https://login.microsoftonline.com/[issuer guid])"; + } + if (string.IsNullOrWhiteSpace(ConfigurationStore.GetClientId())) + { yield return $"No {IdentityProviderName} Client ID specified"; + } } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/AzureADExtension.cs b/source/Server.AzureAD/AzureADExtension.cs index 71bf19d..4dfd47f 100644 --- a/source/Server.AzureAD/AzureADExtension.cs +++ b/source/Server.AzureAD/AzureADExtension.cs @@ -1,4 +1,5 @@ -using Autofac; +using System; +using Autofac; using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.AzureAD.Identities; using Octopus.Server.Extensibility.Authentication.AzureAD.Infrastructure; @@ -7,7 +8,6 @@ using Octopus.Server.Extensibility.Authentication.AzureAD.Web; using Octopus.Server.Extensibility.Authentication.Extensions; using Octopus.Server.Extensibility.Authentication.Extensions.Identities; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; @@ -15,12 +15,11 @@ using Octopus.Server.Extensibility.Extensions.Infrastructure; using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; -using Octopus.Server.Extensibility.Extensions.Mappings; using Octopus.Server.Extensibility.HostServices.Web; namespace Octopus.Server.Extensibility.Authentication.AzureAD { - [OctopusPlugin("AzureAD", "Octopus Deploy")] + [OctopusPlugin("AzureAD - GraphAPI Support", "Octopus Deploy (Modified by: Stephen Shamakian)")] public class AzureADExtension : OpenIDConnectExtension, IOctopusExtension { public override void Load(ContainerBuilder builder) @@ -31,18 +30,16 @@ public override void Load(ContainerBuilder builder) builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); + builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().As().SingleInstance(); builder.RegisterType() .As() .InstancePerDependency(); - builder.RegisterType() + builder.RegisterType() .As() - .As() - .As() - .As() + .As() .InstancePerDependency(); builder.RegisterType() .As() @@ -73,4 +70,4 @@ public override void Load(ContainerBuilder builder) .InstancePerDependency(); } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/AzureADConfiguration.cs b/source/Server.AzureAD/Configuration/AzureADConfiguration.cs index adfa681..3799e31 100644 --- a/source/Server.AzureAD/Configuration/AzureADConfiguration.cs +++ b/source/Server.AzureAD/Configuration/AzureADConfiguration.cs @@ -1,4 +1,6 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; +using System; +using Octopus.Data.Model; +using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration { @@ -10,5 +12,6 @@ public AzureADConfiguration() : base(AzureADConfigurationStore.SingletonId, "Azu { RoleClaimType = DefaultRoleClaimType; } + public SensitiveString? ClientKey { get; set; } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/AzureADConfigurationMapping.cs b/source/Server.AzureAD/Configuration/AzureADConfigurationMap.cs similarity index 78% rename from source/Server.AzureAD/Configuration/AzureADConfigurationMapping.cs rename to source/Server.AzureAD/Configuration/AzureADConfigurationMap.cs index 2235caa..a6bfad5 100644 --- a/source/Server.AzureAD/Configuration/AzureADConfigurationMapping.cs +++ b/source/Server.AzureAD/Configuration/AzureADConfigurationMap.cs @@ -3,8 +3,8 @@ namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration { - class AzureADConfigurationMapping : IConfigurationDocumentMapper + class AzureADConfigurationMap : IConfigurationDocumentMap { public Type GetTypeToMap() => typeof(AzureADConfiguration); } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/AzureADConfigurationMapper.cs b/source/Server.AzureAD/Configuration/AzureADConfigurationMapper.cs new file mode 100644 index 0000000..7a99fb4 --- /dev/null +++ b/source/Server.AzureAD/Configuration/AzureADConfigurationMapper.cs @@ -0,0 +1,32 @@ +using System; +using Octopus.Server.Extensibility.HostServices.Mapping; + +namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration +{ + static class AzureADConfigurationMapper + { + public static AzureADConfigurationResource MapToResource(AzureADConfiguration model) => + new() + { + Id = model.Id, + IsEnabled = model.IsEnabled, + AllowAutoUserCreation = model.AllowAutoUserCreation, + Issuer = model.Issuer, + ClientId = model.ClientId, + ClientSecret = model.ClientSecret.ToSensitiveValue(), + ClientKey = model.ClientKey.ToSensitiveValue(), + RoleClaimType = model.RoleClaimType + }; + + public static void ModifyModel(AzureADConfigurationResource resource, AzureADConfiguration model) + { + model.IsEnabled = resource.IsEnabled; + model.AllowAutoUserCreation = resource.AllowAutoUserCreation == true; + model.Issuer = resource.Issuer; + model.ClientId = resource.ClientId; + model.ClientSecret = resource.ClientSecret.ToSensitiveStringOrExisting(model.ClientSecret); + model.ClientKey = resource.ClientKey.ToSensitiveStringOrExisting(model.ClientKey); + model.RoleClaimType = resource.RoleClaimType; + } + } +} diff --git a/source/Server.AzureAD/Configuration/AzureADConfigurationResource.cs b/source/Server.AzureAD/Configuration/AzureADConfigurationResource.cs index f2f32ef..e2184ea 100644 --- a/source/Server.AzureAD/Configuration/AzureADConfigurationResource.cs +++ b/source/Server.AzureAD/Configuration/AzureADConfigurationResource.cs @@ -1,6 +1,7 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.MessageContracts.Attributes; +using Octopus.Server.MessageContracts; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration { @@ -9,7 +10,9 @@ class AzureADConfigurationResource : OpenIDConnectConfigurationResource { [DisplayName("Role Claim Type")] [Description("Tell Octopus how to find the roles/groups in the security token from Azure Active Directory (usually \"roles\" or \"groups\")")] - [Writeable] public string? RoleClaimType { get; set; } + [DisplayName("Client Access Key")] + [Description("The Azure app registration secret access key. This is used for authenticating against the Azure GraphAPI for group overage lookups. If left blank it will disable Azure GraphAPI lookups. [Learn more](https://github.com/StephenShamakian/OpenIDConnectAuthenticationProviders#readme)")] + public SensitiveValue? ClientKey { get; set; } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/AzureADConfigurationSettings.cs b/source/Server.AzureAD/Configuration/AzureADConfigurationSettings.cs deleted file mode 100644 index 9f05b52..0000000 --- a/source/Server.AzureAD/Configuration/AzureADConfigurationSettings.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration -{ - class AzureADConfigurationSettings : OpenIDConnectConfigurationSettings, IAzureADConfigurationSettings - { - public AzureADConfigurationSettings(IAzureADConfigurationStore configurationDocumentStore) : base(configurationDocumentStore) - { - } - - public override string Id => AzureADConfigurationStore.SingletonId; - - public override string Description => "Azure active directory authentication settings"; - - public override IEnumerable GetConfigurationValues() - { - foreach (var configurationValue in base.GetConfigurationValues()) - { - yield return configurationValue; - } - yield return new ConfigurationValue($"Octopus.{ConfigurationDocumentStore.ConfigurationSettingsName}.RoleClaimType", ConfigurationDocumentStore.GetRoleClaimType(), ConfigurationDocumentStore.GetIsEnabled() && ConfigurationDocumentStore.GetRoleClaimType() != AzureADConfiguration.DefaultRoleClaimType, "Role Claim Type"); - } - - } -} \ No newline at end of file diff --git a/source/Server.AzureAD/Configuration/AzureADConfigurationSettingsProvider.cs b/source/Server.AzureAD/Configuration/AzureADConfigurationSettingsProvider.cs new file mode 100644 index 0000000..65e598a --- /dev/null +++ b/source/Server.AzureAD/Configuration/AzureADConfigurationSettingsProvider.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using Octopus.Data.Model; +using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; +using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; + +namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration +{ + class AzureADConfigurationSettingsProvider : OpenIDConnectConfigurationSettingsProvider, IAzureADConfigurationSettings + { + public AzureADConfigurationSettingsProvider(IAzureADConfigurationStore configurationDocumentStore) : base(configurationDocumentStore) + { + } + + public override string Id => AzureADConfigurationStore.SingletonId; + + public override string ConfigurationSetName => "Azure AD"; + + public override string Description => "Azure active directory authentication settings"; + + public override IEnumerable GetConfigurationValues() + { + foreach (var configurationValue in base.GetConfigurationValues()) + { + yield return configurationValue; + } + + yield return new ConfigurationValue($"Octopus.{ConfigurationDocumentStore.ConfigurationSettingsName}.RoleClaimType", ConfigurationDocumentStore.GetRoleClaimType(), ConfigurationDocumentStore.GetIsEnabled() && ConfigurationDocumentStore.GetRoleClaimType() != AzureADConfiguration.DefaultRoleClaimType, "Role Claim Type"); + yield return new ConfigurationValue($"Octopus.{ConfigurationDocumentStore.ConfigurationSettingsName}.ClientKey", ConfigurationDocumentStore.GetClientKey(), ConfigurationDocumentStore.GetIsEnabled(), "Client Access Key"); + } + + protected override AzureADConfigurationResource MapToResource(AzureADConfiguration model) => AzureADConfigurationMapper.MapToResource(model); + protected override void ModifyModel(AzureADConfigurationResource resource, AzureADConfiguration model) => AzureADConfigurationMapper.ModifyModel(resource, model); + } +} diff --git a/source/Server.AzureAD/Configuration/AzureADConfigurationStore.cs b/source/Server.AzureAD/Configuration/AzureADConfigurationStore.cs index 5c666d6..ba410f7 100644 --- a/source/Server.AzureAD/Configuration/AzureADConfigurationStore.cs +++ b/source/Server.AzureAD/Configuration/AzureADConfigurationStore.cs @@ -1,4 +1,7 @@ -using Octopus.Data.Storage.Configuration; +using System; +using Octopus.Data.Model; +using Octopus.Data.Storage.Configuration; +using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration @@ -6,14 +9,24 @@ namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration class AzureADConfigurationStore : OpenIDConnectConfigurationWithRoleStore, IAzureADConfigurationStore { public const string SingletonId = "authentication-aad"; - + ISystemLog log; public override string Id => SingletonId; public override string ConfigurationSettingsName => "AzureAD"; - public AzureADConfigurationStore( - IConfigurationStore configurationStore) : base(configurationStore) + IConfigurationStore configurationStore, ISystemLog log) : base(configurationStore) { + this.log = log; } + + public SensitiveString? GetClientKey() => GetProperty(doc => doc.ClientKey); + + public void SetClientKey(SensitiveString? key) => SetProperty(doc => + { + if (!string.IsNullOrEmpty(key?.Value)) + log.WithSensitiveValue(key.Value); + + doc.ClientKey = key; + }); } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/AzureADConfigureCommands.cs b/source/Server.AzureAD/Configuration/AzureADConfigureCommands.cs index a494459..b8858f0 100644 --- a/source/Server.AzureAD/Configuration/AzureADConfigureCommands.cs +++ b/source/Server.AzureAD/Configuration/AzureADConfigureCommands.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using Octopus.Data.Model; using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; @@ -30,6 +31,19 @@ public override IEnumerable GetOptions() ConfigurationStore.Value.SetRoleClaimType(v); Log.Info($"{ConfigurationSettingsName} RoleClaimType set to: {v}"); }); + yield return new ConfigureCommandOption($"{ConfigurationSettingsName}ClientKey=", "The App Registration secret access key. Used for authenticating against the GraphAPI for group overage lookups.", v => + { + if (!string.IsNullOrEmpty(v)) + { + ConfigurationStore.Value.SetClientKey(v.ToSensitiveString()); + Log.Info("Azure AD Graph API Client Key set to provided value"); + } + else + { + ConfigurationStore.Value.SetClientKey(null); + Log.Info("Azure AD Graph API Client Key set to null (anonymous bind)"); + } + }); } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/AzureADDatabaseInitializer.cs b/source/Server.AzureAD/Configuration/AzureADDatabaseInitializer.cs index 1117428..d8a78d9 100644 --- a/source/Server.AzureAD/Configuration/AzureADDatabaseInitializer.cs +++ b/source/Server.AzureAD/Configuration/AzureADDatabaseInitializer.cs @@ -1,4 +1,5 @@ -using Octopus.Data.Storage.Configuration; +using System; +using Octopus.Data.Storage.Configuration; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration @@ -11,4 +12,4 @@ public AzureADDatabaseInitializer(IConfigurationStore configurationStore) : base protected override string SingletonId => AzureADConfigurationStore.SingletonId; } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/IAzureADConfigurationSettings.cs b/source/Server.AzureAD/Configuration/IAzureADConfigurationSettings.cs index 4b7d1bb..e477d7e 100644 --- a/source/Server.AzureAD/Configuration/IAzureADConfigurationSettings.cs +++ b/source/Server.AzureAD/Configuration/IAzureADConfigurationSettings.cs @@ -1,7 +1,9 @@ -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; +using System; +using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration { - interface IAzureADConfigurationSettings : IHasConfigurationSettings - { } -} \ No newline at end of file + interface IAzureADConfigurationSettings : IConfigurationSettingsProvider + { + } +} diff --git a/source/Server.AzureAD/Configuration/IAzureADConfigurationStore.cs b/source/Server.AzureAD/Configuration/IAzureADConfigurationStore.cs index 9f1b8c5..ac554cb 100644 --- a/source/Server.AzureAD/Configuration/IAzureADConfigurationStore.cs +++ b/source/Server.AzureAD/Configuration/IAzureADConfigurationStore.cs @@ -1,8 +1,12 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; +using System; +using Octopus.Data.Model; +using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration { interface IAzureADConfigurationStore : IOpenIDConnectConfigurationWithRoleStore { + SensitiveString? GetClientKey(); + void SetClientKey(SensitiveString? key); } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Configuration/MapFromAzureADConfigurationResourceToAzureADConfiguration.cs b/source/Server.AzureAD/Configuration/MapFromAzureADConfigurationResourceToAzureADConfiguration.cs new file mode 100644 index 0000000..a282548 --- /dev/null +++ b/source/Server.AzureAD/Configuration/MapFromAzureADConfigurationResourceToAzureADConfiguration.cs @@ -0,0 +1,76 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Octopus.Core.Infrastructure.Mapping; +using Octopus.Data.Model; + +namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration +{ + class MapFromAzureADConfigurationResourceToAzureADConfiguration : IMapToNew, IMapToExisting + { + public async Task Map(AzureADConfigurationResource source, CancellationToken cancellationToken) + { + await Task.CompletedTask; + var target = new AzureADConfiguration(); + + target.IsEnabled = source.IsEnabled; + target.Issuer = source.Issuer; + target.RoleClaimType = source.RoleClaimType; + target.AllowAutoUserCreation = source.AllowAutoUserCreation ?? false; + target.ClientId = source.ClientId; + + if (source.ClientSecret is { HasValue: true, NewValue: { } }) + { + target.ClientSecret = source.ClientSecret.NewValue.ToSensitiveString(); + } + + if (source.ClientSecret is not { HasValue: true }) + { + target.ClientSecret = null; + } + + if (source.ClientKey is { HasValue: true, NewValue: { } }) + { + target.ClientKey = source.ClientKey.NewValue.ToSensitiveString(); + } + + if (source.ClientKey is not { HasValue: true }) + { + target.ClientKey = null; + } + + return target; + } + + public async Task Map(AzureADConfigurationResource source, AzureADConfiguration target, CancellationToken cancellationToken) + { + await Task.CompletedTask; + + target.IsEnabled = source.IsEnabled; + target.Issuer = source.Issuer; + target.RoleClaimType = source.RoleClaimType; + target.AllowAutoUserCreation = source.AllowAutoUserCreation ?? false; + target.ClientId = source.ClientId; + + if (source.ClientSecret is { HasValue: true, NewValue: { } }) + { + target.ClientSecret = source.ClientSecret.NewValue.ToSensitiveString(); + } + + if (source.ClientSecret is not { HasValue: true }) + { + target.ClientSecret = null; + } + + if (source.ClientKey is { HasValue: true, NewValue: { } }) + { + target.ClientKey = source.ClientKey.NewValue.ToSensitiveString(); + } + + if (source.ClientKey is not { HasValue: true }) + { + target.ClientKey = null; + } + } + } +} diff --git a/source/Server.AzureAD/Configuration/MapFromAzureADConfigurationToAzureADConfigurationResource.cs b/source/Server.AzureAD/Configuration/MapFromAzureADConfigurationToAzureADConfigurationResource.cs new file mode 100644 index 0000000..d9c3354 --- /dev/null +++ b/source/Server.AzureAD/Configuration/MapFromAzureADConfigurationToAzureADConfigurationResource.cs @@ -0,0 +1,45 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Octopus.Core.Infrastructure.Mapping; +using Octopus.Server.MessageContracts; + +namespace Octopus.Server.Extensibility.Authentication.AzureAD.Configuration +{ + class MapFromAzureADConfigurationToAzureADConfigurationResource : IMapToNew + { + public async Task Map(AzureADConfiguration source, CancellationToken cancellationToken) + { + await Task.CompletedTask; + + var target = new AzureADConfigurationResource(); + + target.Id = source.Id; + target.IsEnabled = source.IsEnabled; + target.AllowAutoUserCreation = source.AllowAutoUserCreation; + target.RoleClaimType = source.RoleClaimType; + target.Issuer = source.Issuer; + target.ClientId = source.ClientId; + + if (source.ClientSecret == null) + { + target.ClientSecret = null; + } + else + { + target.ClientSecret = !string.IsNullOrWhiteSpace(source.ClientSecret?.Value) ? new SensitiveValue { HasValue = true } : new SensitiveValue { HasValue = false }; + } + + if (source.ClientKey == null) + { + target.ClientKey = null; + } + else + { + target.ClientKey = !string.IsNullOrWhiteSpace(source.ClientKey?.Value) ? new SensitiveValue { HasValue = true } : new SensitiveValue { HasValue = false }; + } + + return target; + } + } +} diff --git a/source/Server.AzureAD/Identities/AzureADIdentityCreator.cs b/source/Server.AzureAD/Identities/AzureADIdentityCreator.cs index dedaebe..877fdff 100644 --- a/source/Server.AzureAD/Identities/AzureADIdentityCreator.cs +++ b/source/Server.AzureAD/Identities/AzureADIdentityCreator.cs @@ -1,4 +1,5 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Identities; +using System; +using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Identities; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Identities { @@ -8,5 +9,6 @@ class AzureADIdentityCreator : IdentityCreator, IAzureADIdentityCreator } interface IAzureADIdentityCreator : IIdentityCreator - { } -} \ No newline at end of file + { + } +} diff --git a/source/Server.AzureAD/Infrastructure/AzureADPrincipalToUserResourceMapper.cs b/source/Server.AzureAD/Infrastructure/AzureADPrincipalToUserResourceMapper.cs index 26a3424..1859812 100644 --- a/source/Server.AzureAD/Infrastructure/AzureADPrincipalToUserResourceMapper.cs +++ b/source/Server.AzureAD/Infrastructure/AzureADPrincipalToUserResourceMapper.cs @@ -1,3 +1,4 @@ +using System; using System.Security.Claims; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; @@ -5,16 +6,12 @@ namespace Octopus.Server.Extensibility.Authentication.AzureAD.Infrastructure { class AzureADPrincipalToUserResourceMapper : PrincipalToUserResourceMapper, IAzureADPrincipalToUserResourceMapper { - protected override string? GetEmailAddress(ClaimsPrincipal principal) - { + protected override string? GetEmailAddress(ClaimsPrincipal principal) => // Grab the email address if it exists as a claim, otherwise get the UPN as a good fallback - return base.GetEmailAddress(principal) ?? GetClaimValue(principal, ClaimTypes.Upn); - } + base.GetEmailAddress(principal) ?? GetClaimValue(principal, ClaimTypes.Upn); - protected override string? GetUsername(ClaimsPrincipal principal) - { + protected override string? GetUsername(ClaimsPrincipal principal) => // Use the UPN in preference for username - return GetClaimValue(principal, ClaimTypes.Upn) ?? base.GetUsername(principal); - } + GetClaimValue(principal, ClaimTypes.Upn) ?? base.GetUsername(principal); } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Infrastructure/IAzureADPrincipalToUserResourceMapper.cs b/source/Server.AzureAD/Infrastructure/IAzureADPrincipalToUserResourceMapper.cs index 49f26e2..025c95f 100644 --- a/source/Server.AzureAD/Infrastructure/IAzureADPrincipalToUserResourceMapper.cs +++ b/source/Server.AzureAD/Infrastructure/IAzureADPrincipalToUserResourceMapper.cs @@ -1,3 +1,4 @@ +using System; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Infrastructure @@ -5,4 +6,4 @@ namespace Octopus.Server.Extensibility.Authentication.AzureAD.Infrastructure interface IAzureADPrincipalToUserResourceMapper : IPrincipalToUserResourceMapper { } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Issuer/AzureADAuthorizationEndpointUrlBuilder.cs b/source/Server.AzureAD/Issuer/AzureADAuthorizationEndpointUrlBuilder.cs index e299981..50d3899 100644 --- a/source/Server.AzureAD/Issuer/AzureADAuthorizationEndpointUrlBuilder.cs +++ b/source/Server.AzureAD/Issuer/AzureADAuthorizationEndpointUrlBuilder.cs @@ -1,4 +1,5 @@ -using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; +using System; +using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; using Octopus.Server.Extensibility.HostServices.Web; @@ -10,4 +11,4 @@ public AzureADAuthorizationEndpointUrlBuilder(IAzureADConfigurationStore configu { } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Issuer/AzureADKeyRetriever.cs b/source/Server.AzureAD/Issuer/AzureADKeyRetriever.cs index 8c6182b..f8ddb7e 100644 --- a/source/Server.AzureAD/Issuer/AzureADKeyRetriever.cs +++ b/source/Server.AzureAD/Issuer/AzureADKeyRetriever.cs @@ -1,4 +1,5 @@ -using Octopus.Diagnostics; +using System; +using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; @@ -10,4 +11,4 @@ public AzureADKeyRetriever(ISystemLog log, IAzureADConfigurationStore configurat { } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Issuer/IAzureADAuthorizationEndpointUrlBuilder.cs b/source/Server.AzureAD/Issuer/IAzureADAuthorizationEndpointUrlBuilder.cs index f8228fa..691b32c 100644 --- a/source/Server.AzureAD/Issuer/IAzureADAuthorizationEndpointUrlBuilder.cs +++ b/source/Server.AzureAD/Issuer/IAzureADAuthorizationEndpointUrlBuilder.cs @@ -1,7 +1,9 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; +using System; +using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Issuer { interface IAzureADAuthorizationEndpointUrlBuilder : IAuthorizationEndpointUrlBuilder - { } -} \ No newline at end of file + { + } +} diff --git a/source/Server.AzureAD/Issuer/IAzureADKeyRetriever.cs b/source/Server.AzureAD/Issuer/IAzureADKeyRetriever.cs index bec5b52..fd5c4da 100644 --- a/source/Server.AzureAD/Issuer/IAzureADKeyRetriever.cs +++ b/source/Server.AzureAD/Issuer/IAzureADKeyRetriever.cs @@ -1,3 +1,4 @@ +using System; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Issuer @@ -5,4 +6,4 @@ namespace Octopus.Server.Extensibility.Authentication.AzureAD.Issuer interface IAzureADKeyRetriever : IKeyRetriever { } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Server.AzureAD.csproj b/source/Server.AzureAD/Server.AzureAD.csproj index e3821e7..3dbecde 100644 --- a/source/Server.AzureAD/Server.AzureAD.csproj +++ b/source/Server.AzureAD/Server.AzureAD.csproj @@ -14,9 +14,9 @@ true - - - + + 1701;1702 + @@ -24,8 +24,42 @@ - - - - + + + C:\Program Files\Octopus Deploy\Octopus\Newtonsoft.Json.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Core.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Data.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Extensibility.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Extensibility.Authentication.dll + + + C:\Program Files\Octopus Deploy\Octopus\Autofac.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Client.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.MessageContracts.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.MessageContracts.Base.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Diagnostics.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Time.dll + + diff --git a/source/Server.AzureAD/Tokens/AzureADAuthTokenHandler.cs b/source/Server.AzureAD/Tokens/AzureADAuthTokenHandler.cs index 0a48b22..3db2867 100644 --- a/source/Server.AzureAD/Tokens/AzureADAuthTokenHandler.cs +++ b/source/Server.AzureAD/Tokens/AzureADAuthTokenHandler.cs @@ -1,15 +1,238 @@ -using Octopus.Diagnostics; +using Newtonsoft.Json; +using Octopus.Data.Model; +using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.AzureAD.Issuer; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Claims; +using System.Threading.Tasks; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Tokens { class AzureADAuthTokenHandler : OpenIDConnectAuthTokenWithRolesHandler, IAzureADAuthTokenHandler { public AzureADAuthTokenHandler(ISystemLog log, IAzureADConfigurationStore configurationStore, IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, IAzureADKeyRetriever keyRetriever) : base(log, configurationStore, identityProviderConfigDiscoverer, keyRetriever) + {} + + protected class MicrosoftGraphResponse + { + public string? odata {get; set;} + public List? value { get; set; } + } + + protected class MicrosoftGraphTokenResponse + { + public string? token_type { get; set; } + public int expires_in { get; set; } + public int ext_expires_in { get; set; } + public string? access_token { get; set; } + } + + protected async Task FollowGroupApiCall(ClaimsPrincipal principal) { + List groupObjectIds = new List(); + + string? clientId = ConfigurationStore.GetClientId(); + + if (string.IsNullOrWhiteSpace(clientId)) + { + // Failed to get Access Token + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get App Registration Client ID from Octopus Configuration Store!"); + return new string[0]; + } + + String? clientKey = ConfigurationStore.GetClientKey()?.Value; + + if (String.IsNullOrWhiteSpace(clientKey)) + { + // Failed to get Access Token + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get App Registration Client Key from Octopus Configuration Store!"); + return new string[0]; + } + + string? tenantId = null; + if (principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid") != null) + { + tenantId = principal.Claims.FirstOrDefault(c => string.Equals(c.Type, "http://schemas.microsoft.com/identity/claims/tenantid", StringComparison.OrdinalIgnoreCase)).Value; + } + else + { + // Failed to get tenantId from claim data + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get AzureAD TenantID (tid) from claim data. Make sure tenantid is returned in the claim!"); + return new string[0]; + } + + HttpClient client = new HttpClient(); + + // Get Access Token for GraphAPI + HttpRequestMessage requestToken = new HttpRequestMessage(HttpMethod.Post, "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token"); + + var body = new List>(); + body.Add(new KeyValuePair("client_id", clientId)); + body.Add(new KeyValuePair("scope", "https://graph.microsoft.com/.default")); + body.Add(new KeyValuePair("client_secret", clientKey)); + body.Add(new KeyValuePair("grant_type", "client_credentials")); + + requestToken.Content = new FormUrlEncodedContent(body); + HttpResponseMessage responseToken = await client.SendAsync(requestToken); + + // Endpoint returns JSON with an array of Group ObjectIDs + if (responseToken.IsSuccessStatusCode) + { + + string responseTokenContent = await responseToken.Content.ReadAsStringAsync(); + MicrosoftGraphTokenResponse tokenResult = JsonConvert.DeserializeObject(responseTokenContent); + + string accessToken; + + if ((tokenResult.access_token) != null) + { + accessToken = tokenResult.access_token; + } + else + { + // Failed to get Access Token + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get user's Access Token!"); + return new string[0]; + } + + string? userObjectId = null; + if (principal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier") != null) + { + userObjectId = principal.Claims.FirstOrDefault(c => string.Equals(c.Type, "http://schemas.microsoft.com/identity/claims/objectidentifier", StringComparison.OrdinalIgnoreCase)).Value; + } + else + { + // Failed to get userObjectId from claim data + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get AzureAD User Object ID (oid) from claim data. Make sure the user oid is returned in the claim!"); + return new string[0]; + } + + string requestUrl = "https://graph.microsoft.com/v1.0/" + tenantId + "/users/" + userObjectId + "/getMemberObjects"; + + // Get Group Membership list from GraphAPI + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); + StringContent content = new StringContent("{\"securityEnabledOnly\": \"false\"}"); + content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + request.Content = content; + HttpResponseMessage response = await client.SendAsync(request); + + // Endpoint returns JSON with an array of Group ObjectIDs + if (response.IsSuccessStatusCode) + { + string responseContent = await response.Content.ReadAsStringAsync(); + MicrosoftGraphResponse groupsResult = JsonConvert.DeserializeObject(responseContent); + + if ((groupsResult.value) != null) + { + foreach (string groupObjectID in groupsResult.value) + { + groupObjectIds.Add(groupObjectID); + } + } + else + { + // Failed to get Group Memberships + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get list of groups from the AzureAD Graph API!"); + return new string[0]; + } + + string[] groups = groupObjectIds.ToArray(); + + return groups; + } + else + { + string responseContent = await response.Content.ReadAsStringAsync(); + + // Failed to get Group Memberships + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get group membership via the AzureAD Graph API!"); + Log.Error("+++ AzureAD-GraphAPI: ERROR - " + responseContent); + return new string[0]; + } + } + else + { + string responseTokenContent = await responseToken.Content.ReadAsStringAsync(); + + // Failed to get Auth Token + Log.Error("+++ AzureAD-GraphAPI: ERROR - Failed to get Auth Token for group membership API!"); + Log.Error("+++ AzureAD-GraphAPI: ERROR - " + responseTokenContent); + return new string[0]; + } + } + + + protected override string[] GetProviderGroupIds(ClaimsPrincipal principal) + { + var roleClaimType = ConfigurationStore.GetRoleClaimType(); + + if (string.IsNullOrWhiteSpace(roleClaimType)) + { + return new string[0]; + } + + // Get Octopus AzureAD COnfiguration - Client Access Key + String? clientKey = ConfigurationStore.GetClientKey()?.Value; + + + // Retrieve "_claims_names" token value if set, if not null + string? claimNames = null; + if (principal.FindFirst("_claim_names") != null) + { + claimNames = principal.Claims.FirstOrDefault(c => string.Equals(c.Type, "_claim_names", StringComparison.OrdinalIgnoreCase)).Value; + } + + + // Get some additional claim data for better logging + string claimUsersEmail = "(Email token not present in claim!)"; + if (principal.FindFirst(ClaimTypes.Email) != null) + { + claimUsersEmail = principal.Claims.FirstOrDefault(c => string.Equals(c.Type, ClaimTypes.Email, StringComparison.OrdinalIgnoreCase)).Value; + } + + string claimUsersOid = "(Object ID (oid) token not present in claim!)"; + if (principal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier") != null) + { + claimUsersOid = principal.Claims.FirstOrDefault(c => string.Equals(c.Type, "http://schemas.microsoft.com/identity/claims/objectidentifier", StringComparison.OrdinalIgnoreCase)).Value; + } + + // Only follow the Microsoft GraphAPI for group membership If: + // - Octopus AzureAD Config Client Access Key is set + // - claimNames is not null + // - claimNames has the value of: {"groups":"src1"} + // Else look for group membership in JWT token + if ((!String.IsNullOrWhiteSpace(clientKey)) && (!String.IsNullOrWhiteSpace(claimNames)) && (claimNames == "{\"groups\":\"src1\"}")) + { + + // If this claim has the "_claim_names" present this means this user is over the 150/200 group limit in the token. We need to follow the Microsoft Azure Graph API. But only if the Client Key is set in the AzureAD Octopus configuration. + Log.Info("+++ AzureAD-GraphAPI: UserAuth - Using Azure GraphAPI group lookup endpoint - ("+ claimUsersEmail + " - "+ claimUsersOid + ")"); + + return FollowGroupApiCall(principal).Result; + + } + else + { + + // the groups Ids consist of external Role and Group identifiers. We always load ClaimTypes.Role claims + // as external identifiers, and then also based on a custom claim specified by the provider. + Log.Info("+++ AzureAD-GraphAPI: UserAuth - Using JWT token groups - (" + claimUsersEmail + " - " + claimUsersOid + ")"); + + var groups = principal.FindAll(ClaimTypes.Role) + .Concat(principal.FindAll(roleClaimType)) + .Select(c => c.Value).ToArray(); + + return groups; + + } + } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Tokens/IAzureADAuthTokenHandler.cs b/source/Server.AzureAD/Tokens/IAzureADAuthTokenHandler.cs index b014cbb..b021231 100644 --- a/source/Server.AzureAD/Tokens/IAzureADAuthTokenHandler.cs +++ b/source/Server.AzureAD/Tokens/IAzureADAuthTokenHandler.cs @@ -1,7 +1,9 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; +using System; +using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Tokens { interface IAzureADAuthTokenHandler : IAuthTokenHandler - { } -} \ No newline at end of file + { + } +} diff --git a/source/Server.AzureAD/Web/AzureADHomeLinksContributor.cs b/source/Server.AzureAD/Web/AzureADHomeLinksContributor.cs index 31a8077..8699c86 100644 --- a/source/Server.AzureAD/Web/AzureADHomeLinksContributor.cs +++ b/source/Server.AzureAD/Web/AzureADHomeLinksContributor.cs @@ -1,4 +1,5 @@ -using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; +using System; +using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; namespace Octopus.Server.Extensibility.Authentication.AzureAD.Web @@ -9,4 +10,4 @@ public AzureADHomeLinksContributor(IAzureADConfigurationStore configurationStore { } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Web/AzureADStaticContentFolders.cs b/source/Server.AzureAD/Web/AzureADStaticContentFolders.cs index 247b9df..98098cb 100644 --- a/source/Server.AzureAD/Web/AzureADStaticContentFolders.cs +++ b/source/Server.AzureAD/Web/AzureADStaticContentFolders.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Reflection; using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; @@ -13,4 +14,4 @@ public IEnumerable GetStaticContentFolders return new[] { new StaticContentEmbeddedResourcesFolder("", assembly, type.Namespace + ".Static") }; } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Web/AzureADUserAuthenticatedAction.cs b/source/Server.AzureAD/Web/AzureADUserAuthenticatedAction.cs index 6f9248d..2e5c7c0 100644 --- a/source/Server.AzureAD/Web/AzureADUserAuthenticatedAction.cs +++ b/source/Server.AzureAD/Web/AzureADUserAuthenticatedAction.cs @@ -1,4 +1,5 @@ -using Octopus.Diagnostics; +using System; +using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.AzureAD.Identities; using Octopus.Server.Extensibility.Authentication.AzureAD.Infrastructure; @@ -22,7 +23,8 @@ public AzureADUserAuthenticatedAction( ISleep sleep, IAzureADIdentityCreator identityCreator, IUrlEncoder encoder, - IUserService userService) : + IUserService userService, + IAuthenticationConfigurationStore authenticationConfigurationStore) : base( log, authTokenHandler, @@ -33,10 +35,11 @@ public AzureADUserAuthenticatedAction( sleep, identityCreator, encoder, - userService) + userService, + authenticationConfigurationStore) { } protected override string ProviderName => AzureADAuthenticationProvider.ProviderName; } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Web/AzureADUserAuthenticatedPkceAction.cs b/source/Server.AzureAD/Web/AzureADUserAuthenticatedPkceAction.cs index a8c5ab7..0f51d9b 100644 --- a/source/Server.AzureAD/Web/AzureADUserAuthenticatedPkceAction.cs +++ b/source/Server.AzureAD/Web/AzureADUserAuthenticatedPkceAction.cs @@ -1,4 +1,5 @@ -using Octopus.Diagnostics; +using System; +using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.AzureAD.Identities; using Octopus.Server.Extensibility.Authentication.AzureAD.Infrastructure; @@ -26,8 +27,10 @@ public AzureADUserAuthenticatedPkceAction( IUrlEncoder encoder, IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, IMediator mediator, - IUserService service) - : base(log, + IUserService service, + IAuthenticationConfigurationStore authenticationConfigurationStore) + : base( + log, authTokenHandler, principalToUserResourceMapper, configurationStore, @@ -38,10 +41,11 @@ public AzureADUserAuthenticatedPkceAction( encoder, identityProviderConfigDiscoverer, mediator, - service) + service, + authenticationConfigurationStore) { } protected override string ProviderName => AzureADAuthenticationProvider.ProviderName; } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Web/AzureADUserAuthenticationAction.cs b/source/Server.AzureAD/Web/AzureADUserAuthenticationAction.cs index 8ce4eb1..78aefed 100644 --- a/source/Server.AzureAD/Web/AzureADUserAuthenticationAction.cs +++ b/source/Server.AzureAD/Web/AzureADUserAuthenticationAction.cs @@ -1,4 +1,5 @@ -using Octopus.Diagnostics; +using System; +using Octopus.Diagnostics; using Octopus.Server.Extensibility.Authentication.AzureAD.Configuration; using Octopus.Server.Extensibility.Authentication.AzureAD.Issuer; using Octopus.Server.Extensibility.Authentication.HostServices; @@ -18,8 +19,15 @@ public AzureADUserAuthenticationAction( IAzureADAuthorizationEndpointUrlBuilder urlBuilder, IApiActionModelBinder modelBinder, IAuthenticationConfigurationStore authenticationConfigurationStore, - IMediator mediator) : base(log, configurationStore, identityProviderConfigDiscoverer, urlBuilder, modelBinder, authenticationConfigurationStore, mediator) + IMediator mediator) : base( + log, + configurationStore, + identityProviderConfigDiscoverer, + urlBuilder, + modelBinder, + authenticationConfigurationStore, + mediator) { } } -} \ No newline at end of file +} diff --git a/source/Server.AzureAD/Web/Static/areas/users/azureAD_auth_provider.js b/source/Server.AzureAD/Web/Static/areas/users/azureAD_auth_provider.js index 3150361..7e47e44 100644 --- a/source/Server.AzureAD/Web/Static/areas/users/azureAD_auth_provider.js +++ b/source/Server.AzureAD/Web/Static/areas/users/azureAD_auth_provider.js @@ -1,33 +1,35 @@ -(function (providerName) { +(function(providerName) { -function azureADAuthProvider(octopusClient, provider, loginState, onError) { + function azureADAuthProvider(octopusClient, provider, loginState, onError) { - this.linkHtml = '
Sign in with Microsoft
'; + this.linkHtml = '
Sign in with Microsoft
'; - this.signIn = function () { - console.log("Signing in using " + providerName + " provider"); + this.signIn = function() { + console.log("Signing in using " + providerName + " provider"); - var authUri = provider.Links.Authenticate; - var redirectToLink = function (externalProviderLink) { - window.location.href = externalProviderLink.ExternalAuthenticationUrl; - }; - var postData = { - ApiAbsUrl: octopusClient.resolve("~/"), - State: loginState - }; + var authUri = provider.Links.Authenticate; + var redirectToLink = function(externalProviderLink) { + window.location.href = externalProviderLink.ExternalAuthenticationUrl; + }; + var postData = { + ApiAbsUrl: octopusClient.resolve("~/"), + State: loginState + }; - octopusClient.post(authUri, postData) - .then(redirectToLink, onError); - }; + octopusClient.post(authUri, postData) + .then(redirectToLink, onError); + }; - return { - Name: providerName, - LinkHtml: this.linkHtml, - SignIn: this.signIn - }; -} + return { + Name: providerName, + LinkHtml: this.linkHtml, + SignIn: this.signIn + }; + } -console.log("Registering " + providerName + " auth provider"); -window.Octopus.registerExtension(providerName, "auth_provider", azureADAuthProvider); + console.log("Registering " + providerName + " auth provider"); + window.Octopus.registerExtension(providerName, "auth_provider", azureADAuthProvider); })("Azure AD"); \ No newline at end of file diff --git a/source/Server.AzureAD/Web/Static/styles/azureAD.css b/source/Server.AzureAD/Web/Static/styles/azureAD.css index f8e23d0..f09255f 100644 --- a/source/Server.AzureAD/Web/Static/styles/azureAD.css +++ b/source/Server.AzureAD/Web/Static/styles/azureAD.css @@ -1,28 +1,24 @@ .aad-button { + align-items: center; background-color: #000000; - color: #ffffff; - cursor: pointer; border-radius: 2px; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.24), 0 0 1px 0 rgba(0, 0, 0, 0.12); + color: #ffffff; + cursor: pointer; display: flex; - align-items: center; - padding-top: 0.8125rem; padding-bottom: 0.8125rem; + padding-top: 0.8125rem; } -.aad-button:hover { - background-color: #4a4a4a; -} +.aad-button:hover { background-color: #4a4a4a; } -.aad-button img { - margin-left: 0.8125rem; -} +.aad-button img { margin-left: 0.8125rem; } .aad-button div { + display: inline-block; font-family: 'Roboto', sans-serif; font-weight: 600; - display: inline-block; - text-align: left; margin-left: 0.8125rem; - overflow: hidden; -} + overflow: hidden; + text-align: left; +} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/GoogleAppsConfiguration.cs b/source/Server.GoogleApps/Configuration/GoogleAppsConfiguration.cs deleted file mode 100644 index 6ea6630..0000000 --- a/source/Server.GoogleApps/Configuration/GoogleAppsConfiguration.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - class GoogleAppsConfiguration : OpenIDConnectConfiguration - { - public GoogleAppsConfiguration() : base(GoogleAppsConfigurationStore.SingletonId, "GoogleApps", "Octopus Deploy", "1.0") - { - Issuer = "https://accounts.google.com"; - } - - public string? HostedDomain { get; set; } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationMapping.cs b/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationMapping.cs deleted file mode 100644 index 6ece0c4..0000000 --- a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationMapping.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - class GoogleAppsConfigurationMapping : IConfigurationDocumentMapper - { - public Type GetTypeToMap() => typeof(GoogleAppsConfiguration); - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationResource.cs b/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationResource.cs deleted file mode 100644 index d105504..0000000 --- a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationResource.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.MessageContracts.Attributes; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - [Description("Sign in to your Octopus Server with Google Apps. [Learn more](https://g.octopushq.com/AuthGoogleApps).")] - class GoogleAppsConfigurationResource : OpenIDConnectConfigurationResource - { - [DisplayName("Hosted Domain")] - [Description("Tell Octopus which Google Apps domain to trust")] - [Writeable] - public string? HostedDomain { get; set; } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationSettings.cs b/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationSettings.cs deleted file mode 100644 index 94b0fe0..0000000 --- a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationSettings.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - class GoogleAppsConfigurationSettings : OpenIDConnectConfigurationSettings, IGoogleAppsConfigurationSettings - { - public GoogleAppsConfigurationSettings(IGoogleAppsConfigurationStore configurationDocumentStore) : base(configurationDocumentStore) - { - } - - public override string Id => GoogleAppsConfigurationStore.SingletonId; - public override string Description => "GoogleApps authentication settings"; - - public override IEnumerable GetConfigurationValues() - { - foreach (var configurationValue in base.GetConfigurationValues()) - { - yield return configurationValue; - } - - yield return new ConfigurationValue($"Octopus.{ConfigurationDocumentStore.ConfigurationSettingsName}.HostedDomain", ConfigurationDocumentStore.GetHostedDomain(), ConfigurationDocumentStore.GetIsEnabled(), "Hosted Domain"); - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationStore.cs b/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationStore.cs deleted file mode 100644 index db08fde..0000000 --- a/source/Server.GoogleApps/Configuration/GoogleAppsConfigurationStore.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Octopus.Data.Storage.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - class GoogleAppsConfigurationStore : OpenIDConnectConfigurationStore, IGoogleAppsConfigurationStore - { - public const string SingletonId = "authentication-googleapps"; - - public override string Id => SingletonId; - public override string ConfigurationSettingsName => "GoogleApps"; - - public GoogleAppsConfigurationStore( - IConfigurationStore configurationStore) : base(configurationStore) - { - } - - public string? GetHostedDomain() - { - return GetProperty(doc => doc.HostedDomain); - } - - public void SetHostedDomain(string? hostedDomain) - { - SetProperty(doc => doc.HostedDomain = hostedDomain); - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/GoogleAppsConfigureCommands.cs b/source/Server.GoogleApps/Configuration/GoogleAppsConfigureCommands.cs deleted file mode 100644 index a061948..0000000 --- a/source/Server.GoogleApps/Configuration/GoogleAppsConfigureCommands.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; -using Octopus.Server.Extensibility.HostServices.Web; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - class GoogleAppsConfigureCommands : OpenIDConnectConfigureCommands - { - public GoogleAppsConfigureCommands( - ISystemLog log, - Lazy configurationStore, - Lazy webPortalConfigurationStore) - : base(log, configurationStore, webPortalConfigurationStore) - { - } - - protected override string ConfigurationSettingsName => "googleApps"; - - public override IEnumerable GetOptions() - { - foreach (var option in base.GetOptions()) - { - yield return option; - } - yield return new ConfigureCommandOption($"{ConfigurationSettingsName}HostedDomain=", $"Tell Octopus which Google Apps domain to trust.", v => - { - ConfigurationStore.Value.SetHostedDomain(v); - Log.Info($"{ConfigurationSettingsName} HostedDomain set to: {v}"); - }); - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/GoogleAppsDatabaseInitializer.cs b/source/Server.GoogleApps/Configuration/GoogleAppsDatabaseInitializer.cs deleted file mode 100644 index e218b95..0000000 --- a/source/Server.GoogleApps/Configuration/GoogleAppsDatabaseInitializer.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Octopus.Data.Storage.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - class GoogleAppsDatabaseInitializer : DatabaseInitializer - { - public GoogleAppsDatabaseInitializer(IConfigurationStore configurationStore) : base(configurationStore) - { - } - - protected override string SingletonId => GoogleAppsConfigurationStore.SingletonId; - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/IGoogleAppsConfigurationSettings.cs b/source/Server.GoogleApps/Configuration/IGoogleAppsConfigurationSettings.cs deleted file mode 100644 index b425d04..0000000 --- a/source/Server.GoogleApps/Configuration/IGoogleAppsConfigurationSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - interface IGoogleAppsConfigurationSettings : IHasConfigurationSettings - { } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Configuration/IGoogleAppsConfigurationStore.cs b/source/Server.GoogleApps/Configuration/IGoogleAppsConfigurationStore.cs deleted file mode 100644 index e6e5b29..0000000 --- a/source/Server.GoogleApps/Configuration/IGoogleAppsConfigurationStore.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration -{ - interface IGoogleAppsConfigurationStore : IOpenIDConnectConfigurationStore - { - string? GetHostedDomain(); - void SetHostedDomain(string? hostedDomain); - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/GoogleAppsApi.cs b/source/Server.GoogleApps/GoogleAppsApi.cs deleted file mode 100644 index 28368e0..0000000 --- a/source/Server.GoogleApps/GoogleAppsApi.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Identities; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Tokens; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Web; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps -{ - class GoogleAppsApi : OpenIDConnectModule - { - public GoogleAppsApi( - IGoogleAppsConfigurationStore configurationStore, GoogleAppsAuthenticationProvider authenticationProvider) - : base(configurationStore, authenticationProvider) - { - Add("POST", authenticationProvider.AuthenticateUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("POST", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("GET", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/GoogleAppsAuthenticationProvider.cs b/source/Server.GoogleApps/GoogleAppsAuthenticationProvider.cs deleted file mode 100644 index b617e0e..0000000 --- a/source/Server.GoogleApps/GoogleAppsAuthenticationProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps -{ - class GoogleAppsAuthenticationProvider : OpenIDConnectAuthenticationProvider - { - public const string ProviderName = "Google Apps"; - - public GoogleAppsAuthenticationProvider(ISystemLog log, IGoogleAppsConfigurationStore configurationStore) : base(log, configurationStore) - { - } - - public override string IdentityProviderName => ProviderName; - public override string FilenamePrefix => "googleApps"; - - protected override IEnumerable ReasonsWhyConfigIsIncomplete() - { - var issuer = ConfigurationStore.GetIssuer(); - if (string.IsNullOrWhiteSpace(issuer)) - yield return $"No {IdentityProviderName} issuer specified"; - if (!Uri.IsWellFormedUriString(issuer, UriKind.Absolute)) - yield return $"The {IdentityProviderName} issuer must be an absolute URI (expected format: https://accounts.google.com)"; - if (string.IsNullOrWhiteSpace(ConfigurationStore.GetClientId())) - yield return $"No {IdentityProviderName} Client ID specified"; - if (string.IsNullOrWhiteSpace(ConfigurationStore.GetHostedDomain())) - yield return $"No {IdentityProviderName} hosted domain specified"; - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/GoogleAppsExtension.cs b/source/Server.GoogleApps/GoogleAppsExtension.cs deleted file mode 100644 index a6c64e0..0000000 --- a/source/Server.GoogleApps/GoogleAppsExtension.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Autofac; -using Octopus.Server.Extensibility.Authentication.Extensions; -using Octopus.Server.Extensibility.Authentication.Extensions.Identities; -using Octopus.Server.Extensibility.Extensions; -using Octopus.Server.Extensibility.Extensions.Infrastructure; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; -using Octopus.Server.Extensibility.Extensions.Mappings; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Identities; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Issuer; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Tokens; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Web; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps -{ - [OctopusPlugin("GoogleApps", "Octopus Deploy")] - public class GoogleAppsExtension : OpenIDConnectExtension, IOctopusExtension - { - public override void Load(ContainerBuilder builder) - { - base.Load(builder); - - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType() - .As() - .InstancePerDependency(); - builder.RegisterType() - .As() - .As() - .As() - .As() - .InstancePerDependency(); - builder.RegisterType() - .As() - .InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - - // These are important as Singletons because they cache X509 certificates for performance - builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType().AsSelf().InstancePerDependency(); - builder.RegisterType().AsSelf().InstancePerDependency(); - builder.RegisterType().AsSelf().InstancePerDependency(); - - builder.RegisterType() - .As() - .As() - .As() - .As() - .As() - .AsSelf() - .InstancePerDependency(); - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Identities/GoogleAppsIdentityCreator.cs b/source/Server.GoogleApps/Identities/GoogleAppsIdentityCreator.cs deleted file mode 100644 index 49de8db..0000000 --- a/source/Server.GoogleApps/Identities/GoogleAppsIdentityCreator.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Identities; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Identities -{ - class GoogleAppsIdentityCreator : IdentityCreator, IGoogleAppsIdentityCreator - { - protected override string ProviderName => GoogleAppsAuthenticationProvider.ProviderName; - } - - interface IGoogleAppsIdentityCreator : IIdentityCreator - { } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Issuer/GoogleAppsAuthorizationEndpointUrlBuilder.cs b/source/Server.GoogleApps/Issuer/GoogleAppsAuthorizationEndpointUrlBuilder.cs deleted file mode 100644 index ad14329..0000000 --- a/source/Server.GoogleApps/Issuer/GoogleAppsAuthorizationEndpointUrlBuilder.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Issuer -{ - class GoogleAppsAuthorizationEndpointUrlBuilder : AuthorizationEndpointUrlBuilder, IGoogleAppsAuthorizationEndpointUrlBuilder - { - public GoogleAppsAuthorizationEndpointUrlBuilder(IGoogleAppsConfigurationStore configurationStore, IUrlEncoder urlEncoder) : base(configurationStore, urlEncoder) - { - } - - public override string Build(string requestDirectoryPath, IssuerConfiguration issuerConfiguration, string? nonce = null, string? state = null, string? codeChallenge = null) - { - var url = base.Build(requestDirectoryPath, issuerConfiguration, nonce, state, codeChallenge); - - var hd = ConfigurationStore.GetHostedDomain(); - if (!string.IsNullOrWhiteSpace(hd)) - { - url += $"&hd={hd}"; - } - - return url; - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Issuer/GoogleKeyRetriever.cs b/source/Server.GoogleApps/Issuer/GoogleKeyRetriever.cs deleted file mode 100644 index 7495049..0000000 --- a/source/Server.GoogleApps/Issuer/GoogleKeyRetriever.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Issuer -{ - class GoogleKeyRetriever : KeyRetriever, IGoogleKeyRetriever - { - public GoogleKeyRetriever(ISystemLog log, IGoogleAppsConfigurationStore configurationStore, IKeyJsonParser keyParser) : base(log, configurationStore, keyParser) - { - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Issuer/IGoogleAppsAuthorizationEndpointUrlBuilder.cs b/source/Server.GoogleApps/Issuer/IGoogleAppsAuthorizationEndpointUrlBuilder.cs deleted file mode 100644 index e26e7f9..0000000 --- a/source/Server.GoogleApps/Issuer/IGoogleAppsAuthorizationEndpointUrlBuilder.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Issuer -{ - interface IGoogleAppsAuthorizationEndpointUrlBuilder : IAuthorizationEndpointUrlBuilder - { } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Issuer/IGoogleKeyRetriever.cs b/source/Server.GoogleApps/Issuer/IGoogleKeyRetriever.cs deleted file mode 100644 index e09fa8d..0000000 --- a/source/Server.GoogleApps/Issuer/IGoogleKeyRetriever.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Issuer -{ - interface IGoogleKeyRetriever : IKeyRetriever - { - - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Server.GoogleApps.csproj b/source/Server.GoogleApps/Server.GoogleApps.csproj deleted file mode 100644 index dd1d384..0000000 --- a/source/Server.GoogleApps/Server.GoogleApps.csproj +++ /dev/null @@ -1,40 +0,0 @@ - - - - - net6.0 - Octopus.Server.Extensibility.Authentication.GoogleApps - Octopus.Server.Extensibility.Authentication.GoogleApps - Octopus Deploy: Extensibility.Authentication.GoogleApps - Octopus Deploy - http://i.octopusdeploy.com/resources/Avatar3_360.png - Apache-2.0 - https://github.com/OctopusDeploy/OpenIDConnectAuthenticationProviders - enable - true - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/source/Server.GoogleApps/Tokens/GoogleAuthTokenHandler.cs b/source/Server.GoogleApps/Tokens/GoogleAuthTokenHandler.cs deleted file mode 100644 index c64c349..0000000 --- a/source/Server.GoogleApps/Tokens/GoogleAuthTokenHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using System.Security.Claims; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Tokens -{ - class GoogleAuthTokenHandler : OpenIDConnectAuthTokenHandler, IGoogleAuthTokenHandler - { - public GoogleAuthTokenHandler(ISystemLog log, IGoogleAppsConfigurationStore configurationStore, IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, IGoogleKeyRetriever keyRetriever) : base(log, configurationStore, identityProviderConfigDiscoverer, keyRetriever) - { - } - - protected override void DoIssuerSpecificClaimsValidation(ClaimsPrincipal principal, out string error) - { - error = string.Empty; - var hd = ConfigurationStore.GetHostedDomain(); - var hdClaim = principal.Claims.FirstOrDefault(c => c.Type == "hd"); - if (hdClaim == null || hdClaim.Value != hd) - { - error = "Incorrect Hosted Domain value. This server is setup to accept users from a specific hosted domain only."; - } - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Tokens/IGoogleAuthTokenHandler.cs b/source/Server.GoogleApps/Tokens/IGoogleAuthTokenHandler.cs deleted file mode 100644 index 689319a..0000000 --- a/source/Server.GoogleApps/Tokens/IGoogleAuthTokenHandler.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Tokens -{ - interface IGoogleAuthTokenHandler : IAuthTokenHandler - { - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/GoogleAppsHomeLinksContributor.cs b/source/Server.GoogleApps/Web/GoogleAppsHomeLinksContributor.cs deleted file mode 100644 index 5dfc30b..0000000 --- a/source/Server.GoogleApps/Web/GoogleAppsHomeLinksContributor.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Web -{ - class GoogleAppsHomeLinksContributor : OpenIDConnectHomeLinksContributor - { - public GoogleAppsHomeLinksContributor(IGoogleAppsConfigurationStore configurationStore, GoogleAppsAuthenticationProvider authenticationProvider) : base(configurationStore, authenticationProvider) - { - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/GoogleAppsStaticContentFolders.cs b/source/Server.GoogleApps/Web/GoogleAppsStaticContentFolders.cs deleted file mode 100644 index 56cc08b..0000000 --- a/source/Server.GoogleApps/Web/GoogleAppsStaticContentFolders.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using System.Reflection; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Web -{ - class GoogleAppsStaticContentFolders : IContributesStaticContentFolders - { - public IEnumerable GetStaticContentFolders() - { - var type = typeof(GoogleAppsStaticContentFolders); - var assembly = type.GetTypeInfo().Assembly; - return new [] { new StaticContentEmbeddedResourcesFolder("", assembly, type.Namespace + ".Static") }; - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticatedAction.cs b/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticatedAction.cs deleted file mode 100644 index 0707a5e..0000000 --- a/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticatedAction.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Identities; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Tokens; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Time; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Web -{ - class GoogleAppsUserAuthenticatedAction - : UserAuthenticatedAction - { - public GoogleAppsUserAuthenticatedAction( - ISystemLog log, - IGoogleAuthTokenHandler authTokenHandler, - IPrincipalToUserResourceMapper principalToUserResourceMapper, - IGoogleAppsConfigurationStore configurationStore, - IAuthCookieCreator authCookieCreator, - IInvalidLoginTracker loginTracker, - ISleep sleep, - IGoogleAppsIdentityCreator identityCreator, - IUrlEncoder encoder, - IUserService userService) : - base( - log, - authTokenHandler, - principalToUserResourceMapper, - configurationStore, - authCookieCreator, - loginTracker, - sleep, - identityCreator, - encoder, - userService) - { - } - - protected override string ProviderName => GoogleAppsAuthenticationProvider.ProviderName; - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticatedPkceAction.cs b/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticatedPkceAction.cs deleted file mode 100644 index 71cf361..0000000 --- a/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticatedPkceAction.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Identities; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Tokens; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Server.Extensibility.Mediator; -using Octopus.Time; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Web -{ - class GoogleAppsUserAuthenticatedPkceAction - : UserAuthenticatedPkceAction - { - public GoogleAppsUserAuthenticatedPkceAction( - ISystemLog log, - IGoogleAuthTokenHandler authTokenHandler, - IPrincipalToUserResourceMapper principalToUserResourceMapper, - IGoogleAppsConfigurationStore configurationStore, - IAuthCookieCreator authCookieCreator, - IInvalidLoginTracker loginTracker, - ISleep sleep, - IGoogleAppsIdentityCreator identityCreator, - IUrlEncoder encoder, - IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, - IMediator mediator, - IUserService service) - : base(log, - authTokenHandler, - principalToUserResourceMapper, - configurationStore, - authCookieCreator, - loginTracker, - sleep, - identityCreator, - encoder, - identityProviderConfigDiscoverer, - mediator, - service) - { - } - - protected override string ProviderName => GoogleAppsAuthenticationProvider.ProviderName; - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticationAction.cs b/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticationAction.cs deleted file mode 100644 index b1d99f0..0000000 --- a/source/Server.GoogleApps/Web/GoogleAppsUserAuthenticationAction.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Configuration; -using Octopus.Server.Extensibility.Authentication.GoogleApps.Issuer; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; -using Octopus.Server.Extensibility.Mediator; - -namespace Octopus.Server.Extensibility.Authentication.GoogleApps.Web -{ - class GoogleAppsUserAuthenticationAction : UserAuthenticationAction - { - public GoogleAppsUserAuthenticationAction( - ISystemLog log, - IGoogleAppsConfigurationStore configurationStore, - IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, - IGoogleAppsAuthorizationEndpointUrlBuilder urlBuilder, - IApiActionModelBinder modelBinder, - IAuthenticationConfigurationStore authenticationConfigurationStore, - IMediator mediator) - : base(log, configurationStore, identityProviderConfigDiscoverer, urlBuilder, modelBinder, authenticationConfigurationStore, mediator) - { - } - } -} \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/Static/areas/users/googleApps_auth_provider.js b/source/Server.GoogleApps/Web/Static/areas/users/googleApps_auth_provider.js deleted file mode 100644 index 9444ee0..0000000 --- a/source/Server.GoogleApps/Web/Static/areas/users/googleApps_auth_provider.js +++ /dev/null @@ -1,45 +0,0 @@ -(function (providerName) { - -function googleAuthProvider(octopusClient, provider, loginState, onError, isDarkMode) { - //The following styling and structure is following google's branding guidelines. Please see https://developers.google.com/identity/branding-guidelines - //Please note that we do not get cache busting for free for anything inside of the following html snippet. We therefore need to manually - //rev the version for assets like the google logo if we need to make changes. - this.linkHtml = ` - -
-
- Login using Google Auth -
- Sign in with Google -
-
- `; - - this.signIn = function () { - - console.log("Signing in using " + providerName + " provider"); - - var authLink = provider.Links.Authenticate; - var redirectToLink = function (externalProviderLink) { - window.location.href = externalProviderLink.ExternalAuthenticationUrl; - }; - var postData = { - ApiAbsUrl: octopusClient.resolve("~/"), - State: loginState - }; - - octopusClient.post(authLink, postData) - .then(redirectToLink, onError); - }; - - return { - Name: providerName, - LinkHtml: this.linkHtml, - SignIn: this.signIn - }; -} - -console.log("Registering " + providerName + " auth provider"); -window.Octopus.registerExtension(providerName, "auth_provider", googleAuthProvider); - -})("Google Apps"); \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/Static/fonts/LICENSE.txt b/source/Server.GoogleApps/Web/Static/fonts/LICENSE.txt deleted file mode 100644 index d645695..0000000 --- a/source/Server.GoogleApps/Web/Static/fonts/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Black.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-Black.ttf deleted file mode 100644 index fbde625..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Black.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-BlackItalic.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-BlackItalic.ttf deleted file mode 100644 index 60f7782..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-BlackItalic.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Bold.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-Bold.ttf deleted file mode 100644 index a355c27..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Bold.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-BoldItalic.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-BoldItalic.ttf deleted file mode 100644 index 3c9a7a3..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-BoldItalic.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Italic.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-Italic.ttf deleted file mode 100644 index ff6046d..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Italic.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Light.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-Light.ttf deleted file mode 100644 index 94c6bcc..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Light.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-LightItalic.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-LightItalic.ttf deleted file mode 100644 index 04cc002..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-LightItalic.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Medium.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-Medium.ttf deleted file mode 100644 index 39c63d7..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Medium.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-MediumItalic.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-MediumItalic.ttf deleted file mode 100644 index dc743f0..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-MediumItalic.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Regular.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-Regular.ttf deleted file mode 100644 index 8c082c8..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Regular.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Thin.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-Thin.ttf deleted file mode 100644 index d695550..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-Thin.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/fonts/Roboto-ThinItalic.ttf b/source/Server.GoogleApps/Web/Static/fonts/Roboto-ThinItalic.ttf deleted file mode 100644 index 07172ff..0000000 Binary files a/source/Server.GoogleApps/Web/Static/fonts/Roboto-ThinItalic.ttf and /dev/null differ diff --git a/source/Server.GoogleApps/Web/Static/images/google_signin_buttons/icon-google-v1.svg b/source/Server.GoogleApps/Web/Static/images/google_signin_buttons/icon-google-v1.svg deleted file mode 100644 index a98fb41..0000000 --- a/source/Server.GoogleApps/Web/Static/images/google_signin_buttons/icon-google-v1.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/source/Server.GoogleApps/Web/Static/styles/googleApps.css b/source/Server.GoogleApps/Web/Static/styles/googleApps.css deleted file mode 100644 index edc0be7..0000000 --- a/source/Server.GoogleApps/Web/Static/styles/googleApps.css +++ /dev/null @@ -1,42 +0,0 @@ -.googleapps-button { - cursor: pointer; - border-radius: 2px; - box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.24), 0 0 1px 0 rgba(0, 0, 0, 0.12); - display: flex; - align-items: stretch; -} - -.googleapps-button-image { - display:flex; - justify-content: center; - align-items: center; - padding-left: 0.8125rem; - padding-right: 0.8125rem; -} - -.googleapps-button.light { - background-color: #fff; - color: #757575; -} - -.googleapps-button.dark { - background-color: #4285f4; - color: #fff; -} - -.googleapps-button:hover{ - box-shadow: 0 0 3px 3px rgba(66,133,244,.3); -} - -.googleapps-button.dark > .googleapps-button-image { - background-color: #fff; - border: solid 1px #4285f4; -} - -.googleapps-button-text { - padding: 0.8125rem; - font-family: "Roboto", sans-serif; - font-weight: 600; - text-align: left; - overflow: hidden; -} diff --git a/source/Server.OctopusID/Configuration/IOctopusIDConfigurationSettings.cs b/source/Server.OctopusID/Configuration/IOctopusIDConfigurationSettings.cs deleted file mode 100644 index ba66a31..0000000 --- a/source/Server.OctopusID/Configuration/IOctopusIDConfigurationSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - interface IOctopusIDConfigurationSettings: IHasConfigurationSettings - { } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Configuration/IOctopusIDConfigurationStore.cs b/source/Server.OctopusID/Configuration/IOctopusIDConfigurationStore.cs deleted file mode 100644 index 89121ee..0000000 --- a/source/Server.OctopusID/Configuration/IOctopusIDConfigurationStore.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - interface IOctopusIDConfigurationStore : IOpenIDConnectConfigurationWithRoleStore - { - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Configuration/OctopusIDConfiguration.cs b/source/Server.OctopusID/Configuration/OctopusIDConfiguration.cs deleted file mode 100644 index 16214a9..0000000 --- a/source/Server.OctopusID/Configuration/OctopusIDConfiguration.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - class OctopusIDConfiguration : OpenIDConnectConfiguration, IOpenIDConnectConfigurationWithRole - { - public static string DefaultRoleClaimType = "roles"; - - public OctopusIDConfiguration() : base(OctopusIDConfigurationStore.SingletonId, "OctopusID", "Octopus Deploy", "1.1") - { - Issuer = "https://account.octopus.com"; - Scope = DefaultScope; - RoleClaimType = DefaultRoleClaimType; - } - - public string? RoleClaimType { get; set; } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Configuration/OctopusIDConfigurationMapping.cs b/source/Server.OctopusID/Configuration/OctopusIDConfigurationMapping.cs deleted file mode 100644 index d6723ba..0000000 --- a/source/Server.OctopusID/Configuration/OctopusIDConfigurationMapping.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - class OctopusIDConfigurationMapping : IConfigurationDocumentMapper - { - public Type GetTypeToMap() => typeof(OctopusIDConfiguration); - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Configuration/OctopusIDConfigurationResource.cs b/source/Server.OctopusID/Configuration/OctopusIDConfigurationResource.cs deleted file mode 100644 index ff2b0bb..0000000 --- a/source/Server.OctopusID/Configuration/OctopusIDConfigurationResource.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.ComponentModel; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.MessageContracts; -using Octopus.Server.MessageContracts.Attributes; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - [Description("Sign in to your Octopus Server with an Octopus ID. [Learn more](https://g.octopushq.com/AuthOctopusID).")] - class OctopusIDConfigurationResource : OpenIDConnectConfigurationResource - { - [Writeable] - public override string? Issuer { get; set; } - - /// - /// NOTE: the following properties are here to control the order they appear on the settings page - /// - - [Writeable] - public override string? ClientId { get; set; } - - [Writeable] - public override SensitiveValue? ClientSecret { get; set; } - - [Writeable] - public override bool? AllowAutoUserCreation { get; set; } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Configuration/OctopusIDConfigurationSettings.cs b/source/Server.OctopusID/Configuration/OctopusIDConfigurationSettings.cs deleted file mode 100644 index b54504a..0000000 --- a/source/Server.OctopusID/Configuration/OctopusIDConfigurationSettings.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using Octopus.Data.Model; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - class OctopusIDConfigurationSettings : OpenIDConnectConfigurationSettings, IOctopusIDConfigurationSettings - { - public OctopusIDConfigurationSettings(IOctopusIDConfigurationStore configurationDocumentStore) : base(configurationDocumentStore) - { - } - - public override string Id => OctopusIDConfigurationStore.SingletonId; - - public override string ConfigurationSetName => "Octopus ID"; - - public override string Description => "Octopus ID authentication settings"; - - public override IEnumerable GetConfigurationValues() - { - var configurationSettingsName = ConfigurationDocumentStore.ConfigurationSettingsName; - var isEnabled = ConfigurationDocumentStore.GetIsEnabled(); - - return new IConfigurationValue[] - { - new ConfigurationValue($"Octopus.{configurationSettingsName}.IsEnabled", isEnabled, isEnabled, "Is Enabled"), - new ConfigurationValue($"Octopus.{configurationSettingsName}.Issuer", ConfigurationDocumentStore.GetIssuer(), isEnabled, "Issuer"), - new ConfigurationValue($"Octopus.{configurationSettingsName}.ClientId", ConfigurationDocumentStore.GetClientId(), isEnabled, "ClientId"), - new ConfigurationValue($"Octopus.{configurationSettingsName}.ClientSecret", ConfigurationDocumentStore.GetClientSecret(), isEnabled && !string.IsNullOrWhiteSpace(ConfigurationDocumentStore.GetClientSecret()?.Value), "Client Secret"), - new ConfigurationValue($"Octopus.{configurationSettingsName}.AllowAutoUserCreation", ConfigurationDocumentStore.GetAllowAutoUserCreation(), isEnabled, "Allow auto user creation") - }; - } - } -} diff --git a/source/Server.OctopusID/Configuration/OctopusIDConfigurationStore.cs b/source/Server.OctopusID/Configuration/OctopusIDConfigurationStore.cs deleted file mode 100644 index a2a3cfc..0000000 --- a/source/Server.OctopusID/Configuration/OctopusIDConfigurationStore.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Octopus.Data.Storage.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - class OctopusIDConfigurationStore : OpenIDConnectConfigurationStore, IOctopusIDConfigurationStore - { - public const string SingletonId = "authentication-octopusid"; - - public override string Id => SingletonId; - - public override string ConfigurationSettingsName => "OctopusID"; - - public OctopusIDConfigurationStore( - IConfigurationStore configurationStore) : base(configurationStore) - { - } - - public string? GetRoleClaimType() - { - return GetProperty(doc => doc.RoleClaimType); - } - - public void SetRoleClaimType(string? roleClaimType) - { - SetProperty(doc => doc.RoleClaimType = roleClaimType); - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Configuration/OctopusIDConfigureCommands.cs b/source/Server.OctopusID/Configuration/OctopusIDConfigureCommands.cs deleted file mode 100644 index 0a7e8b8..0000000 --- a/source/Server.OctopusID/Configuration/OctopusIDConfigureCommands.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using Octopus.Data.Model; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; -using Octopus.Server.Extensibility.HostServices.Web; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - class OctopusIDConfigureCommands : OpenIDConnectConfigureCommands - { - public OctopusIDConfigureCommands( - ISystemLog log, - Lazy configurationStore, - Lazy webPortalConfigurationStore) - : base(log, configurationStore, webPortalConfigurationStore) - { - } - - protected override string ConfigurationSettingsName => "octopusId"; - - public override IEnumerable GetOptions() - { - foreach (var option in base.GetCoreOptions(hide: true)) - { - yield return option; - } - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Configuration/OctopusIDDatabaseInitializer.cs b/source/Server.OctopusID/Configuration/OctopusIDDatabaseInitializer.cs deleted file mode 100644 index 4b88611..0000000 --- a/source/Server.OctopusID/Configuration/OctopusIDDatabaseInitializer.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Octopus.Data.Storage.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Configuration -{ - class OctopusIDDatabaseInitializer : DatabaseInitializer - { - readonly IConfigurationStore configurationStore; - - public OctopusIDDatabaseInitializer(IConfigurationStore configurationStore) : base(configurationStore) - { - this.configurationStore = configurationStore; - } - - protected override string SingletonId => OctopusIDConfigurationStore.SingletonId; - - public override void Execute() - { - base.Execute(); - - var doc = configurationStore.Get(SingletonId); - - if (doc.ConfigurationSchemaVersion == "1.0") - { - // the plugin was initially intended for hosted only, and was going to be always enabled. When - // the distribution changed to include in all instances the default wasn't changed back to false. - // This is a once off change to disable the provider in any existing instances that haven't been - // configured by the cloud infrastructure to have to use Octopus ID - doc.IsEnabled = !string.IsNullOrWhiteSpace(doc.ClientId); - doc.ConfigurationSchemaVersion = "1.1"; - - configurationStore.Update(doc); - } - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/IOctopusIdentityProviderConfigDiscoverer.cs b/source/Server.OctopusID/IOctopusIdentityProviderConfigDiscoverer.cs deleted file mode 100644 index 579b074..0000000 --- a/source/Server.OctopusID/IOctopusIdentityProviderConfigDiscoverer.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID -{ - interface IOctopusIdentityProviderConfigDiscoverer : IIdentityProviderConfigDiscoverer - { - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Identities/IOctopusIDIdentityCreator.cs b/source/Server.OctopusID/Identities/IOctopusIDIdentityCreator.cs deleted file mode 100644 index 4888e5c..0000000 --- a/source/Server.OctopusID/Identities/IOctopusIDIdentityCreator.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Identities; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Identities -{ - interface IOctopusIDIdentityCreator : IIdentityCreator - { } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Identities/OctopusIDIdentityCreator.cs b/source/Server.OctopusID/Identities/OctopusIDIdentityCreator.cs deleted file mode 100644 index 9771106..0000000 --- a/source/Server.OctopusID/Identities/OctopusIDIdentityCreator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Identities; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Identities -{ - class OctopusIDIdentityCreator : IdentityCreator, IOctopusIDIdentityCreator - { - protected override string ProviderName => OctopusIDAuthenticationProvider.ProviderName; - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Infrastructure/IOctopusIDPrincipalToUserResourceMapper.cs b/source/Server.OctopusID/Infrastructure/IOctopusIDPrincipalToUserResourceMapper.cs deleted file mode 100644 index cad242d..0000000 --- a/source/Server.OctopusID/Infrastructure/IOctopusIDPrincipalToUserResourceMapper.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Infrastructure -{ - interface IOctopusIDPrincipalToUserResourceMapper : IPrincipalToUserResourceMapper - { - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Infrastructure/OctopusIDPrincipalToUserResourceMapper.cs b/source/Server.OctopusID/Infrastructure/OctopusIDPrincipalToUserResourceMapper.cs deleted file mode 100644 index 2a937e5..0000000 --- a/source/Server.OctopusID/Infrastructure/OctopusIDPrincipalToUserResourceMapper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Infrastructure -{ - class OctopusIDPrincipalToUserResourceMapper : PrincipalToUserResourceMapper, IOctopusIDPrincipalToUserResourceMapper - { - readonly IOctopusIDConfigurationStore configurationStore; - - public OctopusIDPrincipalToUserResourceMapper(IOctopusIDConfigurationStore configurationStore) - { - this.configurationStore = configurationStore; - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Issuer/IOctopusIDAuthorizationEndpointUrlBuilder.cs b/source/Server.OctopusID/Issuer/IOctopusIDAuthorizationEndpointUrlBuilder.cs deleted file mode 100644 index b7e7672..0000000 --- a/source/Server.OctopusID/Issuer/IOctopusIDAuthorizationEndpointUrlBuilder.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Issuer -{ - interface IOctopusIDAuthorizationEndpointUrlBuilder : IAuthorizationEndpointUrlBuilder - { } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Issuer/IOctopusIDKeyRetriever.cs b/source/Server.OctopusID/Issuer/IOctopusIDKeyRetriever.cs deleted file mode 100644 index 54fb6e6..0000000 --- a/source/Server.OctopusID/Issuer/IOctopusIDKeyRetriever.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Issuer -{ - interface IOctopusIDKeyRetriever : IKeyRetriever - { - - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Issuer/OctopusIDAuthorizationEndpointUrlBuilder.cs b/source/Server.OctopusID/Issuer/OctopusIDAuthorizationEndpointUrlBuilder.cs deleted file mode 100644 index 59ea0ea..0000000 --- a/source/Server.OctopusID/Issuer/OctopusIDAuthorizationEndpointUrlBuilder.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.HostServices.Web; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Issuer -{ - class OctopusIDAuthorizationEndpointUrlBuilder : AuthorizationEndpointUrlBuilder, IOctopusIDAuthorizationEndpointUrlBuilder - { - public OctopusIDAuthorizationEndpointUrlBuilder(IOctopusIDConfigurationStore configurationStore, IUrlEncoder urlEncoder) : base(configurationStore, urlEncoder) - { - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Issuer/OctopusIDKeyRetriever.cs b/source/Server.OctopusID/Issuer/OctopusIDKeyRetriever.cs deleted file mode 100644 index c9b11e4..0000000 --- a/source/Server.OctopusID/Issuer/OctopusIDKeyRetriever.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Issuer -{ - class OctopusIDKeyRetriever : KeyRetriever, IOctopusIDKeyRetriever - { - public OctopusIDKeyRetriever(ISystemLog log, IOctopusIDConfigurationStore configurationStore, IKeyJsonParser keyParser) : base(log, configurationStore, keyParser) - { - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/OctopusIDApi.cs b/source/Server.OctopusID/OctopusIDApi.cs deleted file mode 100644 index be10818..0000000 --- a/source/Server.OctopusID/OctopusIDApi.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OctopusID.Identities; -using Octopus.Server.Extensibility.Authentication.OctopusID.Tokens; -using Octopus.Server.Extensibility.Authentication.OctopusID.Web; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID -{ - class OctopusIDApi : OpenIDConnectModule - { - public OctopusIDApi( - IOctopusIDConfigurationStore configurationStore, OctopusIDAuthenticationProvider authenticationProvider) - : base(configurationStore, authenticationProvider) - { - Add("POST", authenticationProvider.AuthenticateUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("POST", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("GET", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/OctopusIDAuthenticationProvider.cs b/source/Server.OctopusID/OctopusIDAuthenticationProvider.cs deleted file mode 100644 index c7b7e32..0000000 --- a/source/Server.OctopusID/OctopusIDAuthenticationProvider.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID -{ - class OctopusIDAuthenticationProvider : OpenIDConnectAuthenticationProvider - { - public const string ProviderName = "Octopus ID"; - - public OctopusIDAuthenticationProvider(ISystemLog log, IOctopusIDConfigurationStore configurationStore) : base(log, configurationStore) - { - } - - public override string IdentityProviderName => ProviderName; - public override string FilenamePrefix => "octopusId"; - - protected override IEnumerable ReasonsWhyConfigIsIncomplete() - { - var issuer = ConfigurationStore.GetIssuer(); - if (string.IsNullOrWhiteSpace(issuer)) - yield return $"No {IdentityProviderName} issuer specified"; - if (string.IsNullOrWhiteSpace(ConfigurationStore.GetClientId())) - yield return $"No {IdentityProviderName} Client ID specified"; - } - } -} diff --git a/source/Server.OctopusID/OctopusIDExtension.cs b/source/Server.OctopusID/OctopusIDExtension.cs deleted file mode 100644 index dadc5eb..0000000 --- a/source/Server.OctopusID/OctopusIDExtension.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Autofac; -using Octopus.Server.Extensibility.Authentication.Extensions; -using Octopus.Server.Extensibility.Authentication.Extensions.Identities; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OctopusID.Identities; -using Octopus.Server.Extensibility.Authentication.OctopusID.Infrastructure; -using Octopus.Server.Extensibility.Authentication.OctopusID.Issuer; -using Octopus.Server.Extensibility.Authentication.OctopusID.Tokens; -using Octopus.Server.Extensibility.Authentication.OctopusID.Web; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; -using Octopus.Server.Extensibility.Extensions; -using Octopus.Server.Extensibility.Extensions.Infrastructure; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; -using Octopus.Server.Extensibility.Extensions.Mappings; -using Octopus.Server.Extensibility.HostServices.Web; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID -{ - [OctopusPlugin("OctopusID", "Octopus Deploy")] - public class OctopusIDExtension : OpenIDConnectExtension, IOctopusExtension - { - public override void Load(ContainerBuilder builder) - { - base.Load(builder); - - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType() - .As() - .InstancePerDependency(); - builder.RegisterType() - .As() - .As() - .As() - .As() - .InstancePerDependency(); - builder.RegisterType() - .As() - .InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - - // These are important as Singletons because they cache X509 certificates for performance - builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().AsSelf().InstancePerDependency(); - builder.RegisterType().AsSelf().InstancePerDependency(); - builder.RegisterType().AsSelf().InstancePerDependency(); - - builder.RegisterType() - .As() - .As() - .As() - .As() - .As() - .AsSelf() - .InstancePerDependency(); - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/OctopusIdConfigDiscoverer.cs b/source/Server.OctopusID/OctopusIdConfigDiscoverer.cs deleted file mode 100644 index bad8f74..0000000 --- a/source/Server.OctopusID/OctopusIdConfigDiscoverer.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Threading.Tasks; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID -{ - class OctopusIdConfigDiscoverer : IOctopusIdentityProviderConfigDiscoverer - { - public Task GetConfiguration(string issuer) - { - return Task.FromResult(new IssuerConfiguration - { - Issuer = issuer.WithTrailingSlash(), - AuthorizationEndpoint = $"{issuer.WithoutTrailingSlash()}/oauth2/authorize" - }); - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Properties/AssemblyInfo.cs b/source/Server.OctopusID/Properties/AssemblyInfo.cs deleted file mode 100644 index f460293..0000000 --- a/source/Server.OctopusID/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Tests")] diff --git a/source/Server.OctopusID/Server.OctopusID.csproj b/source/Server.OctopusID/Server.OctopusID.csproj deleted file mode 100644 index d32bc47..0000000 --- a/source/Server.OctopusID/Server.OctopusID.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - - net6.0 - Octopus.Server.Extensibility.Authentication.OctopusID - Octopus.Server.Extensibility.Authentication.OctopusID - Octopus Deploy: Extensibility.Authentication.OctopusID - Octopus Deploy - http://i.octopusdeploy.com/resources/Avatar3_360.png - Apache-2.0 - https://github.com/OctopusDeploy/OpenIDConnectAuthenticationProviders - enable - true - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/Server.OctopusID/StringExtensions.cs b/source/Server.OctopusID/StringExtensions.cs deleted file mode 100644 index 8249489..0000000 --- a/source/Server.OctopusID/StringExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Octopus.Server.Extensibility.Authentication.OctopusID -{ - static class StringExtensions - { - public static string WithTrailingSlash(this string uri) - { - return $"{uri.TrimEnd('/')}/"; - } - - public static string WithoutTrailingSlash(this string uri) - { - return uri.TrimEnd('/'); - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Tokens/IOctopusIDAuthTokenHandler.cs b/source/Server.OctopusID/Tokens/IOctopusIDAuthTokenHandler.cs deleted file mode 100644 index f4a3ed6..0000000 --- a/source/Server.OctopusID/Tokens/IOctopusIDAuthTokenHandler.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Tokens -{ - interface IOctopusIDAuthTokenHandler : IAuthTokenHandler - { } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Tokens/OctopusIDAuthTokenHandler.cs b/source/Server.OctopusID/Tokens/OctopusIDAuthTokenHandler.cs deleted file mode 100644 index 20d3efd..0000000 --- a/source/Server.OctopusID/Tokens/OctopusIDAuthTokenHandler.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OctopusID.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Tokens -{ - class OctopusIDAuthTokenHandler : OpenIDConnectAuthTokenWithRolesHandler, IOctopusIDAuthTokenHandler - { - public OctopusIDAuthTokenHandler(ISystemLog log, IOctopusIDConfigurationStore configurationStore, IOctopusIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, IOctopusIDKeyRetriever keyRetriever) : base(log, configurationStore, identityProviderConfigDiscoverer, keyRetriever) - { - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Web/OctopusIDHomeLinksContributor.cs b/source/Server.OctopusID/Web/OctopusIDHomeLinksContributor.cs deleted file mode 100644 index f2f4269..0000000 --- a/source/Server.OctopusID/Web/OctopusIDHomeLinksContributor.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Web -{ - class OctopusIDHomeLinksContributor : OpenIDConnectHomeLinksContributor - { - public OctopusIDHomeLinksContributor(IOctopusIDConfigurationStore configurationStore, OctopusIDAuthenticationProvider authenticationProvider) : base(configurationStore, authenticationProvider) - { - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Web/OctopusIDLoginParametersHandler.cs b/source/Server.OctopusID/Web/OctopusIDLoginParametersHandler.cs deleted file mode 100644 index 3d58120..0000000 --- a/source/Server.OctopusID/Web/OctopusIDLoginParametersHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Linq; -using Octopus.Server.Extensibility.Authentication.Extensions; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.Web; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Web -{ - class OctopusIDLoginParametersHandler : ICanHandleLoginParameters - { - readonly IOctopusIDConfigurationStore configurationStore; - - public OctopusIDLoginParametersHandler(IOctopusIDConfigurationStore configurationStore) - { - this.configurationStore = configurationStore; - } - - public string IdentityProviderName => OctopusIDAuthenticationProvider.ProviderName; - - public bool? WasExternalLoginInitiated(string encodedQueryString) - { - if (!configurationStore.GetIsEnabled()) - return null; - - var parser = new EncodedQueryStringParser(); - var parameters = parser.Parse(encodedQueryString); - - var issuerParam = parameters.FirstOrDefault(p => p.Name == "iss"); - - var configuredIssuer = configurationStore.GetIssuer(); - - return issuerParam != null && string.Compare(configuredIssuer, issuerParam.Value, StringComparison.InvariantCultureIgnoreCase) == 0; - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Web/OctopusIDStaticContentFolders.cs b/source/Server.OctopusID/Web/OctopusIDStaticContentFolders.cs deleted file mode 100644 index a5e790f..0000000 --- a/source/Server.OctopusID/Web/OctopusIDStaticContentFolders.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using System.Reflection; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Web -{ - class OctopusIDStaticContentFolders : IContributesStaticContentFolders - { - public IEnumerable GetStaticContentFolders() - { - var type = typeof(OctopusIDStaticContentFolders); - var assembly = type.GetTypeInfo().Assembly; - return new[] { new StaticContentEmbeddedResourcesFolder("", assembly, type.Namespace + ".Static") }; - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Web/OctopusIDUserAuthenticatedAction.cs b/source/Server.OctopusID/Web/OctopusIDUserAuthenticatedAction.cs deleted file mode 100644 index f085484..0000000 --- a/source/Server.OctopusID/Web/OctopusIDUserAuthenticatedAction.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OctopusID.Identities; -using Octopus.Server.Extensibility.Authentication.OctopusID.Infrastructure; -using Octopus.Server.Extensibility.Authentication.OctopusID.Tokens; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Time; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Web -{ - class OctopusIDUserAuthenticatedAction : UserAuthenticatedAction - { - public OctopusIDUserAuthenticatedAction( - ISystemLog log, - IOctopusIDAuthTokenHandler authTokenHandler, - IOctopusIDPrincipalToUserResourceMapper principalToUserResourceMapper, - IOctopusIDConfigurationStore configurationStore, - IAuthCookieCreator authCookieCreator, - IInvalidLoginTracker loginTracker, - ISleep sleep, - IOctopusIDIdentityCreator identityCreator, - IUrlEncoder encoder, - IUserService userService) : - base( - log, - authTokenHandler, - principalToUserResourceMapper, - configurationStore, - authCookieCreator, - loginTracker, - sleep, - identityCreator, - encoder, - userService) - { - } - - protected override string ProviderName => OctopusIDAuthenticationProvider.ProviderName; - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Web/OctopusIDUserAuthenticatedPkceAction.cs b/source/Server.OctopusID/Web/OctopusIDUserAuthenticatedPkceAction.cs deleted file mode 100644 index 9a3d218..0000000 --- a/source/Server.OctopusID/Web/OctopusIDUserAuthenticatedPkceAction.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OctopusID.Identities; -using Octopus.Server.Extensibility.Authentication.OctopusID.Tokens; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Server.Extensibility.Mediator; -using Octopus.Time; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Web -{ - class OctopusIDUserAuthenticatedPkceAction - : UserAuthenticatedPkceAction - { - public OctopusIDUserAuthenticatedPkceAction( - ISystemLog log, - IOctopusIDAuthTokenHandler authTokenHandler, - IPrincipalToUserResourceMapper principalToUserResourceMapper, - IOctopusIDConfigurationStore configurationStore, - IAuthCookieCreator authCookieCreator, - IInvalidLoginTracker loginTracker, - ISleep sleep, - IOctopusIDIdentityCreator identityCreator, - IUrlEncoder encoder, - IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, - IMediator mediator, - IUserService service) - : base(log, - authTokenHandler, - principalToUserResourceMapper, - configurationStore, - authCookieCreator, - loginTracker, - sleep, - identityCreator, - encoder, - identityProviderConfigDiscoverer, - mediator, - service) - { - } - - protected override string ProviderName => OctopusIDAuthenticationProvider.ProviderName; - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Web/OctopusIDUserAuthenticationAction.cs b/source/Server.OctopusID/Web/OctopusIDUserAuthenticationAction.cs deleted file mode 100644 index dc21594..0000000 --- a/source/Server.OctopusID/Web/OctopusIDUserAuthenticationAction.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.OctopusID.Configuration; -using Octopus.Server.Extensibility.Authentication.OctopusID.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; -using Octopus.Server.Extensibility.Mediator; - -namespace Octopus.Server.Extensibility.Authentication.OctopusID.Web -{ - class OctopusIDUserAuthenticationAction : UserAuthenticationAction - { - public OctopusIDUserAuthenticationAction( - ISystemLog log, - IOctopusIDConfigurationStore configurationStore, - IOctopusIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, - IOctopusIDAuthorizationEndpointUrlBuilder urlBuilder, - IApiActionModelBinder modelBinder, - IAuthenticationConfigurationStore authenticationConfigurationStore, - IMediator mediator) : base(log, configurationStore, identityProviderConfigDiscoverer, urlBuilder, modelBinder, authenticationConfigurationStore, mediator) - { - } - } -} \ No newline at end of file diff --git a/source/Server.OctopusID/Web/Static/areas/users/octopusId_auth_provider.js b/source/Server.OctopusID/Web/Static/areas/users/octopusId_auth_provider.js deleted file mode 100644 index 48fe486..0000000 --- a/source/Server.OctopusID/Web/Static/areas/users/octopusId_auth_provider.js +++ /dev/null @@ -1,33 +0,0 @@ -(function (providerName) { - -function octopusIDAuthProvider(octopusClient, provider, loginState, onError) { - - this.linkHtml = '
Sign in with your Octopus ID
'; - - this.signIn = function () { - console.log("Signing in using " + providerName + " provider"); - - var authUri = provider.Links.Authenticate; - var redirectToLink = function (externalProviderLink) { - window.location.href = externalProviderLink.ExternalAuthenticationUrl; - }; - var postData = { - ApiAbsUrl: octopusClient.resolve("~/"), - State: loginState - }; - - octopusClient.post(authUri, postData) - .then(redirectToLink, onError); - }; - - return { - Name: providerName, - LinkHtml: this.linkHtml, - SignIn: this.signIn - }; -} - -console.log("Registering " + providerName + " auth provider"); -window.Octopus.registerExtension(providerName, "auth_provider", octopusIDAuthProvider); - -})("Octopus ID"); diff --git a/source/Server.OctopusID/Web/Static/images/Octopus-96x96.png b/source/Server.OctopusID/Web/Static/images/Octopus-96x96.png deleted file mode 100644 index 4e4a05d..0000000 Binary files a/source/Server.OctopusID/Web/Static/images/Octopus-96x96.png and /dev/null differ diff --git a/source/Server.OctopusID/Web/Static/styles/octopusId.css b/source/Server.OctopusID/Web/Static/styles/octopusId.css deleted file mode 100644 index a0b9886..0000000 --- a/source/Server.OctopusID/Web/Static/styles/octopusId.css +++ /dev/null @@ -1,34 +0,0 @@ - -.octopusID-button { - cursor: pointer; - border-radius: 2px; - box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.24), 0 0 1px 0 rgba(0, 0, 0, 0.12); - display: flex; - align-items: center; - padding-top: 0.8125rem; - padding-bottom: 0.8125rem; - background-color: #54B954; - color: #fff; -} - -.octopusID-button:hover { - background-color: #449744; - color: #fff; -} - -.octopusID-button img { - margin-left: 0.8125rem; - width: 23px; - height: 22px; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; -} - -.octopusID-button div { - font-weight: 400; - display: inline-block; - text-align: left; - margin-left: 0.8125rem; - overflow: hidden; -} diff --git a/source/Server.Okta/Configuration/IOktaConfigurationSettings.cs b/source/Server.Okta/Configuration/IOktaConfigurationSettings.cs deleted file mode 100644 index 868fa19..0000000 --- a/source/Server.Okta/Configuration/IOktaConfigurationSettings.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - interface IOktaConfigurationSettings: IHasConfigurationSettings - { } -} \ No newline at end of file diff --git a/source/Server.Okta/Configuration/IOktaConfigurationStore.cs b/source/Server.Okta/Configuration/IOktaConfigurationStore.cs deleted file mode 100644 index 40af8d4..0000000 --- a/source/Server.Okta/Configuration/IOktaConfigurationStore.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - interface IOktaConfigurationStore : IOpenIDConnectConfigurationWithRoleStore - { - string GetUsernameClaimType(); - void SetUsernameClaimType(string usernameClaimType); - } -} \ No newline at end of file diff --git a/source/Server.Okta/Configuration/OktaConfiguration.cs b/source/Server.Okta/Configuration/OktaConfiguration.cs deleted file mode 100644 index 61ff79d..0000000 --- a/source/Server.Okta/Configuration/OktaConfiguration.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - class OktaConfiguration : OpenIDConnectConfigurationWithRole - { - public static string DefaultRoleClaimType = "groups"; - public static string DefaultUsernameClaimType = "preferred_username"; - - public OktaConfiguration() : base(OktaConfigurationStore.SingletonId, "Okta", "Octopus Deploy", "1.0") - { - RoleClaimType = DefaultRoleClaimType; - UsernameClaimType = DefaultUsernameClaimType; - Scope = DefaultScope + "%20groups"; - } - - public string UsernameClaimType { get; set; } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Configuration/OktaConfigurationMapping.cs b/source/Server.Okta/Configuration/OktaConfigurationMapping.cs deleted file mode 100644 index c0d45f8..0000000 --- a/source/Server.Okta/Configuration/OktaConfigurationMapping.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - class OktaConfigurationMapping : IConfigurationDocumentMapper - { - public Type GetTypeToMap() => typeof(OktaConfiguration); - } -} \ No newline at end of file diff --git a/source/Server.Okta/Configuration/OktaConfigurationResource.cs b/source/Server.Okta/Configuration/OktaConfigurationResource.cs deleted file mode 100644 index c30b08e..0000000 --- a/source/Server.Okta/Configuration/OktaConfigurationResource.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.ComponentModel; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.MessageContracts.Attributes; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - [Description("Sign in to your Octopus Server with Okta. [Learn more](https://g.octopushq.com/AuthOkta).")] - class OktaConfigurationResource : OpenIDConnectConfigurationResource - { - [DisplayName("Role Claim Type")] - [Description("Tell Octopus how to find the roles in the security token from Okta")] - [Writeable] - public string? RoleClaimType { get; set; } - - [DisplayName("Username Claim Type")] - [Description("Tell Octopus how to find the value for the Octopus Username in the Okta token. Defaults to \"preferred_username\" if left blank.")] - [Writeable] - public string? UsernameClaimType { get; set; } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Configuration/OktaConfigurationSettings.cs b/source/Server.Okta/Configuration/OktaConfigurationSettings.cs deleted file mode 100644 index 74b0c80..0000000 --- a/source/Server.Okta/Configuration/OktaConfigurationSettings.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - class OktaConfigurationSettings : OpenIDConnectConfigurationSettings, IOktaConfigurationSettings - { - public OktaConfigurationSettings(IOktaConfigurationStore configurationDocumentStore) : base(configurationDocumentStore) - { - } - - public override string Id => OktaConfigurationStore.SingletonId; - public override string Description => "Okta authentication settings"; - - public override IEnumerable GetConfigurationValues() - { - foreach (var configurationValue in base.GetConfigurationValues()) - { - yield return configurationValue; - } - yield return new ConfigurationValue($"Octopus.{ConfigurationDocumentStore.ConfigurationSettingsName}.RoleClaimType", ConfigurationDocumentStore.GetRoleClaimType(), ConfigurationDocumentStore.GetIsEnabled() && ConfigurationDocumentStore.GetRoleClaimType() != OktaConfiguration.DefaultRoleClaimType, "Role Claim Type"); - yield return new ConfigurationValue($"Octopus.{ConfigurationDocumentStore.ConfigurationSettingsName}.UsernameClaimType", ConfigurationDocumentStore.GetUsernameClaimType(), ConfigurationDocumentStore.GetIsEnabled() && ConfigurationDocumentStore.GetUsernameClaimType() != OktaConfiguration.DefaultUsernameClaimType, "Username Claim Type"); - } - } -} diff --git a/source/Server.Okta/Configuration/OktaConfigurationStore.cs b/source/Server.Okta/Configuration/OktaConfigurationStore.cs deleted file mode 100644 index 1667150..0000000 --- a/source/Server.Okta/Configuration/OktaConfigurationStore.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Octopus.Data.Storage.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - class OktaConfigurationStore : OpenIDConnectConfigurationWithRoleStore, IOktaConfigurationStore - { - public const string SingletonId = "authentication-od"; - - public override string Id => SingletonId; - - public override string ConfigurationSettingsName => "Okta"; - - public OktaConfigurationStore( - IConfigurationStore configurationStore) : base(configurationStore) - { - } - - public string GetUsernameClaimType() - { - return GetProperty(doc => doc.UsernameClaimType); - } - - public void SetUsernameClaimType(string usernameClaimType) - { - SetProperty(doc => doc.UsernameClaimType = usernameClaimType); - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Configuration/OktaConfigureCommands.cs b/source/Server.Okta/Configuration/OktaConfigureCommands.cs deleted file mode 100644 index 2f9e9dc..0000000 --- a/source/Server.Okta/Configuration/OktaConfigureCommands.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; -using Octopus.Server.Extensibility.HostServices.Web; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - class OktaConfigureCommands : OpenIDConnectConfigureCommands - { - public OktaConfigureCommands( - ISystemLog log, - Lazy configurationStore, - Lazy webPortalConfigurationStore) - : base(log, configurationStore, webPortalConfigurationStore) - { - } - - protected override string ConfigurationSettingsName => "okta"; - - public override IEnumerable GetOptions() - { - foreach (var option in base.GetOptions()) - { - yield return option; - } - yield return new ConfigureCommandOption($"{ConfigurationSettingsName}RoleClaimType=", "Tell Octopus how to find the roles in the security token from Okta.", v => - { - ConfigurationStore.Value.SetRoleClaimType(v); - Log.Info($"{ConfigurationSettingsName} RoleClaimType set to: {v}"); - }); - yield return new ConfigureCommandOption($"{ConfigurationSettingsName}UsernameClaimType=", "Tell Octopus how to find the value for the Octopus Username in the Okta token. Defaults to \"preferred_username\" if left blank.", v => - { - ConfigurationStore.Value.SetUsernameClaimType(v); - Log.Info($"{ConfigurationSettingsName} UsernameClaimType set to: {v}"); - }); - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Configuration/OktaDatabaseInitializer.cs b/source/Server.Okta/Configuration/OktaDatabaseInitializer.cs deleted file mode 100644 index 6c86fa2..0000000 --- a/source/Server.Okta/Configuration/OktaDatabaseInitializer.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Octopus.Data.Storage.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Configuration -{ - class OktaDatabaseInitializer : DatabaseInitializer - { - public OktaDatabaseInitializer(IConfigurationStore configurationStore) : base(configurationStore) - { - } - - protected override string SingletonId => OktaConfigurationStore.SingletonId; - } -} \ No newline at end of file diff --git a/source/Server.Okta/Identities/OktaIdentityCreator.cs b/source/Server.Okta/Identities/OktaIdentityCreator.cs deleted file mode 100644 index 6f8775a..0000000 --- a/source/Server.Okta/Identities/OktaIdentityCreator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Octopus.Data.Model.User; -using Octopus.Server.Extensibility.Authentication.Model; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Identities; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Identities -{ - class OktaIdentityCreator : IdentityCreator, IOktaIdentityCreator - { - public const string PreferredUsername = "pun"; - - protected override string ProviderName => OktaAuthenticationProvider.ProviderName; - - public override Identity Create(UserResource userResource) - { - var identity = base.Create(userResource); - if (userResource.Username != null && userResource.Username != userResource.EmailAddress && userResource.Username != userResource.ExternalId) - identity = identity.WithClaim(PreferredUsername, userResource.Username, true); - - return identity; - } - } - - interface IOktaIdentityCreator : IIdentityCreator - { } -} \ No newline at end of file diff --git a/source/Server.Okta/Infrastructure/IOktaPrincipalToUserResourceMapper.cs b/source/Server.Okta/Infrastructure/IOktaPrincipalToUserResourceMapper.cs deleted file mode 100644 index 0c89d5e..0000000 --- a/source/Server.Okta/Infrastructure/IOktaPrincipalToUserResourceMapper.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Infrastructure -{ - interface IOktaPrincipalToUserResourceMapper : IPrincipalToUserResourceMapper - { - } -} \ No newline at end of file diff --git a/source/Server.Okta/Infrastructure/OktaPrincipalToUserResourceMapper.cs b/source/Server.Okta/Infrastructure/OktaPrincipalToUserResourceMapper.cs deleted file mode 100644 index f805947..0000000 --- a/source/Server.Okta/Infrastructure/OktaPrincipalToUserResourceMapper.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Security.Claims; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Infrastructure -{ - class OktaPrincipalToUserResourceMapper : PrincipalToUserResourceMapper, IOktaPrincipalToUserResourceMapper - { - readonly IOktaConfigurationStore configurationStore; - - public OktaPrincipalToUserResourceMapper(IOktaConfigurationStore configurationStore) - { - this.configurationStore = configurationStore; - } - - protected override string? GetEmailAddress(ClaimsPrincipal principal) - { - // Grab the email address if it exists as a claim, otherwise get the UPN as a good fallback - return base.GetEmailAddress(principal) ?? GetClaimValue(principal, ClaimTypes.Upn); - } - - protected override string? GetUsername(ClaimsPrincipal principal) - { - // Use the UPN in preference for username - return GetClaimValue(principal, configurationStore.GetUsernameClaimType()) ?? base.GetUsername(principal); - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Issuer/IOktaAuthorizationEndpointUrlBuilder.cs b/source/Server.Okta/Issuer/IOktaAuthorizationEndpointUrlBuilder.cs deleted file mode 100644 index 5be461a..0000000 --- a/source/Server.Okta/Issuer/IOktaAuthorizationEndpointUrlBuilder.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Issuer -{ - interface IOktaAuthorizationEndpointUrlBuilder : IAuthorizationEndpointUrlBuilder - { } -} \ No newline at end of file diff --git a/source/Server.Okta/Issuer/IOktaKeyRetriever.cs b/source/Server.Okta/Issuer/IOktaKeyRetriever.cs deleted file mode 100644 index 1574e27..0000000 --- a/source/Server.Okta/Issuer/IOktaKeyRetriever.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Issuer -{ - interface IOktaKeyRetriever : IKeyRetriever - { - - } -} \ No newline at end of file diff --git a/source/Server.Okta/Issuer/OktaAuthorizationEndpointUrlBuilder.cs b/source/Server.Okta/Issuer/OktaAuthorizationEndpointUrlBuilder.cs deleted file mode 100644 index 53a8d28..0000000 --- a/source/Server.Okta/Issuer/OktaAuthorizationEndpointUrlBuilder.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.HostServices.Web; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Issuer -{ - class OktaAuthorizationEndpointUrlBuilder : AuthorizationEndpointUrlBuilder, IOktaAuthorizationEndpointUrlBuilder - { - public OktaAuthorizationEndpointUrlBuilder(IOktaConfigurationStore configurationStore, IUrlEncoder urlEncoder) : base(configurationStore, urlEncoder) - { - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Issuer/OktaKeyRetriever.cs b/source/Server.Okta/Issuer/OktaKeyRetriever.cs deleted file mode 100644 index 92084fc..0000000 --- a/source/Server.Okta/Issuer/OktaKeyRetriever.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Issuer -{ - class OktaKeyRetriever : KeyRetriever, IOktaKeyRetriever - { - public OktaKeyRetriever(ISystemLog log, IOktaConfigurationStore configurationStore, IKeyJsonParser keyParser) : base(log, configurationStore, keyParser) - { - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/OktaApi.cs b/source/Server.Okta/OktaApi.cs deleted file mode 100644 index 33830b8..0000000 --- a/source/Server.Okta/OktaApi.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.Okta.Identities; -using Octopus.Server.Extensibility.Authentication.Okta.Tokens; -using Octopus.Server.Extensibility.Authentication.Okta.Web; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; - -namespace Octopus.Server.Extensibility.Authentication.Okta -{ - class OktaApi : OpenIDConnectModule - { - public OktaApi(IOktaConfigurationStore configurationStore, OktaAuthenticationProvider authenticationProvider) - : base(configurationStore, authenticationProvider) - { - Add("POST", authenticationProvider.AuthenticateUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("POST", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - Add("GET", configurationStore.RedirectUri, RouteCategory.Raw, new AnonymousWhenEnabledEndpointInvocation(), null, "OpenIDConnect"); - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/OktaAuthenticationProvider.cs b/source/Server.Okta/OktaAuthenticationProvider.cs deleted file mode 100644 index 7cac042..0000000 --- a/source/Server.Okta/OktaAuthenticationProvider.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; - -namespace Octopus.Server.Extensibility.Authentication.Okta -{ - class OktaAuthenticationProvider : OpenIDConnectAuthenticationProvider - { - public const string ProviderName = "Okta"; - - public OktaAuthenticationProvider(ISystemLog log, IOktaConfigurationStore configurationStore) : base(log, configurationStore) - { - } - - public override string IdentityProviderName => ProviderName; - public override string FilenamePrefix => "okta"; - - protected override IEnumerable ReasonsWhyConfigIsIncomplete() - { - var issuer = ConfigurationStore.GetIssuer(); - if (string.IsNullOrWhiteSpace(issuer)) - yield return $"No {IdentityProviderName} issuer specified"; - if (!Uri.IsWellFormedUriString(issuer, UriKind.Absolute)) - yield return $"The {IdentityProviderName} issuer must be an absolute URI (expected format: https://dev-[customer id]-admin.oktapreview.com)"; - if (string.IsNullOrWhiteSpace(ConfigurationStore.GetClientId())) - yield return $"No {IdentityProviderName} Client ID specified"; - } - } -} diff --git a/source/Server.Okta/OktaExtension.cs b/source/Server.Okta/OktaExtension.cs deleted file mode 100644 index 0c3c1b8..0000000 --- a/source/Server.Okta/OktaExtension.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Autofac; -using Octopus.Server.Extensibility.Authentication.Extensions; -using Octopus.Server.Extensibility.Authentication.Extensions.Identities; -using Octopus.Server.Extensibility.Extensions.Infrastructure; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; -using Octopus.Server.Extensibility.Extensions.Mappings; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.Okta.Infrastructure; -using Octopus.Server.Extensibility.Authentication.Okta.Issuer; -using Octopus.Server.Extensibility.Authentication.Okta.Tokens; -using Octopus.Server.Extensibility.Authentication.Okta.Web; -using Octopus.Server.Extensibility.Authentication.Okta.Identities; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Extensions; -using Octopus.Server.Extensibility.HostServices.Web; - -namespace Octopus.Server.Extensibility.Authentication.Okta -{ - [OctopusPlugin("Okta", "Octopus Deploy")] - public class OktaExtension : OpenIDConnectExtension, IOctopusExtension - { - public override void Load(ContainerBuilder builder) - { - base.Load(builder); - - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType() - .As() - .InstancePerDependency(); - builder.RegisterType() - .As() - .As() - .As() - .As() - .InstancePerDependency(); - builder.RegisterType() - .As() - .InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().As().InstancePerDependency(); - - // These are important as Singletons because they cache X509 certificates for performance - builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); - - builder.RegisterType().As().InstancePerDependency(); - - builder.RegisterType().AsSelf().InstancePerDependency(); - builder.RegisterType().AsSelf().InstancePerDependency(); - builder.RegisterType().AsSelf().InstancePerDependency(); - - builder.RegisterType() - .As() - .As() - .As() - .As() - .As() - .AsSelf() - .InstancePerDependency(); - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Properties/launchSettings.json b/source/Server.Okta/Properties/launchSettings.json deleted file mode 100644 index 225ea21..0000000 --- a/source/Server.Okta/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Server.Extensibility.Authentication.Okta": { - "commandName": "Executable", - "executablePath": "..\\..\\..\\..\\..\\..\\OctopusDeploy\\source\\Octopus.Server\\bin\\net452\\Octopus.Server.exe", - "commandLineArgs": "run --instance=master --customExtension=Octopus.Server.Extensibility.Authentication.Okta.dll" - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Server.Okta.csproj b/source/Server.Okta/Server.Okta.csproj deleted file mode 100644 index faa294c..0000000 --- a/source/Server.Okta/Server.Okta.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - - net6.0 - Octopus.Server.Extensibility.Authentication.Okta - Octopus.Server.Extensibility.Authentication.Okta - Octopus Deploy: Extensibility.Authentication.Okta - Octopus Deploy - http://i.octopusdeploy.com/resources/Avatar3_360.png - Apache-2.0 - https://github.com/OctopusDeploy/OpenIDConnectAuthenticationProviders - enable - true - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/Server.Okta/Tokens/IOktaAuthTokenHandler.cs b/source/Server.Okta/Tokens/IOktaAuthTokenHandler.cs deleted file mode 100644 index 1dc755f..0000000 --- a/source/Server.Okta/Tokens/IOktaAuthTokenHandler.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Tokens -{ - interface IOktaAuthTokenHandler : IAuthTokenHandler - { } -} \ No newline at end of file diff --git a/source/Server.Okta/Tokens/OktaAuthTokenHandler.cs b/source/Server.Okta/Tokens/OktaAuthTokenHandler.cs deleted file mode 100644 index cbf77e3..0000000 --- a/source/Server.Okta/Tokens/OktaAuthTokenHandler.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.Okta.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Tokens -{ - class OktaAuthTokenHandler : OpenIDConnectAuthTokenWithRolesHandler, IOktaAuthTokenHandler - { - public OktaAuthTokenHandler(ISystemLog log, IOktaConfigurationStore configurationStore, IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, IOktaKeyRetriever keyRetriever) : base(log, configurationStore, identityProviderConfigDiscoverer, keyRetriever) - { - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Web/OktaHomeLinksContributor.cs b/source/Server.Okta/Web/OktaHomeLinksContributor.cs deleted file mode 100644 index 10fcbb6..0000000 --- a/source/Server.Okta/Web/OktaHomeLinksContributor.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Web -{ - class OktaHomeLinksContributor : OpenIDConnectHomeLinksContributor - { - public OktaHomeLinksContributor(IOktaConfigurationStore configurationStore, OktaAuthenticationProvider authenticationProvider) : base(configurationStore, authenticationProvider) - { - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Web/OktaLoginParametersHandler.cs b/source/Server.Okta/Web/OktaLoginParametersHandler.cs deleted file mode 100644 index ce1f5c3..0000000 --- a/source/Server.Okta/Web/OktaLoginParametersHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Linq; -using Octopus.Server.Extensibility.Authentication.Extensions; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.Web; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Web -{ - class OktaLoginParametersHandler : ICanHandleLoginParameters - { - readonly IOktaConfigurationStore configurationStore; - - public OktaLoginParametersHandler(IOktaConfigurationStore configurationStore) - { - this.configurationStore = configurationStore; - } - - public string IdentityProviderName => OktaAuthenticationProvider.ProviderName; - - public bool? WasExternalLoginInitiated(string encodedQueryString) - { - if (!configurationStore.GetIsEnabled()) - return null; - - var parser = new EncodedQueryStringParser(); - var parameters = parser.Parse(encodedQueryString); - - var issuerParam = parameters.FirstOrDefault(p => p.Name == "iss"); - - var configuredIssuer = configurationStore.GetIssuer(); - - return issuerParam != null && string.Compare(configuredIssuer, issuerParam.Value, StringComparison.InvariantCultureIgnoreCase) == 0; - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Web/OktaStaticContentFolders.cs b/source/Server.Okta/Web/OktaStaticContentFolders.cs deleted file mode 100644 index 390a368..0000000 --- a/source/Server.Okta/Web/OktaStaticContentFolders.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using System.Reflection; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Content; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Web -{ - class OktaStaticContentFolders : IContributesStaticContentFolders - { - public IEnumerable GetStaticContentFolders() - { - var type = typeof(OktaStaticContentFolders); - var assembly = type.GetTypeInfo().Assembly; - return new[] { new StaticContentEmbeddedResourcesFolder("", assembly, type.Namespace + ".Static") }; - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Web/OktaUserAuthenticatedAction.cs b/source/Server.Okta/Web/OktaUserAuthenticatedAction.cs deleted file mode 100644 index 5872ee4..0000000 --- a/source/Server.Okta/Web/OktaUserAuthenticatedAction.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.Okta.Infrastructure; -using Octopus.Server.Extensibility.Authentication.Okta.Tokens; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.Okta.Identities; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Time; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Web -{ - class OktaUserAuthenticatedAction : UserAuthenticatedAction - { - public OktaUserAuthenticatedAction( - ISystemLog log, - IOktaAuthTokenHandler authTokenHandler, - IOktaPrincipalToUserResourceMapper principalToUserResourceMapper, - IOktaConfigurationStore configurationStore, - IAuthCookieCreator authCookieCreator, - IInvalidLoginTracker loginTracker, - ISleep sleep, - IOktaIdentityCreator identityCreator, - IUrlEncoder encoder, - IUserService userService) : - base( - log, - authTokenHandler, - principalToUserResourceMapper, - configurationStore, - authCookieCreator, - loginTracker, - sleep, - identityCreator, - encoder, - userService) - { - } - - protected override string ProviderName => OktaAuthenticationProvider.ProviderName; - } -} \ No newline at end of file diff --git a/source/Server.Okta/Web/OktaUserAuthenticatedPkceAction.cs b/source/Server.Okta/Web/OktaUserAuthenticatedPkceAction.cs deleted file mode 100644 index 813af03..0000000 --- a/source/Server.Okta/Web/OktaUserAuthenticatedPkceAction.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.Okta.Identities; -using Octopus.Server.Extensibility.Authentication.Okta.Tokens; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Infrastructure; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.HostServices.Web; -using Octopus.Server.Extensibility.Mediator; -using Octopus.Time; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Web -{ - class OktaUserAuthenticatedPkceAction - : UserAuthenticatedPkceAction - { - public OktaUserAuthenticatedPkceAction( - ISystemLog log, - IOktaAuthTokenHandler authTokenHandler, - IPrincipalToUserResourceMapper principalToUserResourceMapper, - IOktaConfigurationStore configurationStore, - IAuthCookieCreator authCookieCreator, - IInvalidLoginTracker loginTracker, - ISleep sleep, - IOktaIdentityCreator identityCreator, - IUrlEncoder encoder, - IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, - IMediator mediator, - IUserService service) - : base(log, - authTokenHandler, - principalToUserResourceMapper, - configurationStore, - authCookieCreator, - loginTracker, - sleep, - identityCreator, - encoder, - identityProviderConfigDiscoverer, - mediator, - service) - { - } - - protected override string ProviderName => OktaAuthenticationProvider.ProviderName; - } -} \ No newline at end of file diff --git a/source/Server.Okta/Web/OktaUserAuthenticationAction.cs b/source/Server.Okta/Web/OktaUserAuthenticationAction.cs deleted file mode 100644 index 2d980e9..0000000 --- a/source/Server.Okta/Web/OktaUserAuthenticationAction.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.HostServices; -using Octopus.Server.Extensibility.Authentication.Okta.Configuration; -using Octopus.Server.Extensibility.Authentication.Okta.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Web; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; -using Octopus.Server.Extensibility.Mediator; - -namespace Octopus.Server.Extensibility.Authentication.Okta.Web -{ - class OktaUserAuthenticationAction : UserAuthenticationAction - { - public OktaUserAuthenticationAction( - ISystemLog log, - IOktaConfigurationStore configurationStore, - IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, - IOktaAuthorizationEndpointUrlBuilder urlBuilder, - IApiActionModelBinder modelBinder, - IAuthenticationConfigurationStore authenticationConfigurationStore, - IMediator mediator) : base(log, configurationStore, identityProviderConfigDiscoverer, urlBuilder, modelBinder, authenticationConfigurationStore, mediator) - { - } - } -} \ No newline at end of file diff --git a/source/Server.Okta/Web/Static/areas/users/okta_auth_provider.js b/source/Server.Okta/Web/Static/areas/users/okta_auth_provider.js deleted file mode 100644 index ec063e6..0000000 --- a/source/Server.Okta/Web/Static/areas/users/okta_auth_provider.js +++ /dev/null @@ -1,33 +0,0 @@ -(function (providerName) { - -function oktaAuthProvider(octopusClient, provider, loginState, onError) { - - this.linkHtml = '
Sign in with Okta
'; - - this.signIn = function () { - console.log("Signing in using " + providerName + " provider"); - - var authUri = provider.Links.Authenticate; - var redirectToLink = function (externalProviderLink) { - window.location.href = externalProviderLink.ExternalAuthenticationUrl; - }; - var postData = { - ApiAbsUrl: octopusClient.resolve("~/"), - State: loginState - }; - - octopusClient.post(authUri, postData) - .then(redirectToLink, onError); - }; - - return { - Name: providerName, - LinkHtml: this.linkHtml, - SignIn: this.signIn - }; -} - -console.log("Registering " + providerName + " auth provider"); -window.Octopus.registerExtension(providerName, "auth_provider", oktaAuthProvider); - -})("Okta"); \ No newline at end of file diff --git a/source/Server.Okta/Web/Static/images/okta/aura_solid_blue.png b/source/Server.Okta/Web/Static/images/okta/aura_solid_blue.png deleted file mode 100644 index 3321620..0000000 Binary files a/source/Server.Okta/Web/Static/images/okta/aura_solid_blue.png and /dev/null differ diff --git a/source/Server.Okta/Web/Static/images/okta/logo_blue_medium.png b/source/Server.Okta/Web/Static/images/okta/logo_blue_medium.png deleted file mode 100644 index 9cc9b70..0000000 Binary files a/source/Server.Okta/Web/Static/images/okta/logo_blue_medium.png and /dev/null differ diff --git a/source/Server.Okta/Web/Static/styles/okta.css b/source/Server.Okta/Web/Static/styles/okta.css deleted file mode 100644 index 6c80d28..0000000 --- a/source/Server.Okta/Web/Static/styles/okta.css +++ /dev/null @@ -1,32 +0,0 @@ - -.okta-button { - cursor: pointer; - border-radius: 2px; - box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.24), 0 0 1px 0 rgba(0, 0, 0, 0.12); - display: flex; - align-items: center; - padding-top: 0.8125rem; - padding-bottom: 0.8125rem; -} - -.okta-button:hover { - background-color: #4a4a4a; -} - -.okta-button img { - margin-left: 0.8125rem; - width: 23px; - height: 22px; - background-color: #fafafa; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; -} - -.okta-button div { - font-weight: 600; - display: inline-block; - text-align: left; - margin-left: 0.8125rem; - overflow: hidden; -} \ No newline at end of file diff --git a/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationResource.cs b/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationResource.cs index 647d0b3..d7c14c2 100644 --- a/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationResource.cs +++ b/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationResource.cs @@ -8,22 +8,18 @@ namespace Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Confi public class OpenIDConnectConfigurationResource : ExtensionConfigurationResource { [Description("Follow our documentation to find the Issuer for your identity provider")] - [Writeable] public virtual string? Issuer { get; set; } [DisplayName("Client ID")] [Description("Octopus instances unique authentication id, as provided by your Octopus account")] - [Writeable] public virtual string? ClientId { get; set; } [DisplayName("Client Secret")] [Description("Shared secret for validating the authentication tokens")] - [Writeable] public virtual SensitiveValue? ClientSecret { get; set; } [DisplayName("Allow Auto User Creation")] [Description("Tell Octopus to automatically create a user account when a person signs in for the first time with this identity provider")] - [Writeable] public virtual bool? AllowAutoUserCreation { get; set; } } } \ No newline at end of file diff --git a/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationSettings.cs b/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationSettings.cs index 4cc6c26..941214c 100644 --- a/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationSettings.cs +++ b/source/Server.OpenIDConnect.Common/Configuration/OpenIDConnectConfigurationSettings.cs @@ -1,16 +1,15 @@ -using System.Collections.Generic; -using Octopus.Data.Model; +using System; +using System.Collections.Generic; using Octopus.Server.Extensibility.Extensions.Infrastructure.Configuration; -using Octopus.Server.Extensibility.HostServices.Mapping; namespace Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration { - public abstract class OpenIDConnectConfigurationSettings : ExtensionConfigurationSettings + public abstract class OpenIDConnectConfigurationSettingsProvider : ExtensionConfigurationSettingsProvider where TConfiguration : OpenIDConnectConfiguration, new() where TResource : ExtensionConfigurationResource where TDocumentStore : IOpenIDConnectConfigurationStore { - protected OpenIDConnectConfigurationSettings(TDocumentStore configurationDocumentStore) : base(configurationDocumentStore) + protected OpenIDConnectConfigurationSettingsProvider(TDocumentStore configurationDocumentStore) : base(configurationDocumentStore) { } @@ -29,10 +28,5 @@ public override IEnumerable GetConfigurationValues() yield return new ConfigurationValue($"Octopus.{configurationSettingsName}.NameClaimType", ConfigurationDocumentStore.GetNameClaimType(), isEnabled && ConfigurationDocumentStore.GetNameClaimType() != OpenIDConnectConfiguration.DefaultNameClaimType, "Name Claim Type"); yield return new ConfigurationValue($"Octopus.{configurationSettingsName}.AllowAutoUserCreation", ConfigurationDocumentStore.GetAllowAutoUserCreation(), isEnabled, "Allow auto user creation"); } - - public override void BuildMappings(IResourceMappingsBuilder builder) - { - builder.Map(); - } } -} \ No newline at end of file +} diff --git a/source/Server.OpenIDConnect.Common/Server.OpenIDConnect.Common.csproj b/source/Server.OpenIDConnect.Common/Server.OpenIDConnect.Common.csproj index 8d43ece..895f129 100644 --- a/source/Server.OpenIDConnect.Common/Server.OpenIDConnect.Common.csproj +++ b/source/Server.OpenIDConnect.Common/Server.OpenIDConnect.Common.csproj @@ -14,12 +14,7 @@ - - - - - @@ -30,4 +25,33 @@ + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Data.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Extensibility.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Extensibility.Authentication.dll + + + C:\Program Files\Octopus Deploy\Octopus\Autofac.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.Client.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.MessageContracts.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Server.MessageContracts.Base.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Diagnostics.dll + + + C:\Program Files\Octopus Deploy\Octopus\Octopus.Time.dll + + \ No newline at end of file diff --git a/source/Server.OpenIDConnect.Common/Web/AuthServerResponseHandler.cs b/source/Server.OpenIDConnect.Common/Web/AuthServerResponseHandler.cs index 6bb75a0..9a66098 100644 --- a/source/Server.OpenIDConnect.Common/Web/AuthServerResponseHandler.cs +++ b/source/Server.OpenIDConnect.Common/Web/AuthServerResponseHandler.cs @@ -88,7 +88,7 @@ public InvalidLoginAction CheckIfAuthenticationAttemptIsBanned(string username, public IOctoResponseProvider Success(IOctoRequest request, ISuccessResult successResult, string username, LoginState state) { - loginTracker.RecordSucess(username, request.Host); + loginTracker.RecordSuccess(username, request.Host); UserAuthenticatedValidator.ValidateUserIsActive(successResult.Value.IsActive, username); UserAuthenticatedValidator.ValidateUserIsNotServiceAccount(successResult.Value.IsService, username); diff --git a/source/Tests/Helpers/RS256AlgorithmRsaOnly.cs b/source/Tests/Helpers/RS256AlgorithmRsaOnly.cs deleted file mode 100644 index dce00a2..0000000 --- a/source/Tests/Helpers/RS256AlgorithmRsaOnly.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Security.Cryptography; -using JWT; -using JWT.Algorithms; - -namespace Tests.Helpers -{ - public class RS256AlgorithmRsaOnly : IJwtAlgorithm - { - readonly RSACryptoServiceProvider rsa; - public RS256AlgorithmRsaOnly(RSACryptoServiceProvider rsa) - { - this.rsa = rsa; - } - - public string Name => JwtHashAlgorithm.RS256.ToString(); - public bool IsAsymmetric { get; } - - public byte[] Sign(byte[] key, byte[] bytesToSign) - { - return rsa.SignData(bytesToSign, CryptoConfig.MapNameToOID("SHA256")); - } - } -} diff --git a/source/Tests/OctopusID/OctopusIdConfigDiscovererFixture.cs b/source/Tests/OctopusID/OctopusIdConfigDiscovererFixture.cs deleted file mode 100644 index f410222..0000000 --- a/source/Tests/OctopusID/OctopusIdConfigDiscovererFixture.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Threading.Tasks; -using NUnit.Framework; -using Octopus.Server.Extensibility.Authentication.OctopusID; - -namespace Tests.OctopusID -{ - [TestFixture] - public class OctopusIdConfigDiscovererFixture - { - [Test] - [TestCase("https://someissuer/", "https://someissuer/", "https://someissuer/oauth2/authorize")] - [TestCase("https://someissuer", "https://someissuer/", "https://someissuer/oauth2/authorize")] - public async Task ShouldHandleTrailingSlashes(string inputIssuer, string expectedOutputIssuer, string expectedAuthorizationEndpoint) - { - var sut = new OctopusIdConfigDiscoverer(); - - var result = await sut.GetConfiguration(inputIssuer); - - Assert.AreEqual(expectedOutputIssuer, result.Issuer); - Assert.AreEqual(expectedAuthorizationEndpoint, result.AuthorizationEndpoint); - } - } -} \ No newline at end of file diff --git a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_AzureAD.approved.txt b/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_AzureAD.approved.txt deleted file mode 100644 index d6990c2..0000000 --- a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_AzureAD.approved.txt +++ /dev/null @@ -1 +0,0 @@ -Octopus.Server.Extensibility.Authentication.AzureAD.AzureADExtension \ No newline at end of file diff --git a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_GoogleApps.approved.txt b/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_GoogleApps.approved.txt deleted file mode 100644 index f23db4e..0000000 --- a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_GoogleApps.approved.txt +++ /dev/null @@ -1 +0,0 @@ -Octopus.Server.Extensibility.Authentication.GoogleApps.GoogleAppsExtension \ No newline at end of file diff --git a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_OctopusId.approved.txt b/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_OctopusId.approved.txt deleted file mode 100644 index e9a526c..0000000 --- a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_OctopusId.approved.txt +++ /dev/null @@ -1 +0,0 @@ -Octopus.Server.Extensibility.Authentication.OctopusID.OctopusIDExtension \ No newline at end of file diff --git a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_Okta.approved.txt b/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_Okta.approved.txt deleted file mode 100644 index ad7707e..0000000 --- a/source/Tests/OnlyExposeWhatIsNecessary.ServerExtensionsShouldMinimiseWhatIsExposed_Okta.approved.txt +++ /dev/null @@ -1 +0,0 @@ -Octopus.Server.Extensibility.Authentication.Okta.OktaExtension \ No newline at end of file diff --git a/source/Tests/OnlyExposeWhatIsNecessary.cs b/source/Tests/OnlyExposeWhatIsNecessary.cs deleted file mode 100644 index 313cf11..0000000 --- a/source/Tests/OnlyExposeWhatIsNecessary.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using Assent; -using NUnit.Framework; -using Octopus.Server.Extensibility.Authentication.AzureAD; -using Octopus.Server.Extensibility.Authentication.GoogleApps; -using Octopus.Server.Extensibility.Authentication.OctopusID; -using Octopus.Server.Extensibility.Authentication.Okta; - -namespace Tests -{ - [TestFixture] - public class OnlyExposeWhatIsNecessary - { - [Test] - public void ServerExtensionsShouldMinimiseWhatIsExposed_AzureAD() - { - this.Assent(CheckAssembly(typeof(AzureADExtension).Assembly)); - } - - [Test] - public void ServerExtensionsShouldMinimiseWhatIsExposed_GoogleApps() - { - this.Assent(CheckAssembly(typeof(GoogleAppsExtension).Assembly)); - } - - [Test] - public void ServerExtensionsShouldMinimiseWhatIsExposed_Okta() - { - this.Assent(CheckAssembly(typeof(OktaExtension).Assembly)); - } - - [Test] - public void ServerExtensionsShouldMinimiseWhatIsExposed_OctopusId() - { - this.Assent(CheckAssembly(typeof(OctopusIDExtension).Assembly)); - } - - string CheckAssembly(Assembly assembly) - { - var publicThings = assembly.GetExportedTypes() - .Select(t => t.FullName); - - return string.Join(Environment.NewLine, publicThings); - } - } -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_AzureAD.approved.txt b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_AzureAD.approved.txt deleted file mode 100644 index 0f9fd5c..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_AzureAD.approved.txt +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.KeyDetails[], Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "$values": [ - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.CertificateDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Certificate": "MIIDBTCCAe2gAwIBAgIQXVogj9BAf49IpuOSIvztNDANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTIwMDMxNzAwMDAwMFoXDTI1MDMxNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANfLmdz9yIDskpZzrMXiDeVlCs75ZunrzwzBW5lz7UxdBjHu7Q9iT32otlBp++LOwBcKsVjuQ0GUbulX0FLsfLjEeCe58ZtSn//+6VRFSScg7i+WvDwEUWELR+vMPtCGcXBTpILEnYbSMz0No4+Jpkc1lyMIfDP/KSeqojo74xfW4RKtAgv39uwZ5Yz2hZ/IcWOvaQqMXp1lqhXLFIRWbwjLYYUbmwGwYpQ6++Cml0ucQoMkgYT88HpA/fzXQlLgrHamr3eE/lVp26ZWwfGLAvkdNBabQRSrk8k/c6BmY1mYpUFZo+795PI16mAdp1ioEwH8I5osis+/BR5GhPpwiA8CAwEAAaMhMB8wHQYDVR0OBBYEFF8MDGklOGhGNVJvsHHRCaqtzexcMA0GCSqGSIb3DQEBCwUAA4IBAQCKkegw/mdpCVl1lOpgU4G9RT+1gtcPqZK9kpimuDggSJju6KUQlOCi5/lIH5DCzpjFdmG17TjWVBNve5kowmrhLzovY0Ykk7+6hYTBK8dNNSmd4SK7zY++0aDIuOzHP2Cur+kgFC0gez50tPzotLDtMmp40gknXuzltwJfezNSw3gLgljDsGGcDIXK3qLSYh44qSuRGwulcN2EJUZBI9tIxoODpaWHIN8+z2uZvf8JBYFjA3+n9FRQn51X16CTcjq4QRTbNVpgVuQuyaYnEtx0ZnDvguB3RjGSPIXTRBkLl2x7e8/6uAZ6tchw8rhcOtPsFgJuoJokGjvcUSR/6Eqd", - "Kid": "CtTuhMJmD5M7DLdzD2v2x3QKSRY" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.CertificateDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Certificate": "MIIDBTCCAe2gAwIBAgIQWHw7h/Ysh6hPcXpnrJ0N8DANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTIwMDQyNzAwMDAwMFoXDTI1MDQyNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALhz3sIYOFgt3i1T5BBZY+0Q7WimFlwiORviz1c7DCjriLu6kEG3srSAOj+h0/f4iEbfMzUL7sOD/b2zY4FAqSOr32RrI5N17glaAf2wCIb7gXEIfXjx9shMEua3kfjaxtT7Ks6G52WbooCgqA5rjm/1A8dQ4lcjQmzAZRBu1M00MC3+TT+h2kR8dNu1ESXmbzwFmO84x5UjriqEv3dclL3mgRSIGaj1iwoOOHJOIL4pOOR7DVVk/c2H0++Hb1EkqzEkfkhxU+x8tV421V6RyRzTQF6T6BqFl07nNAcTLAeHKo3yaqH7RRjhuMd9rxM2pAKyz8QCsBr5L7tI06AMr0kCAwEAAaMhMB8wHQYDVR0OBBYEFOI7M+DDFMlP7Ac3aomPnWo1QL1SMA0GCSqGSIb3DQEBCwUAA4IBAQBv+8rBiDY8sZDBoUDYwFQM74QjqCmgNQfv5B0Vjwg20HinERjQeH24uAWzyhWN9++FmeY4zcRXDY5UNmB0nJz7UGlprA9s7voQ0Lkyiud0DO072RPBg38LmmrqoBsLb3MB9MZ2CGBaHftUHfpdTvrgmXSP0IJn7mCUq27g+hFk7n/MLbN1k8JswEODIgdMRvGqN+mnrPKkviWmcVAZccsWfcmS1pKwXqICTKzd6WmVdz+cL7ZSd9I2X0pY4oRwauoE2bS95vrXljCYgLArI3XB2QcnglDDBRYu3Z3aIJb26PTIyhkVKT7xaXhXl4OgrbmQon9/O61G2dzpjzzBPqNP", - "Kid": "SsZsBNhZcF3Q9S4trpQBTByNRRI" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.CertificateDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Certificate": "MIIC8TCCAdmgAwIBAgIQfEWlTVc1uINEc9RBi6qHMjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhsb2dpbi5taWNyb3NvZnRvbmxpbmUudXMwHhcNMTgxMDE0MDAwMDAwWhcNMjAxMDE0MDAwMDAwWjAjMSEwHwYDVQQDExhsb2dpbi5taWNyb3NvZnRvbmxpbmUudXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEdJxkw+jwWJ+gNyuCdxZDuYYm2IqGuyGjT64U9eD452dEpi51MPv4GrUwONypZF/ch8NWMUmLFBLrUzvCb3AAsOP76Uu4kn2MNQBZMDfFa9AtuIEz6CpTSyPiZzaVabqc9+qXJh5a1BxILSxiQuVrI2BfiegoNpeK+FU6ntvAZervsxHN4vj72qtFgqO7Md9kvuQ0EKyo7Xzk/Q0jYm2bD4SypiysJoex81EZGtO9QdSreFZrzn2Qr/m413tN5jZkTApUPx7MKZJ9Hn1nPLFO24+mQJIdL061S9LeapNiK3vepy+muOXdHyGmNctvyh+1+laveEVF2nGvC6hAQ7hBAgMBAAGjITAfMB0GA1UdDgQWBBQ5TKadw06O0cvXrQbXW0Nb3M3h/DANBgkqhkiG9w0BAQsFAAOCAQEAI48JaFtwOFcYS/3pfS5+7cINrafXAKTL+/+he4q+RMx4TCu/L1dl9zS5W1BeJNO2GUznfI+b5KndrxdlB6qJIDf6TRHh6EqfA18oJP5NOiKhU4pgkF2UMUw4kjxaZ5fQrSoD9omjfHAFNjradnHA7GOAoF4iotvXDWDBWx9K4XNZHWvD11Td66zTg5IaEQDIZ+f8WS6nn/98nAVMDtR9zW7Te5h9kGJGfe6WiHVaGRPpBvqC4iypGHjbRwANwofZvmp5wP08hY1CsnKY5tfP+E2k/iAQgKKa6QoxXToYvP7rsSkglak8N5g/+FJGnq4wP6cOzgZpjdPMwaVt5432GA==", - "Kid": "M6pX7RHoraLsprfJeRCjSxuURhc" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.CertificateDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Certificate": "MIIDYDCCAkigAwIBAgIJAIB4jVVJ3BeuMA0GCSqGSIb3DQEBCwUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTAeFw0xNjA0MDUxNDQzMzVaFw0yMTA0MDQxNDQzMzVaMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN7CnCUg+HB8E2OY2JuZTRM6pN8DjdQmgETuRKFiELebvl/mZ1utQokWaVqX4SsEWFNed7XeUfKfgCQ1k/jXBCdDB1NyoriBD5m4CaUu6pMlEbh0bnAzNpTuC+F3yJb4s0K5ciZyXHdPbixK2RDvT3Lyogx6KIrNgeHxo+wrAHuVGYBMSbwAg5bEEpLtiVMg5mVGT9v7v4ArqjSTOaNIVuxSkSNzBaGArKkhJh557pridoxdERw0VkKaHYZQEerii6Ilh6hzt2hu7HMWDI+XDM5KXtSqvw5ucsh5DAkifyWkYcMphX1f0lpKnd5/llWU9AAyxKtETYvbameN56FJzv8CAwEAAaOBijCBhzAdBgNVHQ4EFgQU9IdLLpbC2S8Wn1MCXsdtFac9SRYwWQYDVR0jBFIwUIAU9IdLLpbC2S8Wn1MCXsdtFac9SRahLaQrMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleYIJAIB4jVVJ3BeuMAsGA1UdDwQEAwIBxjANBgkqhkiG9w0BAQsFAAOCAQEAXk0sQAib0PGqvwELTlflQEKS++vqpWYPW/2gCVCn5shbyP1J7z1nT8kE/ZDVdl3LvGgTMfdDHaRF5ie5NjkTHmVOKbbHaWpTwUFbYAFBJGnx+s/9XSdmNmW9GlUjdpd6lCZxsI6888r0ptBgKINRRrkwMlq3jD1U0kv4JlsIhafUIOqGi4+hIDXBlY0F/HJPfUU75N885/r4CCxKhmfh3PBM35XOch/NGC67fLjqLN+TIWLoxnvil9m3jRjqOA9u50JUeDGZABIYIMcAdLpI2lcfru4wXcYXuQul22nAR7yOyGKNOKULoOTE4t4AeGRqCogXSxZgaTgKSBhvhE+MGg==", - "Kid": "1LTMzakihiRla_8z2BEJVXeWMqo" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.CertificateDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Certificate": "MIIDYDCCAkigAwIBAgIJAJzCyTLC+DjJMA0GCSqGSIb3DQEBCwUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTAeFw0xNjA3MTMyMDMyMTFaFw0yMTA3MTIyMDMyMTFaMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANqVmrWn3m95gdAO9/mflEcK7m8A5XVr4r0btfRjQutTATm932eCOJcoVITbku2iUTySBQes5fhxcdZx6RoO+AR3tM/bJDgx2GRAAndoigSHreeQ3XbiHtQl7GfZHshJjWhr910uDlv+yAzNI+cEfTh7oFIn5B9z0CHBb02Gpx5l6I05oIyDlqM+8tKJKcjffhW2Uc3X8fno/p42o+YEfK+vZrsDucJU2yBttFeNEes2IfkDgzFKWssu4wxhRsOb4xR/QmtLS2XDUKv/yShP5qftHzgzgEKGzqwVKAEhZMgnfeQVVuyia53b1u6H0Vmgk7mWTsuUp1OGrG4zK4MRWRcCAwEAAaOBijCBhzAdBgNVHQ4EFgQU11z579/IePwuc4WBdN4L0ljG4CUwWQYDVR0jBFIwUIAU11z579/IePwuc4WBdN4L0ljG4CWhLaQrMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleYIJAJzCyTLC+DjJMAsGA1UdDwQEAwIBxjANBgkqhkiG9w0BAQsFAAOCAQEAiASLEpQseGNahE+9f9PQgmX3VgjJerNjXr1zXWXDJfFE31DxgsxddjcIgoBL9lwegOHHvwpzK1ecgH45xcJ0Z/40OgY8NITqXbQRfdgLrEGJCoyOQEbjb5PW5k2aOdn7LBxvDsH6Y8ax26v+EFMPh3G+xheh6bfoIRSK1b+44PfoDZoJ9NfJibOZ4Cq+wt/yOvpMYQDB/9CNo18wmA3RCLYjf2nAc7RO0PDYHSIq5QDWV+1awmXDKgIdRpYPpRtn9KFXQkpCeEc/lDTG+o6n7nC40wyjioyR6QmHGvNkMR4VfSoTKCTnFATyDpI1bqU2K7KNjUEsCYfwybFB8d6mjQ==", - "Kid": "xP_zn6I1YkXcUUmlBoPuXTGsaxk" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_AzureAD.jwks.json b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_AzureAD.jwks.json deleted file mode 100644 index 1b7459b..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_AzureAD.jwks.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "keys": [ - { - "kty": "RSA", - "use": "sig", - "kid": "CtTuhMJmD5M7DLdzD2v2x3QKSRY", - "x5t": "CtTuhMJmD5M7DLdzD2v2x3QKSRY", - "n": "18uZ3P3IgOySlnOsxeIN5WUKzvlm6evPDMFbmXPtTF0GMe7tD2JPfai2UGn74s7AFwqxWO5DQZRu6VfQUux8uMR4J7nxm1Kf__7pVEVJJyDuL5a8PARRYQtH68w-0IZxcFOkgsSdhtIzPQ2jj4mmRzWXIwh8M_8pJ6qiOjvjF9bhEq0CC_f27BnljPaFn8hxY69pCoxenWWqFcsUhFZvCMthhRubAbBilDr74KaXS5xCgySBhPzwekD9_NdCUuCsdqavd4T-VWnbplbB8YsC-R00FptBFKuTyT9zoGZjWZilQVmj7v3k8jXqYB2nWKgTAfwjmiyKz78FHkaE-nCIDw", - "e": "AQAB", - "x5c": [ - "MIIDBTCCAe2gAwIBAgIQXVogj9BAf49IpuOSIvztNDANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTIwMDMxNzAwMDAwMFoXDTI1MDMxNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANfLmdz9yIDskpZzrMXiDeVlCs75ZunrzwzBW5lz7UxdBjHu7Q9iT32otlBp++LOwBcKsVjuQ0GUbulX0FLsfLjEeCe58ZtSn//+6VRFSScg7i+WvDwEUWELR+vMPtCGcXBTpILEnYbSMz0No4+Jpkc1lyMIfDP/KSeqojo74xfW4RKtAgv39uwZ5Yz2hZ/IcWOvaQqMXp1lqhXLFIRWbwjLYYUbmwGwYpQ6++Cml0ucQoMkgYT88HpA/fzXQlLgrHamr3eE/lVp26ZWwfGLAvkdNBabQRSrk8k/c6BmY1mYpUFZo+795PI16mAdp1ioEwH8I5osis+/BR5GhPpwiA8CAwEAAaMhMB8wHQYDVR0OBBYEFF8MDGklOGhGNVJvsHHRCaqtzexcMA0GCSqGSIb3DQEBCwUAA4IBAQCKkegw/mdpCVl1lOpgU4G9RT+1gtcPqZK9kpimuDggSJju6KUQlOCi5/lIH5DCzpjFdmG17TjWVBNve5kowmrhLzovY0Ykk7+6hYTBK8dNNSmd4SK7zY++0aDIuOzHP2Cur+kgFC0gez50tPzotLDtMmp40gknXuzltwJfezNSw3gLgljDsGGcDIXK3qLSYh44qSuRGwulcN2EJUZBI9tIxoODpaWHIN8+z2uZvf8JBYFjA3+n9FRQn51X16CTcjq4QRTbNVpgVuQuyaYnEtx0ZnDvguB3RjGSPIXTRBkLl2x7e8/6uAZ6tchw8rhcOtPsFgJuoJokGjvcUSR/6Eqd" - ], - "issuer": "https://login.microsoftonline.com/{tenantid}/v2.0" - }, - { - "kty": "RSA", - "use": "sig", - "kid": "SsZsBNhZcF3Q9S4trpQBTByNRRI", - "x5t": "SsZsBNhZcF3Q9S4trpQBTByNRRI", - "n": "uHPewhg4WC3eLVPkEFlj7RDtaKYWXCI5G-LPVzsMKOuIu7qQQbeytIA6P6HT9_iIRt8zNQvuw4P9vbNjgUCpI6vfZGsjk3XuCVoB_bAIhvuBcQh9ePH2yEwS5reR-NrG1PsqzobnZZuigKCoDmuOb_UDx1DiVyNCbMBlEG7UzTQwLf5NP6HaRHx027URJeZvPAWY7zjHlSOuKoS_d1yUveaBFIgZqPWLCg44ck4gvik45HsNVWT9zYfT74dvUSSrMSR-SHFT7Hy1XjbVXpHJHNNAXpPoGoWXTuc0BxMsB4cqjfJqoftFGOG4x32vEzakArLPxAKwGvkvu0jToAyvSQ", - "e": "AQAB", - "x5c": [ - "MIIDBTCCAe2gAwIBAgIQWHw7h/Ysh6hPcXpnrJ0N8DANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTIwMDQyNzAwMDAwMFoXDTI1MDQyNzAwMDAwMFowLTErMCkGA1UEAxMiYWNjb3VudHMuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALhz3sIYOFgt3i1T5BBZY+0Q7WimFlwiORviz1c7DCjriLu6kEG3srSAOj+h0/f4iEbfMzUL7sOD/b2zY4FAqSOr32RrI5N17glaAf2wCIb7gXEIfXjx9shMEua3kfjaxtT7Ks6G52WbooCgqA5rjm/1A8dQ4lcjQmzAZRBu1M00MC3+TT+h2kR8dNu1ESXmbzwFmO84x5UjriqEv3dclL3mgRSIGaj1iwoOOHJOIL4pOOR7DVVk/c2H0++Hb1EkqzEkfkhxU+x8tV421V6RyRzTQF6T6BqFl07nNAcTLAeHKo3yaqH7RRjhuMd9rxM2pAKyz8QCsBr5L7tI06AMr0kCAwEAAaMhMB8wHQYDVR0OBBYEFOI7M+DDFMlP7Ac3aomPnWo1QL1SMA0GCSqGSIb3DQEBCwUAA4IBAQBv+8rBiDY8sZDBoUDYwFQM74QjqCmgNQfv5B0Vjwg20HinERjQeH24uAWzyhWN9++FmeY4zcRXDY5UNmB0nJz7UGlprA9s7voQ0Lkyiud0DO072RPBg38LmmrqoBsLb3MB9MZ2CGBaHftUHfpdTvrgmXSP0IJn7mCUq27g+hFk7n/MLbN1k8JswEODIgdMRvGqN+mnrPKkviWmcVAZccsWfcmS1pKwXqICTKzd6WmVdz+cL7ZSd9I2X0pY4oRwauoE2bS95vrXljCYgLArI3XB2QcnglDDBRYu3Z3aIJb26PTIyhkVKT7xaXhXl4OgrbmQon9/O61G2dzpjzzBPqNP" - ], - "issuer": "https://login.microsoftonline.com/{tenantid}/v2.0" - }, - { - "kty": "RSA", - "use": "sig", - "kid": "M6pX7RHoraLsprfJeRCjSxuURhc", - "x5t": "M6pX7RHoraLsprfJeRCjSxuURhc", - "n": "xHScZMPo8FifoDcrgncWQ7mGJtiKhrsho0-uFPXg-OdnRKYudTD7-Bq1MDjcqWRf3IfDVjFJixQS61M7wm9wALDj--lLuJJ9jDUAWTA3xWvQLbiBM-gqU0sj4mc2lWm6nPfqlyYeWtQcSC0sYkLlayNgX4noKDaXivhVOp7bwGXq77MRzeL4-9qrRYKjuzHfZL7kNBCsqO185P0NI2Jtmw-EsqYsrCaHsfNRGRrTvUHUq3hWa859kK_5uNd7TeY2ZEwKVD8ezCmSfR59ZzyxTtuPpkCSHS9OtUvS3mqTYit73qcvprjl3R8hpjXLb8oftfpWr3hFRdpxrwuoQEO4QQ", - "e": "AQAB", - "x5c": [ - "MIIC8TCCAdmgAwIBAgIQfEWlTVc1uINEc9RBi6qHMjANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhsb2dpbi5taWNyb3NvZnRvbmxpbmUudXMwHhcNMTgxMDE0MDAwMDAwWhcNMjAxMDE0MDAwMDAwWjAjMSEwHwYDVQQDExhsb2dpbi5taWNyb3NvZnRvbmxpbmUudXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEdJxkw+jwWJ+gNyuCdxZDuYYm2IqGuyGjT64U9eD452dEpi51MPv4GrUwONypZF/ch8NWMUmLFBLrUzvCb3AAsOP76Uu4kn2MNQBZMDfFa9AtuIEz6CpTSyPiZzaVabqc9+qXJh5a1BxILSxiQuVrI2BfiegoNpeK+FU6ntvAZervsxHN4vj72qtFgqO7Md9kvuQ0EKyo7Xzk/Q0jYm2bD4SypiysJoex81EZGtO9QdSreFZrzn2Qr/m413tN5jZkTApUPx7MKZJ9Hn1nPLFO24+mQJIdL061S9LeapNiK3vepy+muOXdHyGmNctvyh+1+laveEVF2nGvC6hAQ7hBAgMBAAGjITAfMB0GA1UdDgQWBBQ5TKadw06O0cvXrQbXW0Nb3M3h/DANBgkqhkiG9w0BAQsFAAOCAQEAI48JaFtwOFcYS/3pfS5+7cINrafXAKTL+/+he4q+RMx4TCu/L1dl9zS5W1BeJNO2GUznfI+b5KndrxdlB6qJIDf6TRHh6EqfA18oJP5NOiKhU4pgkF2UMUw4kjxaZ5fQrSoD9omjfHAFNjradnHA7GOAoF4iotvXDWDBWx9K4XNZHWvD11Td66zTg5IaEQDIZ+f8WS6nn/98nAVMDtR9zW7Te5h9kGJGfe6WiHVaGRPpBvqC4iypGHjbRwANwofZvmp5wP08hY1CsnKY5tfP+E2k/iAQgKKa6QoxXToYvP7rsSkglak8N5g/+FJGnq4wP6cOzgZpjdPMwaVt5432GA==" - ], - "issuer": "https://login.microsoftonline.com/{tenantid}/v2.0" - }, - { - "kty": "RSA", - "use": "sig", - "kid": "1LTMzakihiRla_8z2BEJVXeWMqo", - "x5t": "1LTMzakihiRla_8z2BEJVXeWMqo", - "n": "3sKcJSD4cHwTY5jYm5lNEzqk3wON1CaARO5EoWIQt5u-X-ZnW61CiRZpWpfhKwRYU153td5R8p-AJDWT-NcEJ0MHU3KiuIEPmbgJpS7qkyURuHRucDM2lO4L4XfIlvizQrlyJnJcd09uLErZEO9PcvKiDHoois2B4fGj7CsAe5UZgExJvACDlsQSku2JUyDmZUZP2_u_gCuqNJM5o0hW7FKRI3MFoYCsqSEmHnnumuJ2jF0RHDRWQpodhlAR6uKLoiWHqHO3aG7scxYMj5cMzkpe1Kq_Dm5yyHkMCSJ_JaRhwymFfV_SWkqd3n-WVZT0ADLEq0RNi9tqZ43noUnO_w", - "e": "AQAB", - "x5c": [ - "MIIDYDCCAkigAwIBAgIJAIB4jVVJ3BeuMA0GCSqGSIb3DQEBCwUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTAeFw0xNjA0MDUxNDQzMzVaFw0yMTA0MDQxNDQzMzVaMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN7CnCUg+HB8E2OY2JuZTRM6pN8DjdQmgETuRKFiELebvl/mZ1utQokWaVqX4SsEWFNed7XeUfKfgCQ1k/jXBCdDB1NyoriBD5m4CaUu6pMlEbh0bnAzNpTuC+F3yJb4s0K5ciZyXHdPbixK2RDvT3Lyogx6KIrNgeHxo+wrAHuVGYBMSbwAg5bEEpLtiVMg5mVGT9v7v4ArqjSTOaNIVuxSkSNzBaGArKkhJh557pridoxdERw0VkKaHYZQEerii6Ilh6hzt2hu7HMWDI+XDM5KXtSqvw5ucsh5DAkifyWkYcMphX1f0lpKnd5/llWU9AAyxKtETYvbameN56FJzv8CAwEAAaOBijCBhzAdBgNVHQ4EFgQU9IdLLpbC2S8Wn1MCXsdtFac9SRYwWQYDVR0jBFIwUIAU9IdLLpbC2S8Wn1MCXsdtFac9SRahLaQrMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleYIJAIB4jVVJ3BeuMAsGA1UdDwQEAwIBxjANBgkqhkiG9w0BAQsFAAOCAQEAXk0sQAib0PGqvwELTlflQEKS++vqpWYPW/2gCVCn5shbyP1J7z1nT8kE/ZDVdl3LvGgTMfdDHaRF5ie5NjkTHmVOKbbHaWpTwUFbYAFBJGnx+s/9XSdmNmW9GlUjdpd6lCZxsI6888r0ptBgKINRRrkwMlq3jD1U0kv4JlsIhafUIOqGi4+hIDXBlY0F/HJPfUU75N885/r4CCxKhmfh3PBM35XOch/NGC67fLjqLN+TIWLoxnvil9m3jRjqOA9u50JUeDGZABIYIMcAdLpI2lcfru4wXcYXuQul22nAR7yOyGKNOKULoOTE4t4AeGRqCogXSxZgaTgKSBhvhE+MGg==" - ], - "issuer": "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0" - }, - { - "kty": "RSA", - "use": "sig", - "kid": "xP_zn6I1YkXcUUmlBoPuXTGsaxk", - "x5t": "xP_zn6I1YkXcUUmlBoPuXTGsaxk", - "n": "2pWatafeb3mB0A73-Z-URwrubwDldWvivRu19GNC61MBOb3fZ4I4lyhUhNuS7aJRPJIFB6zl-HFx1nHpGg74BHe0z9skODHYZEACd2iKBIet55DdduIe1CXsZ9keyEmNaGv3XS4OW_7IDM0j5wR9OHugUifkH3PQIcFvTYanHmXojTmgjIOWoz7y0okpyN9-FbZRzdfx-ej-njaj5gR8r69muwO5wlTbIG20V40R6zYh-QODMUpayy7jDGFGw5vjFH9Ca0tLZcNQq__JKE_mp-0fODOAQobOrBUoASFkyCd95BVW7KJrndvW7ofRWaCTuZZOy5SnU4asbjMrgxFZFw", - "e": "AQAB", - "x5c": [ - "MIIDYDCCAkigAwIBAgIJAJzCyTLC+DjJMA0GCSqGSIb3DQEBCwUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTAeFw0xNjA3MTMyMDMyMTFaFw0yMTA3MTIyMDMyMTFaMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANqVmrWn3m95gdAO9/mflEcK7m8A5XVr4r0btfRjQutTATm932eCOJcoVITbku2iUTySBQes5fhxcdZx6RoO+AR3tM/bJDgx2GRAAndoigSHreeQ3XbiHtQl7GfZHshJjWhr910uDlv+yAzNI+cEfTh7oFIn5B9z0CHBb02Gpx5l6I05oIyDlqM+8tKJKcjffhW2Uc3X8fno/p42o+YEfK+vZrsDucJU2yBttFeNEes2IfkDgzFKWssu4wxhRsOb4xR/QmtLS2XDUKv/yShP5qftHzgzgEKGzqwVKAEhZMgnfeQVVuyia53b1u6H0Vmgk7mWTsuUp1OGrG4zK4MRWRcCAwEAAaOBijCBhzAdBgNVHQ4EFgQU11z579/IePwuc4WBdN4L0ljG4CUwWQYDVR0jBFIwUIAU11z579/IePwuc4WBdN4L0ljG4CWhLaQrMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVibGljIEtleYIJAJzCyTLC+DjJMAsGA1UdDwQEAwIBxjANBgkqhkiG9w0BAQsFAAOCAQEAiASLEpQseGNahE+9f9PQgmX3VgjJerNjXr1zXWXDJfFE31DxgsxddjcIgoBL9lwegOHHvwpzK1ecgH45xcJ0Z/40OgY8NITqXbQRfdgLrEGJCoyOQEbjb5PW5k2aOdn7LBxvDsH6Y8ax26v+EFMPh3G+xheh6bfoIRSK1b+44PfoDZoJ9NfJibOZ4Cq+wt/yOvpMYQDB/9CNo18wmA3RCLYjf2nAc7RO0PDYHSIq5QDWV+1awmXDKgIdRpYPpRtn9KFXQkpCeEc/lDTG+o6n7nC40wyjioyR6QmHGvNkMR4VfSoTKCTnFATyDpI1bqU2K7KNjUEsCYfwybFB8d6mjQ==" - ], - "issuer": "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Google.approved.txt b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Google.approved.txt deleted file mode 100644 index 9801f95..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Google.approved.txt +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.KeyDetails[], Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "$values": [ - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.RsaDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Modulus": "zK8PHf_6V3G5rU-viUOL1HvAYn7q--dxMoUkt7x1rSWX6fimla-lpoYAKhFTLUELkRKy_6UDzfybz0P9eItqS2UxVWYpKYmKTQ08HgUBUde4GtO_B0SkSk8iLtGh653UBBjgXmfzdfQEz_DsaWn7BMtuAhY9hpMtJye8LQlwaS8ibQrsC0j0GZM5KXRITHwfx06_T1qqC_MOZRA6iJs-J2HNlgeyFuoQVBTY6pRqGXa-qaVsSG3iU-vqNIciFquIq-xydwxLqZNksRRer5VAsSHf0eD3g2DX-cf6paSy1aM40svO9EfSvG_07MuHafEE44RFvSZZ4ubEN9U7ALSjdw", - "Exponent": "AQAB", - "Kid": "fb8ca5b7d8d9a5c6c6788071e866c6c40f3fc1f9" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.RsaDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Modulus": "wl6TaY_3dsuLczYH_hioeQ5JjcLKLGYb--WImN9_IKMkOj49dgs25wkjsdI9XGJYhhPJLlvfjIfXH49ZGA_XKLx7fggNaBRZcj1y-I3_77tVa9N7An5JLq3HT9XVt0PNTq0mtX009z1Hva4IWZ5IhENx2rWlZOfFAXiMUqhnDc8VY3lG7vr8_VG3cw3XRKvlZQKbb6p2YIMFsUwaDGL2tVF4SkxpxIazUYfOY5lijyVugNTslOBhlEMq_43MZlkznSrbFx8ToQ2bQX4Shj-r9pLyofbo6A7K9mgWnQXGY5rQVLPYYRzUg0ThWDzwHdgxYC5MNxKyQH4RC2LPv3U0LQ", - "Exponent": "AQAB", - "Kid": "492710a7fcdb153960ce01f760520a32c8455dff" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Google.jwks.json b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Google.jwks.json deleted file mode 100644 index bdd1941..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Google.jwks.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "keys": [ - { - "kty": "RSA", - "kid": "fb8ca5b7d8d9a5c6c6788071e866c6c40f3fc1f9", - "e": "AQAB", - "alg": "RS256", - "use": "sig", - "n": "zK8PHf_6V3G5rU-viUOL1HvAYn7q--dxMoUkt7x1rSWX6fimla-lpoYAKhFTLUELkRKy_6UDzfybz0P9eItqS2UxVWYpKYmKTQ08HgUBUde4GtO_B0SkSk8iLtGh653UBBjgXmfzdfQEz_DsaWn7BMtuAhY9hpMtJye8LQlwaS8ibQrsC0j0GZM5KXRITHwfx06_T1qqC_MOZRA6iJs-J2HNlgeyFuoQVBTY6pRqGXa-qaVsSG3iU-vqNIciFquIq-xydwxLqZNksRRer5VAsSHf0eD3g2DX-cf6paSy1aM40svO9EfSvG_07MuHafEE44RFvSZZ4ubEN9U7ALSjdw" - }, - { - "kty": "RSA", - "kid": "492710a7fcdb153960ce01f760520a32c8455dff", - "e": "AQAB", - "alg": "RS256", - "use": "sig", - "n": "wl6TaY_3dsuLczYH_hioeQ5JjcLKLGYb--WImN9_IKMkOj49dgs25wkjsdI9XGJYhhPJLlvfjIfXH49ZGA_XKLx7fggNaBRZcj1y-I3_77tVa9N7An5JLq3HT9XVt0PNTq0mtX009z1Hva4IWZ5IhENx2rWlZOfFAXiMUqhnDc8VY3lG7vr8_VG3cw3XRKvlZQKbb6p2YIMFsUwaDGL2tVF4SkxpxIazUYfOY5lijyVugNTslOBhlEMq_43MZlkznSrbFx8ToQ2bQX4Shj-r9pLyofbo6A7K9mgWnQXGY5rQVLPYYRzUg0ThWDzwHdgxYC5MNxKyQH4RC2LPv3U0LQ" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Okta.approved.txt b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Okta.approved.txt deleted file mode 100644 index 789a8f2..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Okta.approved.txt +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.KeyDetails[], Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "$values": [ - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.RsaDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Modulus": "lfqMF8GPSred3eTzn4QENsU7CKzr2dJjyHm2kS7ejHaQmpjGJM4Ct5anQ70b0gmC2I2yaptz79qkxrOxj-SXDiA9gwX67nahjREXg5pXEW5B9Io9Sg0FLYLOOf43srYz6Fio2XmAjnuI6q0PNoOcw5wil2evJY5q1uipMFXi6CJV-ZLg4SNQr6DWX5adglNCxFMG1vmmBkJohrwBf4F8djWc4dufdX-FCXXwNboVwh-oNFqPhKRK1q_dcH_bXZnJ_It2MvW9Qf4mqfD3Pdfj3mT3P_yYymsfD6ntgt8kSwuGACFdG5H86sQfgwAo2H1XIxWtdweZR5zJIS8kuEluhQ", - "Exponent": "AQAB", - "Kid": "FnD5-YVK_9heZSb4upa8tCwEDfAfJnHnIradaMsJQA8" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Okta.jwks.json b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Okta.jwks.json deleted file mode 100644 index 5c97e67..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Okta.jwks.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "keys": [ - { - "kty": "RSA", - "alg": "RS256", - "kid": "FnD5-YVK_9heZSb4upa8tCwEDfAfJnHnIradaMsJQA8", - "use": "sig", - "e": "AQAB", - "n": "lfqMF8GPSred3eTzn4QENsU7CKzr2dJjyHm2kS7ejHaQmpjGJM4Ct5anQ70b0gmC2I2yaptz79qkxrOxj-SXDiA9gwX67nahjREXg5pXEW5B9Io9Sg0FLYLOOf43srYz6Fio2XmAjnuI6q0PNoOcw5wil2evJY5q1uipMFXi6CJV-ZLg4SNQr6DWX5adglNCxFMG1vmmBkJohrwBf4F8djWc4dufdX-FCXXwNboVwh-oNFqPhKRK1q_dcH_bXZnJ_It2MvW9Qf4mqfD3Pdfj3mT3P_yYymsfD6ntgt8kSwuGACFdG5H86sQfgwAo2H1XIxWtdweZR5zJIS8kuEluhQ" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Ping.approved.txt b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Ping.approved.txt deleted file mode 100644 index 72fa43d..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Ping.approved.txt +++ /dev/null @@ -1,29 +0,0 @@ -{ - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.KeyDetails[], Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "$values": [ - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.RsaDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Modulus": "kZ3TEh6j93bWSR1Fpkgam2SiBIohC4_KCeUYd-_uUM6jDQZic5pOEvHWxL-sc3Mg4Zx4c5Qn_Lw5BVPtyY2BSDLiQwTCD8RpGX7MgQllgd9TM64PblyE6HPMgCOqIOxDHq-QJL1IlA80OM8Hlf7Ze-YQPeKxfTBpfuw4KcNxblo3G5pNq8tFDjoBqE4E3mOv8Ay1b0KnZZTfxQ-FqXLEynysRFNGZ-cWyvRRCD_1S8f5BppBJq6lnlSwLg5MvFwLd5vCFx_WShYv-pTy2kUascEVnLdTo0WAZcVpUkFaRL5G_TrQe-pe892hF3EYl2I9uVUXjQTlmlB-x2o5MZGFcw", - "Exponent": "AQAB", - "Kid": "da7wFyqmnDaQ1WKEhXZ-A6rYqSA" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.RsaDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Modulus": "qxCiLX5H67U4d30Mt3DATMpdyIAxsnTfRPivB0RXA93udke6i22BTHHA16ZkBvPeiQOOFirhTmz5SOVib4BoKKPQ4druxOXK8nw9Rb_sppMkWweuE7MqU7vjOAaoHHfxV4Q259H-uU48t2cvLMgYIu7Bjx4j0Trgx_SxQt5MKbIH0Fm0fzgwAzL3-MZ45QpM7ZQNMtrmh33HucM_fQ7kL3eu9M2l50ArnazqwFwwr8sIRexwG5bK_tqDpMiaU1Wd2DSbG1K3Bz2lM7o8MUipJuM1JrvFZmZ28siJsOv5V6qXxsrtEXv6_FnnGsLt0wbG5fafg1jxBGhbjpM1JHNITw", - "Exponent": "AQAB", - "Kid": "P4QmQdazhOEZ6ESp3Ox50SdbHaU" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.RsaDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Modulus": "ie0wE0bn1pQ0xEeM5-2_I3aMt_eDI7oyCClCyU1faMeQkzDTAp6FLnqSD99Ryb-dheGObooPWm1JxxKU8gvoNl2k7OVNYcyZUsaBmvCLn1RWsBOpULojgjwdAH9WeKEXzNJVBwnGy_MZaRxC10-DVe36tIzhAzqo_I5WC-LKIb5l1MTbXjMVGltuQyVd-TrLhKunsXXBC7pwIEw2hh7XT9eeg8Hm4vYj1Urj44JsbNxKQ1JHEt4qG3RKAEJAipi9uSE8L8cnxTEHkqC9g1uomghazyNc17XMofTTzy7d0ZavRpIfnUID0YAAQihYBJCJP2pQn-lAfRQgjnBdCDZjRQ", - "Exponent": "AQAB", - "Kid": "gvqsO-tegUGtLWrVeFtRDjwCzhE" - }, - { - "$type": "Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates.RsaDetails, Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common", - "Modulus": "r4kVtn4i4caKzmn20VaPVyh6kBst2nObPejmkHRysyNtt06ttC0YwJpyGqeOFIl-pvDzXWfxFIOHpm25w1rotV47Sh6VT6zsZBUXUY3Go0_3pCacZO6HVNytCZvxHzA8Wtxzvc8Jri9dQzL0SYs_FKGzgyPNebprUepSVjtM-maS9suqokTcZ_7dizR5IhslDVLPPmmdGHqdwUIP4q75VguVPpDAQrSWLj_mvvqFSuA05XwJoGanWE612oCTBj2hMftyVNwi86PVXKZgPI5TM3cMpTrckXSgfGb-3Ls0cde5VlUrQI8v0Fo-ygAuTF9orSj6E5t3mJCZ6AaxuKcz0w", - "Exponent": "AQAB", - "Kid": "j4hQX_PyMw_SU1EJIhwEIt2jVSM" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Ping.jwks.json b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Ping.jwks.json deleted file mode 100644 index 1e9a656..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.ShouldParseSupportedJwks_Ping.jwks.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "keys": [ - { - "kty": "EC", - "kid": "ED3qX-C65lQTXC1eXDGj0gY5QV8", - "use": "sig", - "x": "yqp2gAIKascSxT7gJBvlUMXfWCASvvEhBQbCNoL2LFQoOucOPSVdjIH7yh6AmbvV", - "y": "Oy3SjdyoFPFKlKpN8LXEiOpgN2o8p9u_xvFkiEzqkJGq7amL7KU3GVo86I1kR74q", - "crv": "P-384" - }, - { - "kty": "EC", - "kid": "ceGDhhMNKN1PknS3ZkTKu2xZqlU", - "use": "sig", - "x": "AdqiwLuYHwURX-uONBisLIuVuDu1pnC31ET5PhyGy23TkVaG6ToFWbkDwy5q91dK50sFtzi5kYKWxfEPpbilI8iM", - "y": "AE1ZL1_aczmBj20k6wdaAVwkpnlyz5w1qeNQKR_3CJ-3lC58Xz2K8PH_nSjojyrS7cN36-V0lhoptGyqJI3pOW7e", - "crv": "P-521" - }, - { - "kty": "RSA", - "kid": "da7wFyqmnDaQ1WKEhXZ-A6rYqSA", - "use": "sig", - "n": "kZ3TEh6j93bWSR1Fpkgam2SiBIohC4_KCeUYd-_uUM6jDQZic5pOEvHWxL-sc3Mg4Zx4c5Qn_Lw5BVPtyY2BSDLiQwTCD8RpGX7MgQllgd9TM64PblyE6HPMgCOqIOxDHq-QJL1IlA80OM8Hlf7Ze-YQPeKxfTBpfuw4KcNxblo3G5pNq8tFDjoBqE4E3mOv8Ay1b0KnZZTfxQ-FqXLEynysRFNGZ-cWyvRRCD_1S8f5BppBJq6lnlSwLg5MvFwLd5vCFx_WShYv-pTy2kUascEVnLdTo0WAZcVpUkFaRL5G_TrQe-pe892hF3EYl2I9uVUXjQTlmlB-x2o5MZGFcw", - "e": "AQAB" - }, - { - "kty": "EC", - "kid": "xSKvZxINfE7q84-_LRoEA235ANc", - "use": "sig", - "x": "4TkeqHgSbTNUC2PlWAlYYKF00ZnsaZZMiuEw8yKDkp0", - "y": "bvN_HvX6MqDSgF4CPvxNXYv00ykh4xNY5DjL8yqtQhY", - "crv": "P-256" - }, - { - "kty": "EC", - "kid": "DIlXC5clKGNCKMEbea0LEwGLu3A", - "use": "sig", - "x": "uFpx9tngNIhbCuxz4lZqlnVp9tRK0wc3K1VgjqwVplRsfcIX-3vfrQkQK56jdEnU", - "y": "l5RQxZVyAINt5a1fLPcflv1MF7ZPhcEezZjAMljHwJt0lstlLE1smVNtBVdfHFLI", - "crv": "P-384" - }, - { - "kty": "EC", - "kid": "Gbg8Vq0EWaTtG7pnzS_JK3V-T7Q", - "use": "sig", - "x": "AO6l8bUjuZh_kuQ6iWC0Lv9yz4efZJ1hmSdWbeLHIfJLKZ6Zoj5kC8e3rVvE6L-I0pqW4B4M82Aq97H-_PgYtiF2", - "y": "AZ1ecToQxtmkS-KetRWWMgCpIu1pabvNKpG1wKR7mIiZzYGmMljAx-8rgd26V1Nmkm5t6KnzUPtbhXqx8hZ3kxQr", - "crv": "P-521" - }, - { - "kty": "RSA", - "kid": "P4QmQdazhOEZ6ESp3Ox50SdbHaU", - "use": "sig", - "n": "qxCiLX5H67U4d30Mt3DATMpdyIAxsnTfRPivB0RXA93udke6i22BTHHA16ZkBvPeiQOOFirhTmz5SOVib4BoKKPQ4druxOXK8nw9Rb_sppMkWweuE7MqU7vjOAaoHHfxV4Q259H-uU48t2cvLMgYIu7Bjx4j0Trgx_SxQt5MKbIH0Fm0fzgwAzL3-MZ45QpM7ZQNMtrmh33HucM_fQ7kL3eu9M2l50ArnazqwFwwr8sIRexwG5bK_tqDpMiaU1Wd2DSbG1K3Bz2lM7o8MUipJuM1JrvFZmZ28siJsOv5V6qXxsrtEXv6_FnnGsLt0wbG5fafg1jxBGhbjpM1JHNITw", - "e": "AQAB" - }, - { - "kty": "EC", - "kid": "nWpBvRYWQClnJOMan7kZdeZyfJs", - "use": "sig", - "x": "ef5H_yUCuK3UYZ_N9tRPJBpsPn9Q43NS2lGQbssoEH8", - "y": "s7rQV_lLrB8-P-u8PXqc1JWrh3CG2dmq4-GDVq7jXvY", - "crv": "P-256" - }, - { - "kty": "EC", - "kid": "JFfeGS2KxYhtLQuGeg7nvIHQLPw", - "use": "sig", - "x": "gDUNGdt8A60xuElQYofIkHAGFdzGa9XrP7SJpU8CWpBLYpajOdm-nTUekbok4LTT", - "y": "iLFcRe-rE1txPFTIAlpyfbvB3c-J5YljeEcweriOCEd2C8vPTkNXQZdtQ6YJt-_L", - "crv": "P-384" - }, - { - "kty": "EC", - "kid": "NcjGwtxzt2b7V2m_Aql9lNkITxU", - "use": "sig", - "x": "Xa9mIe-gvxXBE1YDx5f6HtQSRTrfTlevBmfAMTPNndI", - "y": "HXqyS4Oj7nFaHVjdPOz0czmWlNmVHZkv49tKg-h_UnY", - "crv": "P-256" - }, - { - "kty": "EC", - "kid": "Nt8fp2lv7Dl68IzEw4LfciECYyM", - "use": "sig", - "x": "Afy5uoyurWTEnFsQFbz406s7ubuYuw8NxvYZjjjOWu3OXdQB5STE3Dq6IU384gtz7Qf-anX8_aLfpB1vQDz9Mc26", - "y": "AdSafTQB7IX_wiw3j5Xd-zRIaoIVBr5WdEvNKxlGM7VtDpPFXtn7YIU8bvNN8g6hqqdVMT4-LBk_khmcTSel-Bjb", - "crv": "P-521" - }, - { - "kty": "RSA", - "kid": "gvqsO-tegUGtLWrVeFtRDjwCzhE", - "use": "sig", - "n": "ie0wE0bn1pQ0xEeM5-2_I3aMt_eDI7oyCClCyU1faMeQkzDTAp6FLnqSD99Ryb-dheGObooPWm1JxxKU8gvoNl2k7OVNYcyZUsaBmvCLn1RWsBOpULojgjwdAH9WeKEXzNJVBwnGy_MZaRxC10-DVe36tIzhAzqo_I5WC-LKIb5l1MTbXjMVGltuQyVd-TrLhKunsXXBC7pwIEw2hh7XT9eeg8Hm4vYj1Urj44JsbNxKQ1JHEt4qG3RKAEJAipi9uSE8L8cnxTEHkqC9g1uomghazyNc17XMofTTzy7d0ZavRpIfnUID0YAAQihYBJCJP2pQn-lAfRQgjnBdCDZjRQ", - "e": "AQAB" - }, - { - "kty": "EC", - "kid": "QfOa2hKH27Xv4rl-zQbejysMynw", - "use": "enc", - "x": "Vet0n8upcTLpzZ_f4F8lWSId4YulgRIUcTdYrcw1SSmzKGFiUxAja0ZZnvaSPhBg", - "y": "D9oTv5xkGwtfrxQnRu10mylrApRjHkYLqrk_2Kcy5VnQHP3xuPNBFmvwl9qb-96e", - "crv": "P-384" - }, - { - "kty": "EC", - "kid": "QuAXzXi8B5mIcJnnmiXmPflLwx8", - "use": "enc", - "x": "dYHoomiYKJt87b-ed6nv7s3M_qU8r-DB6n105DTmKA4", - "y": "_864VDm74ZKkuRul30i4QrdjurApoX3B4iG2alYK0Oo", - "crv": "P-256" - }, - { - "kty": "EC", - "kid": "fm7BBBbVLxlaKc78nwP9l4lZRio", - "use": "enc", - "x": "AQSOn3fuj9l-gYamy1mJYRGj9aJXh2BlqgNqKPIYyCb2UjvHxnf4iTNPYbSqzmRD8pwCAvA8vcEeAXooBe06PeyX", - "y": "AUZcrcl3dUrfQg8cvcfwHXRtMND4TvGwQC0BU7T7HkF90oAXaun9AhAMURNomX7581_3AdK-znCBgifPqhgmcfQC", - "crv": "P-521" - }, - { - "kty": "RSA", - "kid": "j4hQX_PyMw_SU1EJIhwEIt2jVSM", - "use": "enc", - "n": "r4kVtn4i4caKzmn20VaPVyh6kBst2nObPejmkHRysyNtt06ttC0YwJpyGqeOFIl-pvDzXWfxFIOHpm25w1rotV47Sh6VT6zsZBUXUY3Go0_3pCacZO6HVNytCZvxHzA8Wtxzvc8Jri9dQzL0SYs_FKGzgyPNebprUepSVjtM-maS9suqokTcZ_7dizR5IhslDVLPPmmdGHqdwUIP4q75VguVPpDAQrSWLj_mvvqFSuA05XwJoGanWE612oCTBj2hMftyVNwi86PVXKZgPI5TM3cMpTrckXSgfGb-3Ls0cde5VlUrQI8v0Fo-ygAuTF9orSj6E5t3mJCZ6AaxuKcz0w", - "e": "AQAB" - } - ] -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.cs b/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.cs deleted file mode 100644 index ad3fef5..0000000 --- a/source/Tests/OpenIdConnect/Certificates/DefaultKeyJsonParserFixture.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.IO; -using Assent; -using Newtonsoft.Json; -using NUnit.Framework; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; - -namespace Tests.OpenIdConnect.Certificates -{ - [TestFixture] - public class DefaultKeyJsonParserFixture - { - [Test] - public void ShouldParseSupportedJwks_AzureAD() - { - // Source: https://login.microsoftonline.com/common/discovery/v2.0/keys - var content = LoadJwksContent(nameof(ShouldParseSupportedJwks_AzureAD)); - - var result = new DefaultKeyJsonParser().Parse(content); - - this.Assent(FormattedResult(result)); - } - - [Test] - public void ShouldParseSupportedJwks_Google() - { - // Source: https://www.googleapis.com/oauth2/v3/certs - var content = LoadJwksContent(nameof(ShouldParseSupportedJwks_Google)); - - var result = new DefaultKeyJsonParser().Parse(content); - - this.Assent(FormattedResult(result)); - } - - [Test] - public void ShouldParseSupportedJwks_Okta() - { - // Source: https://octopus-dev-roy.okta.com/oauth2/v1/keys - var content = LoadJwksContent(nameof(ShouldParseSupportedJwks_Okta)); - - var result = new DefaultKeyJsonParser().Parse(content); - - this.Assent(FormattedResult(result)); - } - - [Test] - public void ShouldParseSupportedJwks_Ping() - { - // Source: https://secure.helpscout.net/conversation/1171176136/64935 - var content = LoadJwksContent(nameof(ShouldParseSupportedJwks_Ping)); - - var result = new DefaultKeyJsonParser().Parse(content); - - this.Assent(FormattedResult(result)); - } - - static string FormattedResult(KeyDetails[] result) - { - return JsonConvert.SerializeObject(result, Formatting.Indented, new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All}); - } - - string LoadJwksContent(string testName) - { - var fixtureType = typeof(DefaultKeyJsonParserFixture); - var resourceName = $"{fixtureType.FullName}.{testName}.jwks.json"; - using var s = fixtureType.Assembly.GetManifestResourceStream(resourceName); - using var sr = new StreamReader(s); - return sr.ReadToEnd(); - } - } -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Tokens/CustomOpenIDConnectAuthTokenHandler.cs b/source/Tests/OpenIdConnect/Tokens/CustomOpenIDConnectAuthTokenHandler.cs deleted file mode 100644 index 2abf1a0..0000000 --- a/source/Tests/OpenIdConnect/Tokens/CustomOpenIDConnectAuthTokenHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Tests.OpenIdConnect.Tokens -{ - public class CustomOpenIDConnectAuthTokenHandler : OpenIDConnectAuthTokenHandler - { - public CustomOpenIDConnectAuthTokenHandler(ISystemLog log, IOpenIDConnectConfigurationStore configurationStore, IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, IKeyRetriever keyRetriever) : base(log, configurationStore, identityProviderConfigDiscoverer, keyRetriever) - { - - } - } -} diff --git a/source/Tests/OpenIdConnect/Tokens/CustomOpenIDConnectWithRoleAuthTokenHandler.cs b/source/Tests/OpenIdConnect/Tokens/CustomOpenIDConnectWithRoleAuthTokenHandler.cs deleted file mode 100644 index 29bed7a..0000000 --- a/source/Tests/OpenIdConnect/Tokens/CustomOpenIDConnectWithRoleAuthTokenHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Tokens; - -namespace Tests.OpenIdConnect.Tokens -{ - public class CustomOpenIDConnectWithRoleAuthTokenHandler : OpenIDConnectAuthTokenWithRolesHandler - { - public CustomOpenIDConnectWithRoleAuthTokenHandler(ISystemLog log, IOpenIDConnectConfigurationWithRoleStore configurationStore, IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer, IKeyRetriever keyRetriever) : base(log, configurationStore, identityProviderConfigDiscoverer, keyRetriever) - { - - } - } -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Tokens/OpenIDConnectAuthTokenHandlerFixture.cs b/source/Tests/OpenIdConnect/Tokens/OpenIDConnectAuthTokenHandlerFixture.cs deleted file mode 100644 index 0749263..0000000 --- a/source/Tests/OpenIdConnect/Tokens/OpenIDConnectAuthTokenHandlerFixture.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.IdentityModel.Tokens; -using Newtonsoft.Json; -using NSubstitute; -using NUnit.Framework; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; -using Octopus.Server.Extensibility.Authentication.Resources; - -namespace Tests.OpenIdConnect.Tokens -{ - [TestFixture] - public class OpenIDConnectAuthTokenHandlerFixture : OpenIDFixtureBase - { - ISystemLog log; - IOpenIDConnectConfigurationStore configurationStore; - IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer; - IKeyRetriever keyRetriever; - CustomOpenIDConnectAuthTokenHandler target; - - [SetUp] - public void SetUp() - { - log = Substitute.For(); - configurationStore = Substitute.For(); - identityProviderConfigDiscoverer = Substitute.For(); - keyRetriever = Substitute.For(); - - target = new CustomOpenIDConnectAuthTokenHandler( - log, - configurationStore, - identityProviderConfigDiscoverer, - keyRetriever); - } - - [Test] - public async Task ShouldReturnPrincipalWhenValidTokenReceived() - { - // Arrange - RsaSecurityKey rsaSecurityKeyPublic; - var token = CreateToken(KeyId, out rsaSecurityKeyPublic); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var key = new Dictionary {{KeyId, rsaSecurityKeyPublic}}; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - keyRetriever.GetKeysAsync(issuerConfig, false) - .Returns(Task.FromResult>(key)); - - // Act - var result = await target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => (string) pair.Value), out var stateString); - var state = JsonConvert.DeserializeObject(stateString); - - // Assert - Assert.IsNotNull(result); - Assert.That(result.Error, Is.Null.Or.Empty); - Assert.IsNotNull(result.Principal); - Assert.AreEqual(DefaultRedirect, state.RedirectAfterLoginTo); - - AssertClaims(result.Principal); - - configurationStore.Received().GetIssuer(); - configurationStore.Received().GetClientId(); - Received.InOrder(async () => { await keyRetriever.GetKeysAsync(issuerConfig, false); }); - - } - - [Test] - public async Task ShouldRetryWhenInvalidKeyDetected() - { - // Arrange - RsaSecurityKey rsaSecurityKeyStale; - RsaSecurityKey rsaSecurityKeyCurrent; - - var token = CreateToken("99a8e79fba13856b4159f96e9c9ea6d5", out rsaSecurityKeyStale); - token = CreateToken(KeyId, out rsaSecurityKeyCurrent); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var key = new Dictionary() { { KeyId, rsaSecurityKeyCurrent } }; - var staleKey = new Dictionary() { { "99a8e79fba13856b4159f96e9c9ea6d5", rsaSecurityKeyStale } }; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - // On first call to keyRetriever return invalid (stale) key - keyRetriever.GetKeysAsync(issuerConfig, false) - .Returns(Task.FromResult>(staleKey)); - - // On second call return the new valid key - keyRetriever.GetKeysAsync(issuerConfig, true) - .Returns(Task.FromResult>(key)); - - // Act - var result = await target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => pair.Value), out var stateString); - var state = JsonConvert.DeserializeObject(stateString); - - // Assert - Assert.IsNotNull(result); - Assert.That(result.Error, Is.Null.Or.Empty); - Assert.IsNotNull(result.Principal); - Assert.AreEqual(DefaultRedirect, state.RedirectAfterLoginTo); - - AssertClaims(result.Principal); - - configurationStore.Received().GetIssuer(); - configurationStore.Received().GetClientId(); - - Received.InOrder(async () => { await keyRetriever.GetKeysAsync(issuerConfig, false); }); - Received.InOrder(async () => { await keyRetriever.GetKeysAsync(issuerConfig, true); }); - } - - - [Test] - public void ShouldThrowWhenInvalidKeyDetectedTwice() - { - // Arrange - RsaSecurityKey rsaSecurityKeyStale; - RsaSecurityKey rsaSecurityKeyCurrent; - - var token = CreateToken("99a8e79fba13856b4159f96e9c9ea6d5", out rsaSecurityKeyStale); - token = CreateToken(KeyId, out rsaSecurityKeyCurrent); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var staleKey = new Dictionary() { { "99a8e79fba13856b4159f96e9c9ea6d5", rsaSecurityKeyStale } }; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - // set keyRetriever to always return invalid (stale) key - keyRetriever.GetKeysAsync(issuerConfig) - .ReturnsForAnyArgs(Task.FromResult>(staleKey)); - - // Act - Assert.ThrowsAsync(() => target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => pair.Value), out var stateString)); - - // Expect Exception Thrown - - } - - [Test] - [TestCase("https://someotherdomain.com", DefaultClientId, typeof(SecurityTokenInvalidIssuerException), Description = "Invalid Issuer")] - [TestCase(DefaultIssuer, "Another Client", typeof(SecurityTokenInvalidAudienceException), Description = "Invalid ClientId")] - public void ShouldThrowWhenInvalidTokenDetected(string issuer, string clientId, Type expectedException) - { - // Arrange - RsaSecurityKey rsaSecurityKeyPublic; - var token = CreateToken(KeyId, out rsaSecurityKeyPublic, issuer: issuer, clientId: clientId); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var key = new Dictionary() { { KeyId, rsaSecurityKeyPublic } }; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - keyRetriever.GetKeysAsync(issuerConfig, false) - .Returns(Task.FromResult>(key)); - - // Act - Assert.ThrowsAsync(expectedException, () => target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => pair.Value), out var stateString)); - - // Expect Exception Thrown - - } - - static IssuerConfiguration BuildCertificateIssuerConfiguration() - { - return new IssuerConfiguration {Issuer = DefaultIssuer, JwksUri = "https://some-jwks-uri/"}; - } - } -} diff --git a/source/Tests/OpenIdConnect/Tokens/OpenIDConnectWithRolesAuthTokenHandlerFixture.cs b/source/Tests/OpenIdConnect/Tokens/OpenIDConnectWithRolesAuthTokenHandlerFixture.cs deleted file mode 100644 index bc464ca..0000000 --- a/source/Tests/OpenIdConnect/Tokens/OpenIDConnectWithRolesAuthTokenHandlerFixture.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.IdentityModel.Tokens; -using NSubstitute; -using NUnit.Framework; -using Octopus.Diagnostics; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Certificates; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Configuration; -using Octopus.Server.Extensibility.Authentication.OpenIDConnect.Common.Issuer; - -namespace Tests.OpenIdConnect.Tokens -{ - [TestFixture] - public class OpenIDConnectWithRolesAuthTokenHandlerFixture : OpenIDFixtureBase - { - ISystemLog log; - IOpenIDConnectConfigurationWithRoleStore configurationStore; - IIdentityProviderConfigDiscoverer identityProviderConfigDiscoverer; - IKeyRetriever keyRetriever; - CustomOpenIDConnectWithRoleAuthTokenHandler target; - - [SetUp] - public void SetUp() - { - log = Substitute.For(); - configurationStore = Substitute.For(); - identityProviderConfigDiscoverer = Substitute.For(); - keyRetriever = Substitute.For(); - - target = new CustomOpenIDConnectWithRoleAuthTokenHandler( - log, - configurationStore, - identityProviderConfigDiscoverer, - keyRetriever); - } - - [Test] - public async Task ShouldReturnRolesFromToken() - { - // Arrange - RsaSecurityKey rsaSecurityKeyPublic; - var token = CreateToken(KeyId, out rsaSecurityKeyPublic, roleIds: new[] {"octoTesters"}); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var key = new Dictionary() {{KeyId, rsaSecurityKeyPublic}}; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - configurationStore.GetRoleClaimType().Returns("roles"); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - keyRetriever.GetKeysAsync(issuerConfig, false) - .Returns(Task.FromResult>(key)); - - // Act - var result = await target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => pair.Value), out var stateString); - - // Assert - Assert.IsNotNull(result); - Assert.That(result.Error, Is.Null.Or.Empty); - Assert.IsNotNull(result.ExternalGroupIds); - Assert.That(result.ExternalGroupIds.SingleOrDefault(x => x == "octoTesters"), Is.Not.Null.And.Not.Empty); - } - - [Test] - public async Task ShouldReturnGroupsFromToken() - { - // Arrange - RsaSecurityKey rsaSecurityKeyPublic; - var token = CreateToken(KeyId, out rsaSecurityKeyPublic, groupIds: new[] {"octoTesters"}); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var key = new Dictionary() {{KeyId, rsaSecurityKeyPublic}}; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - configurationStore.GetRoleClaimType().Returns("groups"); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - keyRetriever.GetKeysAsync(issuerConfig, false) - .Returns(Task.FromResult>(key)); - - // Act - var result = await target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => pair.Value), out var stateString); - - // Assert - Assert.IsNotNull(result); - Assert.That(result.Error, Is.Null.Or.Empty); - Assert.IsNotNull(result.ExternalGroupIds); - Assert.That(result.ExternalGroupIds.SingleOrDefault(x => x == "octoTesters"), Is.Not.Null.And.Not.Empty); - } - - [Test] - public async Task ShouldReturnNoRolesWhenOnlyGroupsAreInToken() - { - // Arrange - RsaSecurityKey rsaSecurityKeyPublic; - var token = CreateToken(KeyId, out rsaSecurityKeyPublic, groupIds: new[] {"octoTesters"}); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var key = new Dictionary() {{KeyId, rsaSecurityKeyPublic}}; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - configurationStore.GetRoleClaimType().Returns("roles"); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - keyRetriever.GetKeysAsync(issuerConfig, false) - .Returns(Task.FromResult>(key)); - - // Act - var result = await target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => pair.Value), out var stateString); - - // Assert - Assert.IsNotNull(result); - Assert.That(result.Error, Is.Null.Or.Empty); - - Assert.IsNotNull(result.ExternalGroupIds); - - Assert.IsEmpty(result.ExternalGroupIds); - } - - [Test] - public async Task ShouldReturnRolesAndGroupsWhenBothAreInToken() - { - // Arrange - RsaSecurityKey rsaSecurityKeyPublic; - var token = CreateToken(KeyId, out rsaSecurityKeyPublic, roleIds: new[] {"octoTestersRole"}, groupIds: new[] {"octoTestersGroup"}); - var issuerConfig = BuildCertificateIssuerConfiguration(); - var key = new Dictionary() {{KeyId, rsaSecurityKeyPublic}}; - - var request = CreateRequest(token); - - configurationStore.GetIssuer().Returns(DefaultIssuer); - configurationStore.GetClientId().Returns(DefaultClientId); - configurationStore.GetRoleClaimType().Returns("groups"); - - identityProviderConfigDiscoverer.GetConfiguration(DefaultIssuer) - .Returns(Task.FromResult(issuerConfig)); - - keyRetriever.GetKeysAsync(issuerConfig, false) - .Returns(Task.FromResult>(key)); - - // Act - var result = await target.GetPrincipalAsync(request.Form.ToDictionary(pair => pair.Key, pair => pair.Value), out var stateString); - - // Assert - Assert.IsNotNull(result); - Assert.That(result.Error, Is.Null.Or.Empty); - Assert.IsNotNull(result.ExternalGroupIds); - Assert.That(result.ExternalGroupIds.SingleOrDefault(x => x == "octoTestersRole"), Is.Not.Null.And.Not.Empty); - Assert.That(result.ExternalGroupIds.SingleOrDefault(x => x == "octoTestersGroup"), Is.Not.Null.And.Not.Empty); - } - - static IssuerConfiguration BuildCertificateIssuerConfiguration() - { - return new IssuerConfiguration {Issuer = DefaultIssuer, JwksUri = "https://some-jwks-uri/"}; - } - } -} \ No newline at end of file diff --git a/source/Tests/OpenIdConnect/Tokens/OpenIDFixtureBase.cs b/source/Tests/OpenIdConnect/Tokens/OpenIDFixtureBase.cs deleted file mode 100644 index 9a55474..0000000 --- a/source/Tests/OpenIdConnect/Tokens/OpenIDFixtureBase.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Security.Cryptography; -using System.Security.Principal; -using System.Threading.Tasks; -using JWT; -using JWT.Serializers; -using Microsoft.IdentityModel.Tokens; -using Newtonsoft.Json; -using NUnit.Framework; -using Octopus.Server.Extensibility.Authentication.Resources; -using Octopus.Server.Extensibility.Extensions.Infrastructure.Web.Api; -using Tests.Helpers; - -namespace Tests.OpenIdConnect.Tokens -{ - public class OpenIDFixtureBase - { - protected const string DefaultIssuer = "https://somedomain.com/"; - protected const string DefaultClientId = "Octopus Deploy"; - protected const string DefaultSubject = "12345"; - protected const string DefaultName = "bob"; - protected const string DefaultEmail = "bob@somedomain.com"; - - protected const string KeyId = "88a8e79fba13856b4159f96e9c9ea6d5"; - protected const string Nonce = ""; - - protected const string DefaultRedirect = "/infrastructure/machines/machines-1"; - - class OctoRequest : IOctoRequest - { - public OctoRequest(string scheme, bool isHttps, string host, string pathBase, string path, string protocol, IDictionary> headers, IDictionary form, IDictionary cookies, IPrincipal user) - { - Scheme = scheme; - IsHttps = isHttps; - Host = host; - PathBase = pathBase; - Path = path; - Protocol = protocol; - Headers = headers; - Form = form; - Cookies = cookies; - User = user; - } - - public string Scheme { get; } - public bool IsHttps { get; } - public string Host { get; } - public string PathBase { get; } - public string Path { get; } - public string Protocol { get; } - public IDictionary> Headers { get; } - public IDictionary Form { get; } - public IDictionary Cookies { get; } - public IPrincipal User { get; } - - public Task HandleAsync(Func> onSuccess) - { - throw new NotImplementedException(); - } - - public Task HandleAsync(IResponderParameter parameter, Func> onSuccess) - { - throw new NotImplementedException(); - } - - public Task HandleAsync(IResponderParameter parameter1, IResponderParameter parameter2, Func> onSuccess) - { - throw new NotImplementedException(); - } - - public Task HandleAsync(IResponderParameter parameter1, IResponderParameter parameter2, IResponderParameter parameter3, Func> onSuccess) - { - throw new NotImplementedException(); - } - - public Task HandleAsync(IResponderParameter parameter1, IResponderParameter parameter2, IResponderParameter parameter3, IResponderParameter parameter4, Func> onSuccess) - { - throw new NotImplementedException(); - } - - public Task HandleAsync(IResponderParameter parameter1, IResponderParameter parameter2, IResponderParameter parameter3, IResponderParameter parameter4, IResponderParameter parameter5, Func> onSuccess) - { - throw new NotImplementedException(); - } - - public TResource GetBody(RequestBodyRegistration registration) - { - throw new NotImplementedException(); - } - } - - protected IOctoRequest CreateRequest(string token, string redirectAfterLoginTo = DefaultRedirect, bool usingSecureConnection = false) - { - var request = new OctoRequest("https", true, DefaultIssuer, String.Empty, string.Empty, "http", null, new Dictionary(), null, null); - //request.Form["access_token"] = null; - request.Form["id_token"] = token; - var stateData = JsonConvert.SerializeObject(new LoginState {RedirectAfterLoginTo = redirectAfterLoginTo, UsingSecureConnection = usingSecureConnection}); - request.Form["state"] = stateData; - return request; - } - - protected string CreateToken( - string keyId, - out RsaSecurityKey key, - string issuer = DefaultIssuer, - string clientId = DefaultClientId, - string nonce = Nonce, - string subject = DefaultSubject, - string name = DefaultName, - string email = DefaultEmail, - string[] roleIds = null, - string[] groupIds = null) - { - var epoch = new DateTime(1970, 1, 1); - var now = Math.Round((DateTime.Now - epoch).TotalSeconds); - var exp = now + 36000; - - var payload = new Dictionary - { - { "aud", clientId }, - { "iss", issuer }, - { "exp", exp }, - { "iat", now }, - { "nonce", nonce }, - { "sub", subject}, - { "name", name}, - { "email", email} - }; - - var headers = new Dictionary - { - { "kid", keyId} - }; - - if (roleIds != null && roleIds.Any()) - { - payload.Add("roles", roleIds); - } - if (groupIds != null && groupIds.Any()) - { - payload.Add("groups", groupIds); - } - - using (var rsa = new RSACryptoServiceProvider(2048)) - { - var rsaParametersPublic = rsa.ExportParameters(includePrivateParameters: false); - key = new RsaSecurityKey(rsaParametersPublic) {KeyId = keyId}; - - var algorithm = new RS256AlgorithmRsaOnly(rsa); - var serializer = new JsonNetSerializer(); - var urlEncoder = new JwtBase64UrlEncoder(); - var encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - var token = encoder.Encode(headers, payload, string.Empty); - - return token; - } - } - - protected void AssertClaims( - ClaimsPrincipal principal, - string issuer = DefaultIssuer, - string clientid = DefaultClientId, - string nonce = Nonce, - string subject = DefaultSubject, - string name = DefaultName, - string email = DefaultEmail) - { - Assert.IsTrue(principal.HasClaim(x => x.Type == "iss" && x.Value == issuer)); - Assert.IsTrue(principal.HasClaim(x => x.Type == "aud" && x.Value == clientid)); - Assert.IsTrue(principal.HasClaim(x => x.Type == "nonce" && x.Value == nonce)); - Assert.IsTrue(principal.HasClaim(x => x.Type == "name" && x.Value == name)); - Assert.IsTrue(principal.HasClaim(x => x.Type == ClaimTypes.NameIdentifier && x.Value == subject)); - Assert.IsTrue(principal.HasClaim(x => x.Type == ClaimTypes.Email && x.Value == email)); - } - } -} \ No newline at end of file diff --git a/source/Tests/Tests.csproj b/source/Tests/Tests.csproj deleted file mode 100644 index 236165f..0000000 --- a/source/Tests/Tests.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - net6.0 - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file