From 2fdc550dcb389bf18dffbf52bc45253d8b65958a Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Thu, 5 Sep 2024 09:14:22 +0200 Subject: [PATCH 01/10] scaffold sample --- .../CustomClaimsProvider.csproj | 91 ++++++++++++++++++ .../CustomClaimsProvider.sln | 27 ++++++ ...DAPCPSE.Custom.ClaimsProvider.Template.xml | 3 + .../LDAPCPSE.Custom.ClaimsProvider.feature | 2 + .../LDAPCPSE.Custom.EventReceiver.cs | 51 ++++++++++ .../CustomClaimsProvider/LDAPCPSE_Custom.cs | 37 +++++++ .../Package/Package.Template.xml | 3 + .../Package/Package.package | 47 +++++++++ .../Properties/AssemblyInfo.cs | 38 ++++++++ .../CustomClaimsProvider/README.md | 9 ++ custom-claims-provider-samples/README.md | 4 + .../Yvand.LDAPCPSE.dll | Bin 0 -> 128000 bytes 12 files changed, 312 insertions(+) create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.csproj create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.sln create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.Template.xml create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/LDAPCPSE_Custom.cs create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Package/Package.Template.xml create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Properties/AssemblyInfo.cs create mode 100644 custom-claims-provider-samples/CustomClaimsProvider/README.md create mode 100644 custom-claims-provider-samples/README.md create mode 100644 custom-claims-provider-samples/Yvand.LDAPCPSE.dll diff --git a/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.csproj b/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.csproj new file mode 100644 index 0000000..1e3fe49 --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.csproj @@ -0,0 +1,91 @@ + + + + Debug + AnyCPU + {CC278266-3F09-4908-BCE8-725D2AA9153E} + Library + Properties + CustomClaimsProvider + CustomClaimsProvider + v4.8 + 19.0 + 512 + {C1CDDADD-2546-481F-9697-4EA41081F2FC};{14822709-B5A1-4724-98CA-57A101D1B079};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + 14.1 + False + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + x64 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + true + + + key.snk + + + + + + + False + ..\Yvand.LDAPCPSE.dll + + + + + LDAPCPSE.Custom.ClaimsProvider.feature + + + + + + + {9492009a-e84b-4bcc-a960-e0671966464d} + + + + {034f2ce9-76ca-4b10-a136-85143ef303c9} + + + Package.package + + + + + + LDAPCPSE.Custom.ClaimsProvider.feature + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\gacutil.exe" /f /i "$(TargetPath)" +copy /Y "$(TargetDir)Yvand.LDAPCPSE.dll" $(ProjectDir)\bin + + \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.sln b/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.sln new file mode 100644 index 0000000..b6bde26 --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35013.160 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomClaimsProvider", "CustomClaimsProvider.csproj", "{CC278266-3F09-4908-BCE8-725D2AA9153E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CC278266-3F09-4908-BCE8-725D2AA9153E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC278266-3F09-4908-BCE8-725D2AA9153E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC278266-3F09-4908-BCE8-725D2AA9153E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {CC278266-3F09-4908-BCE8-725D2AA9153E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC278266-3F09-4908-BCE8-725D2AA9153E}.Release|Any CPU.Build.0 = Release|Any CPU + {CC278266-3F09-4908-BCE8-725D2AA9153E}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {75E70229-6D16-4FD1-B776-1D3CF6994E65} + EndGlobalSection +EndGlobal diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.Template.xml b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.Template.xml new file mode 100644 index 0000000..c27273d --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.Template.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature new file mode 100644 index 0000000..3500408 --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs new file mode 100644 index 0000000..90f0e12 --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs @@ -0,0 +1,51 @@ +using Microsoft.SharePoint; +using System; +using System.Runtime.InteropServices; +using System.Security.Permissions; + +namespace CustomClaimsProvider.Features +{ + /// + /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade. + /// + /// + /// The GUID attached to this class may be used during packaging and should not be modified. + /// + + [Guid("8a0189bf-2e90-48b0-85f7-f639b42e3ef8")] + public class LDAPCPSECustomEventReceiver : SPFeatureReceiver + { + // Uncomment the method below to handle the event raised after a feature has been activated. + + //public override void FeatureActivated(SPFeatureReceiverProperties properties) + //{ + //} + + + // Uncomment the method below to handle the event raised before a feature is deactivated. + + //public override void FeatureDeactivating(SPFeatureReceiverProperties properties) + //{ + //} + + + // Uncomment the method below to handle the event raised after a feature has been installed. + + //public override void FeatureInstalled(SPFeatureReceiverProperties properties) + //{ + //} + + + // Uncomment the method below to handle the event raised before a feature is uninstalled. + + //public override void FeatureUninstalling(SPFeatureReceiverProperties properties) + //{ + //} + + // Uncomment the method below to handle the event raised when a feature is upgrading. + + //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary parameters) + //{ + //} + } +} diff --git a/custom-claims-provider-samples/CustomClaimsProvider/LDAPCPSE_Custom.cs b/custom-claims-provider-samples/CustomClaimsProvider/LDAPCPSE_Custom.cs new file mode 100644 index 0000000..efa51bf --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/LDAPCPSE_Custom.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using Yvand.LdapClaimsProvider; +using Yvand.LdapClaimsProvider.Configuration; + +namespace CustomClaimsProvider +{ + public class LDAPCPSE_Custom : LDAPCPSE + { + /// + /// Sets the name of the claims provider, also set in (Get-SPTrustedIdentityTokenIssuer).ClaimProviderName property + /// + public new const string ClaimsProviderName = "LDAPCPSE_Custom"; + + /// + /// Do not remove or change this property + /// + public override string Name => ClaimsProviderName; + + public LDAPCPSE_Custom(string displayName) : base(displayName) + { + } + + public override ILdapProviderSettings GetSettings() + { + ClaimsProviderSettings settings = ClaimsProviderSettings.GetDefaultSettings(ClaimsProviderName); + //EntraIDTenant tenant = new EntraIDTenant + //{ + // AzureCloud = AzureCloudName.AzureGlobal, + // Name = "TENANTNAME.onmicrosoft.com", + // ClientId = "CLIENTID", + // ClientSecret = "CLIENTSECRET", + //}; + //settings.EntraIDTenants = new List() { tenant }; + return settings; + } + } +} diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.Template.xml b/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.Template.xml new file mode 100644 index 0000000..640ff0f --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.Template.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package b/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package new file mode 100644 index 0000000..0d15d72 --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Properties/AssemblyInfo.cs b/custom-claims-provider-samples/CustomClaimsProvider/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..bebe4c0 --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("EntraCP.Custom")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EntraCP.Custom")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("cc278266-3f09-4908-bce8-725d2aa9153e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + diff --git a/custom-claims-provider-samples/CustomClaimsProvider/README.md b/custom-claims-provider-samples/CustomClaimsProvider/README.md new file mode 100644 index 0000000..6a7e667 --- /dev/null +++ b/custom-claims-provider-samples/CustomClaimsProvider/README.md @@ -0,0 +1,9 @@ +# Sample with a hard-coded configuration and a manual reference to LDAPCPSE + +This project shows how to create a claims provider that inherits LDAPCPSE. It uses a simple, hard-coded configuration to specify the tenant. + +> [!WARNING] +> Do NOT deploy this solution in a SharePoint farm that already has LDAPCPSE deployed, unless both use **exactly** the same versions of NuGet dependencies. If they use different versions, that may cause errors when loading DLLs, due to mismatches with the assembly bindings in the machine.config file. + +> [!IMPORTANT] +> You need to manually add a reference to `Yvand.LDAPCPSE.dll`. diff --git a/custom-claims-provider-samples/README.md b/custom-claims-provider-samples/README.md new file mode 100644 index 0000000..e0a0728 --- /dev/null +++ b/custom-claims-provider-samples/README.md @@ -0,0 +1,4 @@ +# Sample projects for developers + +This folder contains Visual Studio projects that developers can use to create their custom clainms providers based on EntraCP. +This is useful only for specific needs. diff --git a/custom-claims-provider-samples/Yvand.LDAPCPSE.dll b/custom-claims-provider-samples/Yvand.LDAPCPSE.dll new file mode 100644 index 0000000000000000000000000000000000000000..768a153a931be8a7067ae4f8a79b7cb85ff6bda2 GIT binary patch literal 128000 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 literal 0 HcmV?d00001 From f2362f109f953dc044c45f6b2142f332b1680161 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Thu, 5 Sep 2024 16:41:44 +0200 Subject: [PATCH 02/10] work --- custom-claims-provider-samples/.gitignore | 1 + .../LDAPCPSE.Custom.EventReceiver.cs | 76 ++++++++++++------- 2 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 custom-claims-provider-samples/.gitignore diff --git a/custom-claims-provider-samples/.gitignore b/custom-claims-provider-samples/.gitignore new file mode 100644 index 0000000..ea23616 --- /dev/null +++ b/custom-claims-provider-samples/.gitignore @@ -0,0 +1 @@ +*.dll \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs index 90f0e12..0894f36 100644 --- a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs +++ b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs @@ -1,7 +1,9 @@ using Microsoft.SharePoint; +using Microsoft.SharePoint.Administration; +using Microsoft.SharePoint.Administration.Claims; using System; using System.Runtime.InteropServices; -using System.Security.Permissions; +using Yvand.LdapClaimsProvider.Logging; namespace CustomClaimsProvider.Features { @@ -13,39 +15,59 @@ namespace CustomClaimsProvider.Features /// [Guid("8a0189bf-2e90-48b0-85f7-f639b42e3ef8")] - public class LDAPCPSECustomEventReceiver : SPFeatureReceiver + public class LDAPCPSECustomEventReceiver : SPClaimProviderFeatureReceiver { - // Uncomment the method below to handle the event raised after a feature has been activated. + public override string ClaimProviderAssembly => typeof(LDAPCPSE_Custom).Assembly.FullName; - //public override void FeatureActivated(SPFeatureReceiverProperties properties) - //{ - //} + public override string ClaimProviderDescription => LDAPCPSE_Custom.ClaimsProviderName; + public override string ClaimProviderDisplayName => LDAPCPSE_Custom.ClaimsProviderName; - // Uncomment the method below to handle the event raised before a feature is deactivated. + public override string ClaimProviderType => typeof(LDAPCPSE_Custom).FullName; - //public override void FeatureDeactivating(SPFeatureReceiverProperties properties) - //{ - //} + public override void FeatureActivated(SPFeatureReceiverProperties properties) + { + ExecBaseFeatureActivated(properties); + } + private void ExecBaseFeatureActivated(Microsoft.SharePoint.SPFeatureReceiverProperties properties) + { + // Wrapper function for base FeatureActivated. + // Used because base keywork can lead to unverifiable code inside lambda expression + base.FeatureActivated(properties); + SPSecurity.RunWithElevatedPrivileges((SPSecurity.CodeToRunElevated)delegate () + { + try + { + Logger svc = Logger.Local; + Logger.Log($"[{LDAPCPSE_Custom.ClaimsProviderName}] Activating farm-scoped feature for claims provider \"{LDAPCPSE_Custom.ClaimsProviderName}\"", TraceSeverity.High, EventSeverity.Information, TraceCategory.Configuration); + } + catch (Exception ex) + { + Logger.LogException((string)LDAPCPSE_Custom.ClaimsProviderName, $"activating farm-scoped feature for claims provider \"{LDAPCPSE_Custom.ClaimsProviderName}\"", TraceCategory.Configuration, ex); + } + }); + } - // Uncomment the method below to handle the event raised after a feature has been installed. + public override void FeatureUninstalling(SPFeatureReceiverProperties properties) + { + } - //public override void FeatureInstalled(SPFeatureReceiverProperties properties) - //{ - //} + public override void FeatureDeactivating(SPFeatureReceiverProperties properties) + { + SPSecurity.RunWithElevatedPrivileges((SPSecurity.CodeToRunElevated)delegate () + { + try + { + Logger.Log($"[{LDAPCPSE_Custom.ClaimsProviderName}] Deactivating farm-scoped feature for claims provider \"{LDAPCPSE_Custom.ClaimsProviderName}\": Removing claims provider from the farm (but not its configuration)", TraceSeverity.High, EventSeverity.Information, TraceCategory.Configuration); + base.RemoveClaimProvider((string)LDAPCPSE_Custom.ClaimsProviderName); + } + catch (Exception ex) + { + Logger.LogException((string)LDAPCPSE_Custom.ClaimsProviderName, $"deactivating farm-scoped feature for claims provider \"{LDAPCPSE_Custom.ClaimsProviderName}\"", TraceCategory.Configuration, ex); + } + }); + } - - // Uncomment the method below to handle the event raised before a feature is uninstalled. - - //public override void FeatureUninstalling(SPFeatureReceiverProperties properties) - //{ - //} - - // Uncomment the method below to handle the event raised when a feature is upgrading. - - //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary parameters) - //{ - //} } -} +} \ No newline at end of file From 758d97b7a4c9fd6d803f7b325bf9720587680342 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Thu, 5 Sep 2024 16:42:48 +0200 Subject: [PATCH 03/10] work --- custom-claims-provider-samples/.gitignore | 2 +- .../Yvand.LDAPCPSE.dll | Bin 128000 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 custom-claims-provider-samples/Yvand.LDAPCPSE.dll diff --git a/custom-claims-provider-samples/.gitignore b/custom-claims-provider-samples/.gitignore index ea23616..0e11bd6 100644 --- a/custom-claims-provider-samples/.gitignore +++ b/custom-claims-provider-samples/.gitignore @@ -1 +1 @@ -*.dll \ No newline at end of file +*.dllx \ No newline at end of file diff --git a/custom-claims-provider-samples/Yvand.LDAPCPSE.dll b/custom-claims-provider-samples/Yvand.LDAPCPSE.dll deleted file mode 100644 index 768a153a931be8a7067ae4f8a79b7cb85ff6bda2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128000 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 From 18af13857d69b68601cb22acd7e7a5a0167b2e8b Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Thu, 5 Sep 2024 16:43:05 +0200 Subject: [PATCH 04/10] Update .gitignore --- custom-claims-provider-samples/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom-claims-provider-samples/.gitignore b/custom-claims-provider-samples/.gitignore index 0e11bd6..ea23616 100644 --- a/custom-claims-provider-samples/.gitignore +++ b/custom-claims-provider-samples/.gitignore @@ -1 +1 @@ -*.dllx \ No newline at end of file +*.dll \ No newline at end of file From 1931c8071b120be11f9163e3ef97e86db30346b4 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Wed, 18 Sep 2024 11:44:06 +0200 Subject: [PATCH 05/10] update sample --- .../LDAPCPSE.Custom.ClaimsProvider.feature | 2 - .../Package/Package.package | 47 ------------------- ...PSE_basic.ClaimsProvider.EventReceiver.cs} | 3 +- ...DAPCPSE_basic.ClaimsProvider.Template.xml} | 0 .../LDAPCPSE_basic.ClaimsProvider.feature | 2 + .../LDAPCPSE_Custom.cs | 14 ++---- .../LDAPCPSE_basic.csproj} | 18 +++---- .../LDAPCPSE_basic.sln} | 2 +- .../Package/Package.Template.xml | 0 .../LDAPCPSE_basic/Package/Package.package | 9 ++++ .../Properties/AssemblyInfo.cs | 0 .../README.md | 0 12 files changed, 26 insertions(+), 71 deletions(-) delete mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature delete mode 100644 custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package rename custom-claims-provider-samples/{CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs => LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.EventReceiver.cs} (98%) rename custom-claims-provider-samples/{CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.Template.xml => LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.Template.xml} (100%) create mode 100644 custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.feature rename custom-claims-provider-samples/{CustomClaimsProvider => LDAPCPSE_basic}/LDAPCPSE_Custom.cs (63%) rename custom-claims-provider-samples/{CustomClaimsProvider/CustomClaimsProvider.csproj => LDAPCPSE_basic/LDAPCPSE_basic.csproj} (85%) rename custom-claims-provider-samples/{CustomClaimsProvider/CustomClaimsProvider.sln => LDAPCPSE_basic/LDAPCPSE_basic.sln} (88%) rename custom-claims-provider-samples/{CustomClaimsProvider => LDAPCPSE_basic}/Package/Package.Template.xml (100%) create mode 100644 custom-claims-provider-samples/LDAPCPSE_basic/Package/Package.package rename custom-claims-provider-samples/{CustomClaimsProvider => LDAPCPSE_basic}/Properties/AssemblyInfo.cs (100%) rename custom-claims-provider-samples/{CustomClaimsProvider => LDAPCPSE_basic}/README.md (100%) diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature b/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature deleted file mode 100644 index 3500408..0000000 --- a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.feature +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package b/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package deleted file mode 100644 index 0d15d72..0000000 --- a/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.package +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs b/custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.EventReceiver.cs similarity index 98% rename from custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs rename to custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.EventReceiver.cs index 0894f36..8df1ac5 100644 --- a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.EventReceiver.cs +++ b/custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.EventReceiver.cs @@ -5,7 +5,7 @@ using System.Runtime.InteropServices; using Yvand.LdapClaimsProvider.Logging; -namespace CustomClaimsProvider.Features +namespace LDAPCPSE_basic.Features { /// /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade. @@ -68,6 +68,5 @@ public override void FeatureDeactivating(SPFeatureReceiverProperties properties) } }); } - } } \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.Template.xml b/custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.Template.xml similarity index 100% rename from custom-claims-provider-samples/CustomClaimsProvider/Features/LDAPCPSE.Custom.ClaimsProvider/LDAPCPSE.Custom.ClaimsProvider.Template.xml rename to custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.Template.xml diff --git a/custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.feature b/custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.feature new file mode 100644 index 0000000..f4d85ff --- /dev/null +++ b/custom-claims-provider-samples/LDAPCPSE_basic/Features/LDAPCPSE_basic.ClaimsProvider/LDAPCPSE_basic.ClaimsProvider.feature @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/LDAPCPSE_Custom.cs b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs similarity index 63% rename from custom-claims-provider-samples/CustomClaimsProvider/LDAPCPSE_Custom.cs rename to custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs index efa51bf..86eb028 100644 --- a/custom-claims-provider-samples/CustomClaimsProvider/LDAPCPSE_Custom.cs +++ b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs @@ -1,8 +1,7 @@ -using System.Collections.Generic; -using Yvand.LdapClaimsProvider; +using Yvand.LdapClaimsProvider; using Yvand.LdapClaimsProvider.Configuration; -namespace CustomClaimsProvider +namespace LDAPCPSE_basic { public class LDAPCPSE_Custom : LDAPCPSE { @@ -23,14 +22,7 @@ public LDAPCPSE_Custom(string displayName) : base(displayName) public override ILdapProviderSettings GetSettings() { ClaimsProviderSettings settings = ClaimsProviderSettings.GetDefaultSettings(ClaimsProviderName); - //EntraIDTenant tenant = new EntraIDTenant - //{ - // AzureCloud = AzureCloudName.AzureGlobal, - // Name = "TENANTNAME.onmicrosoft.com", - // ClientId = "CLIENTID", - // ClientSecret = "CLIENTSECRET", - //}; - //settings.EntraIDTenants = new List() { tenant }; + settings.EntityDisplayTextPrefix = "(custom) "; return settings; } } diff --git a/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.csproj b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_basic.csproj similarity index 85% rename from custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.csproj rename to custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_basic.csproj index 1e3fe49..d5d2693 100644 --- a/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.csproj +++ b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_basic.csproj @@ -6,8 +6,8 @@ {CC278266-3F09-4908-BCE8-725D2AA9153E} Library Properties - CustomClaimsProvider - CustomClaimsProvider + LDAPCPSE_basic + LDAPCPSE_basic v4.8 19.0 512 @@ -47,21 +47,23 @@ - + + False + False ..\Yvand.LDAPCPSE.dll - - LDAPCPSE.Custom.ClaimsProvider.feature + + LDAPCPSE_basic.ClaimsProvider.feature - + {9492009a-e84b-4bcc-a960-e0671966464d} @@ -74,8 +76,8 @@ - - LDAPCPSE.Custom.ClaimsProvider.feature + + LDAPCPSE_basic.ClaimsProvider.feature diff --git a/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.sln b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_basic.sln similarity index 88% rename from custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.sln rename to custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_basic.sln index b6bde26..38b9df5 100644 --- a/custom-claims-provider-samples/CustomClaimsProvider/CustomClaimsProvider.sln +++ b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_basic.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.10.35013.160 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomClaimsProvider", "CustomClaimsProvider.csproj", "{CC278266-3F09-4908-BCE8-725D2AA9153E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LDAPCPSE_basic", "LDAPCPSE_basic.csproj", "{CC278266-3F09-4908-BCE8-725D2AA9153E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Package/Package.Template.xml b/custom-claims-provider-samples/LDAPCPSE_basic/Package/Package.Template.xml similarity index 100% rename from custom-claims-provider-samples/CustomClaimsProvider/Package/Package.Template.xml rename to custom-claims-provider-samples/LDAPCPSE_basic/Package/Package.Template.xml diff --git a/custom-claims-provider-samples/LDAPCPSE_basic/Package/Package.package b/custom-claims-provider-samples/LDAPCPSE_basic/Package/Package.package new file mode 100644 index 0000000..4928ed3 --- /dev/null +++ b/custom-claims-provider-samples/LDAPCPSE_basic/Package/Package.package @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/custom-claims-provider-samples/CustomClaimsProvider/Properties/AssemblyInfo.cs b/custom-claims-provider-samples/LDAPCPSE_basic/Properties/AssemblyInfo.cs similarity index 100% rename from custom-claims-provider-samples/CustomClaimsProvider/Properties/AssemblyInfo.cs rename to custom-claims-provider-samples/LDAPCPSE_basic/Properties/AssemblyInfo.cs diff --git a/custom-claims-provider-samples/CustomClaimsProvider/README.md b/custom-claims-provider-samples/LDAPCPSE_basic/README.md similarity index 100% rename from custom-claims-provider-samples/CustomClaimsProvider/README.md rename to custom-claims-provider-samples/LDAPCPSE_basic/README.md From 327e2f216f10989115a3b864e115de0d26ad6941 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Wed, 18 Sep 2024 11:46:43 +0200 Subject: [PATCH 06/10] update readme files --- custom-claims-provider-samples/LDAPCPSE_basic/README.md | 5 +---- custom-claims-provider-samples/README.md | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/custom-claims-provider-samples/LDAPCPSE_basic/README.md b/custom-claims-provider-samples/LDAPCPSE_basic/README.md index 6a7e667..faace8b 100644 --- a/custom-claims-provider-samples/LDAPCPSE_basic/README.md +++ b/custom-claims-provider-samples/LDAPCPSE_basic/README.md @@ -3,7 +3,4 @@ This project shows how to create a claims provider that inherits LDAPCPSE. It uses a simple, hard-coded configuration to specify the tenant. > [!WARNING] -> Do NOT deploy this solution in a SharePoint farm that already has LDAPCPSE deployed, unless both use **exactly** the same versions of NuGet dependencies. If they use different versions, that may cause errors when loading DLLs, due to mismatches with the assembly bindings in the machine.config file. - -> [!IMPORTANT] -> You need to manually add a reference to `Yvand.LDAPCPSE.dll`. +> Do NOT deploy this solution in a SharePoint farm that already has LDAPCPSE deployed, unless both use **exactly** the same version of `Yvand.LDAPCPSE.dll`. diff --git a/custom-claims-provider-samples/README.md b/custom-claims-provider-samples/README.md index e0a0728..9c44320 100644 --- a/custom-claims-provider-samples/README.md +++ b/custom-claims-provider-samples/README.md @@ -1,4 +1,4 @@ # Sample projects for developers -This folder contains Visual Studio projects that developers can use to create their custom clainms providers based on EntraCP. +This folder contains Visual Studio projects that developers can use to create their custom clainms providers based on LDAPCPSE. This is useful only for specific needs. From 80fa4bc5b401241b5b90ceeb54dd033637034c23 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Wed, 18 Sep 2024 17:40:08 +0200 Subject: [PATCH 07/10] Add property CustomFilter to class DirectoryConnection --- Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj | 1 + .../Configuration/ClaimsProviderConstants.cs | 2 +- .../Configuration/DirectoryConnection.cs | 11 ++++++ .../Yvand.LdapClaimsProvider/LDAPCPSE.cs | 8 +++++ .../LdapEntityProvider.cs | 36 ++++++++++++++----- .../LDAPCPSE_basic/LDAPCPSE_Custom.cs | 13 ++++++- 6 files changed, 60 insertions(+), 11 deletions(-) diff --git a/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj b/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj index c1a3aaa..ff01a1e 100644 --- a/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj +++ b/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj @@ -65,6 +65,7 @@ False references\SPSE\Microsoft.SharePoint.dll + False diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs index 98cf5a6..d585dce 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs @@ -312,7 +312,7 @@ public class OperationContext /// public List CurrentClaimTypeConfigList { get; private set; } - public List LdapConnections { get; private set; } + public List LdapConnections { get; set; } public OperationContext(ClaimsProviderSettings settings, OperationType currentRequestType, string input, SPClaim incomingEntity, Uri context, string[] entityTypes, string hierarchyNodeID, int maxCount) { diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs index 695c9ec..367397f 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs @@ -105,6 +105,17 @@ public string[] GroupMembershipLdapAttributes [Persisted] private string[] _GroupMembershipLdapAttributes = new string[] { "memberOf", "uniquememberof" }; + /// + /// Get or set a LDAP filter specific to this LDAP connection + /// + public string CustomFilter + { + get { return _CustomFilter; } + set { _CustomFilter = value; } + } + [Persisted] + private string _CustomFilter; + /// /// DirectoryEntry used to make LDAP queries /// diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs index 47650c7..45caa31 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs @@ -385,6 +385,7 @@ protected void AugmentEntity(Uri context, SPClaim entity, SPClaimProviderContext Logger.Log($"[{Name}] Starting augmentation for user '{decodedEntity.Value}'.", TraceSeverity.Verbose, EventSeverity.Information, TraceCategory.Augmentation); currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Augmentation, String.Empty, decodedEntity, context, null, null, Int32.MaxValue); + ValidateRuntimeSettings(currentContext); Stopwatch timer = new Stopwatch(); timer.Start(); List groups = this.EntityProvider.GetEntityGroups(currentContext); @@ -439,6 +440,7 @@ protected override void FillResolve(Uri context, string[] entityTypes, string re try { OperationContext currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Search, resolveInput, null, context, entityTypes, null, 30); + ValidateRuntimeSettings(currentContext); List entities = SearchOrValidate(currentContext); if (entities == null || entities.Count == 0) { return; } foreach (PickerEntity entity in entities) @@ -470,6 +472,7 @@ protected override void FillSearch(Uri context, string[] entityTypes, string sea try { OperationContext currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Search, searchPattern, null, context, entityTypes, hierarchyNodeID, maxCount); + ValidateRuntimeSettings(currentContext); List entities = this.SearchOrValidate(currentContext); if (entities == null || entities.Count == 0) { return; } SPProviderHierarchyNode matchNode = null; @@ -523,6 +526,7 @@ protected override void FillResolve(Uri context, string[] entityTypes, SPClaim r if (!String.Equals(resolveInput.OriginalIssuer, this.OriginalIssuerName, StringComparison.InvariantCultureIgnoreCase)) { return; } OperationContext currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Validation, resolveInput.Value, resolveInput, context, entityTypes, null, 1); + ValidateRuntimeSettings(currentContext); List entities = this.SearchOrValidate(currentContext); if (entities?.Count == 1) { @@ -947,6 +951,10 @@ protected virtual string FormatPermissionDisplayText(LdapEntityProviderResult di } return entityDisplayText; } + + public virtual void ValidateRuntimeSettings(OperationContext operationContext) + { + } #endregion /// diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs index 2cda0bf..2038c5d 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs @@ -411,30 +411,42 @@ public override List SearchOrValidateEntities(Operatio return new List(0); } - string ldapFilter = this.BuildFilter(currentContext); + //string ldapFilter = this.BuildFilter(currentContext); List LdapSearchResult = null; SPSecurity.RunWithElevatedPrivileges(delegate () { - LdapSearchResult = this.QueryLDAPServers(currentContext, ldapFilter); + LdapSearchResult = this.QueryLDAPServers(currentContext); }); return LdapSearchResult; } - protected string BuildFilter(OperationContext currentContext) + protected string BuildFilter(List claimTypeConfigList, string inputText, bool exactSearch, DirectoryConnection ldapConnection) { + if (ldapConnection != null && String.IsNullOrWhiteSpace(ldapConnection.CustomFilter)) + { // In this case, the generic LDAP filter can be used + return String.Empty; + } + StringBuilder filter = new StringBuilder(); if (this.Settings.FilterEnabledUsersOnly) { filter.Append(ClaimsProviderConstants.LDAPFilterEnabledUsersOnly); } + + // A LDAP connection may have a custom filter + if (!String.IsNullOrWhiteSpace(ldapConnection?.CustomFilter)) + { + filter.Append(ldapConnection.CustomFilter); + } + filter.Append("(| "); // START OR // Fix bug https://github.com/Yvand/LDAPCP/issues/53 by escaping special characters with their hex representation as documented in https://ldap.com/ldap-filters/ - string input = Utils.EscapeSpecialCharacters(currentContext.Input); + string input = Utils.EscapeSpecialCharacters(inputText); - foreach (var ctConfig in currentContext.CurrentClaimTypeConfigList) + foreach (var ctConfig in claimTypeConfigList) { - filter.Append(AddLdapAttributeToFilter(currentContext, input, ctConfig)); + filter.Append(AddLdapAttributeToFilter(exactSearch, input, ctConfig)); } if (this.Settings.FilterEnabledUsersOnly) @@ -446,7 +458,7 @@ protected string BuildFilter(OperationContext currentContext) return filter.ToString(); } - protected string AddLdapAttributeToFilter(OperationContext currentContext, string input, ClaimTypeConfig attributeConfig) + protected string AddLdapAttributeToFilter(bool exactSearch, string input, ClaimTypeConfig attributeConfig) { // Prevent use of wildcard for LDAP attributes which do not support it if (String.Equals(attributeConfig.DirectoryObjectAttribute, "objectSid", StringComparison.InvariantCultureIgnoreCase)) @@ -460,7 +472,7 @@ protected string AddLdapAttributeToFilter(OperationContext currentContext, strin // Test if wildcard(s) should be added to the input string inputFormatted; - if (currentContext.ExactSearch || !attributeConfig.DirectoryObjectAttributeSupportsWildcard) + if (exactSearch || !attributeConfig.DirectoryObjectAttributeSupportsWildcard) { inputFormatted = input; } @@ -484,7 +496,7 @@ protected string AddLdapAttributeToFilter(OperationContext currentContext, strin return filter; } - protected List QueryLDAPServers(OperationContext currentContext, string ldapFilter) + protected List QueryLDAPServers(OperationContext currentContext) { if (this.Settings.LdapConnections == null || this.Settings.LdapConnections.Count == 0) { return null; } object lockResults = new object(); @@ -492,9 +504,15 @@ protected List QueryLDAPServers(OperationContext curre Stopwatch globalStopWatch = new Stopwatch(); globalStopWatch.Start(); + string ldapFilter = this.BuildFilter(currentContext.CurrentClaimTypeConfigList, currentContext.Input, currentContext.ExactSearch, null); //foreach (var ldapConnection in this.Settings.LdapConnections.Where(x => x.LdapEntry != null)) Parallel.ForEach(this.Settings.LdapConnections.Where(x => x.LdapEntry != null), ldapConnection => { + if (!String.IsNullOrWhiteSpace(ldapConnection.CustomFilter)) + { + // The LDAP filter needs to be entirely rewritten to include the filter specified in current connection + ldapFilter = this.BuildFilter(currentContext.CurrentClaimTypeConfigList, currentContext.Input, currentContext.ExactSearch, ldapConnection); + } Debug.WriteLine($"ldapConnection: Path: {ldapConnection.LdapEntry.Path}, UseDefaultADConnection: {ldapConnection.UseDefaultADConnection}"); Logger.LogDebug($"ldapConnection: Path: {ldapConnection.LdapEntry.Path}, UseDefaultADConnection: {ldapConnection.UseDefaultADConnection}"); using (DirectoryEntry directory = ldapConnection.LdapEntry) diff --git a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs index 86eb028..bfa59f2 100644 --- a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs +++ b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs @@ -1,4 +1,5 @@ -using Yvand.LdapClaimsProvider; +using System; +using Yvand.LdapClaimsProvider; using Yvand.LdapClaimsProvider.Configuration; namespace LDAPCPSE_basic @@ -25,5 +26,15 @@ public override ILdapProviderSettings GetSettings() settings.EntityDisplayTextPrefix = "(custom) "; return settings; } + + public override void ValidateRuntimeSettings(OperationContext operationContext) + { + Uri currentSite = operationContext.UriContext; + string currentUser = operationContext.UserInHttpContext?.Value; + if (currentSite.Port == 6000) + { + operationContext.LdapConnections[0].CustomFilter = "(telephoneNumber=00110011)"; + } + } } } From e83e1e6cce0f7dfcbd844ec9abf36aee2f5d290f Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Thu, 19 Sep 2024 11:31:02 +0200 Subject: [PATCH 08/10] work --- .../Yvand.LdapClaimsProvider/LdapEntityProvider.cs | 6 +++--- .../LDAPCPSE_basic/LDAPCPSE_Custom.cs | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs index 2038c5d..91d935d 100644 --- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs +++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs @@ -498,15 +498,15 @@ protected string AddLdapAttributeToFilter(bool exactSearch, string input, ClaimT protected List QueryLDAPServers(OperationContext currentContext) { - if (this.Settings.LdapConnections == null || this.Settings.LdapConnections.Count == 0) { return null; } + if (currentContext.LdapConnections == null || currentContext.LdapConnections.Count == 0) { return null; } object lockResults = new object(); List results = new List(); Stopwatch globalStopWatch = new Stopwatch(); globalStopWatch.Start(); string ldapFilter = this.BuildFilter(currentContext.CurrentClaimTypeConfigList, currentContext.Input, currentContext.ExactSearch, null); - //foreach (var ldapConnection in this.Settings.LdapConnections.Where(x => x.LdapEntry != null)) - Parallel.ForEach(this.Settings.LdapConnections.Where(x => x.LdapEntry != null), ldapConnection => + //foreach (var ldapConnection in currentContext.LdapConnections.Where(x => x.LdapEntry != null)) + Parallel.ForEach(currentContext.LdapConnections.Where(x => x.LdapEntry != null), ldapConnection => { if (!String.IsNullOrWhiteSpace(ldapConnection.CustomFilter)) { diff --git a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs index bfa59f2..76e5687 100644 --- a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs +++ b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs @@ -1,6 +1,8 @@ -using System; +using Microsoft.SharePoint.Administration; +using System; using Yvand.LdapClaimsProvider; using Yvand.LdapClaimsProvider.Configuration; +using Yvand.LdapClaimsProvider.Logging; namespace LDAPCPSE_basic { @@ -10,7 +12,7 @@ public class LDAPCPSE_Custom : LDAPCPSE /// Sets the name of the claims provider, also set in (Get-SPTrustedIdentityTokenIssuer).ClaimProviderName property /// public new const string ClaimsProviderName = "LDAPCPSE_Custom"; - + /// /// Do not remove or change this property /// @@ -31,8 +33,10 @@ public override void ValidateRuntimeSettings(OperationContext operationContext) { Uri currentSite = operationContext.UriContext; string currentUser = operationContext.UserInHttpContext?.Value; + Logger.Log($"New request with input {operationContext.Input} from URL {currentSite} and user {currentUser}", TraceSeverity.High, EventSeverity.Information, TraceCategory.Custom); if (currentSite.Port == 6000) { + Logger.Log($"Apply custom LDAP filter \"(telephoneNumber=00110011)\"", TraceSeverity.High, EventSeverity.Information, TraceCategory.Custom); operationContext.LdapConnections[0].CustomFilter = "(telephoneNumber=00110011)"; } } From b04ee5992496e4066f352dff17804521933479c1 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 15 Oct 2024 17:14:09 +0200 Subject: [PATCH 09/10] Update LDAPCPSE_Custom.cs --- .../LDAPCPSE_basic/LDAPCPSE_Custom.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs index 76e5687..7bd85f8 100644 --- a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs +++ b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs @@ -26,6 +26,7 @@ public override ILdapProviderSettings GetSettings() { ClaimsProviderSettings settings = ClaimsProviderSettings.GetDefaultSettings(ClaimsProviderName); settings.EntityDisplayTextPrefix = "(custom) "; + //settings.UserIdentifierClaimTypeConfig.DirectoryObjectAttributeForDisplayText = "displayName"; return settings; } @@ -34,11 +35,15 @@ public override void ValidateRuntimeSettings(OperationContext operationContext) Uri currentSite = operationContext.UriContext; string currentUser = operationContext.UserInHttpContext?.Value; Logger.Log($"New request with input {operationContext.Input} from URL {currentSite} and user {currentUser}", TraceSeverity.High, EventSeverity.Information, TraceCategory.Custom); - if (currentSite.Port == 6000) - { - Logger.Log($"Apply custom LDAP filter \"(telephoneNumber=00110011)\"", TraceSeverity.High, EventSeverity.Information, TraceCategory.Custom); - operationContext.LdapConnections[0].CustomFilter = "(telephoneNumber=00110011)"; - } + // Returns all groups, or only users members of group testLdapcpGroup_002 + string customFilter = "(|(objectClass=group)(memberOf=CN=testLdapcpGroup_002,OU=ldapcp,DC=contoso,DC=local))"; + customFilter = "(|(&(objectClass=group)(|(sAMAccountName=testLdapcpGroup_002)(sAMAccountName=testLdapcpGroup_003)))(memberOf=CN=testLdapcpGroup_002,OU=ldapcp,DC=contoso,DC=local))"; + operationContext.LdapConnections[0].CustomFilter = customFilter; + //if (currentSite.Port == 6000) + //{ + // operationContext.LdapConnections[0].CustomFilter = "(telephoneNumber=00110011)"; + //} + Logger.Log($"Apply custom LDAP filter \"{customFilter}\"", TraceSeverity.High, EventSeverity.Information, TraceCategory.Custom); } } } From f313572bec730ae8e4fb9ec4894753213366b334 Mon Sep 17 00:00:00 2001 From: Yvan Duhamel Date: Tue, 22 Oct 2024 09:31:56 +0200 Subject: [PATCH 10/10] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83c8a86..6aec0c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for LDAPCP +## LDAPCP Second Edition v20.0 - Unreleased + +* Add property CustomFilter to class DirectoryConnection, to allow setting a custom LDAP filter per LDAP connection +* Add sample custom claims provider LDAPCPSE_basic + ## LDAPCP Second Edition v19.0.20240823.4 - Published in August 23, 2024 * Fix error when creating the configuration if the trust uses an identifier claim type that is not well-known by LDAPCP - https://github.com/Yvand/LDAPCP/issues/221