I have a colleague who wrote a Custom Claim Provider for a SharePoint deployment which uses ADFS as its authentication provider. The goal of the custom claim provider was to ensure that the people picker would resolve things by searching our Active Directory. One of the other things we were working on was to set permissions on certain sites from within .NET code. Online we found several ways to get this task done, but my colleague kept running into an ArgumentException error.
I tried to simulate what he was doing in PowerShell. Our troubleshooting would benefit from this as a typical refresh of the custom code on SharePoint takes several minutes. One thing we quickly found out that it was working for a claim type we’ve had available in SharePoint and which was also specified in the claims provider. However lately we registered a new claim type in SharePoint, and for some reason this was not being accepted. Here’s how we registered it:
From a SharePoint PowerShell prompt:
- $claimType = http://schemas.customer.com/claims/entity
- $claimTypeSPS = "Entity"
- $ti = Get-SPTrustedIdentityTokenIssuer "Cust ADFS Provider"
- $ti.ClaimTypes.Add($claimType)
- $ti.Update()
- $map = New-SPClaimTypeMapping –IncomingClaimType "$claimType" –IncomingClaimTypeDisplayName "$claimTypeSPS" –SameAsIncoming
- Add-SPClaimTypeMapping –Identity $map –TrustedIdentityTokenIssuer $ti
Typically this should be enough to start using the claim type “Entity” in SharePoint. However when we executed the following lines:
- $mgr = Get-SPClaimProviderManager
- $tp = Get-SPTrustedIdentityTokenIssuer -Identity "Cust ADFS Provider"
- $cp = Get-SPClaimProvider -Identity "ADFSClaimsProvider"
- $claim = New-SPClaimsPrincipal -ClaimValue "readPermission" -ClaimType http://schemas.customer.com/claims/technicalrole -TrustedIdentityTokenIssuer $tp
- $mgr.EncodeClaim($claim)
We stumbled upon this error:
In words: Exception calling "EncodeClaim" with "1" argument(s): "Exception of type 'System.ArgumentException' was thrown.
Parameter name: claimType"
At line:1 char:194
+ $claim = New-SPClaimsPrincipal -ClaimValue "readPermission" -ClaimType "http://schemas.customer.com/claims/entity" -TrustedIdentity
TokenIssuer $tp -IdentifierClaim:$false;$mgr.EncodeClaim <<<< ($claim)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
So we started digging into it. Long story short, as far as we can tell, from the moment you specify a custom claim provider on your Security Token Issuer, you must include all claims of the security token issuer in the custom claim provider. You can easily check which claim types are currently visible to SharePoint by executing the following lines:
- $cp = Get-SPClaimProvider -Identity "ADFSClaimsProvider"
- $cp.ClaimProvider.ClaimTypes()
Remark:
- Don’t confuse the Get-SPTrustedIdentityTokenIssuer and the Get-SPClaimProvider.
- Often the name of the custom claim provider is the same as it’s proper name, but without spaces. This property is also called the internal name.
Here’s a screenshot, I could clearly see that Entity was not included:
And here’s a small code snippet:
Now after adding the claim type in the code, and redeploying the necessary assemblies, things still didn’t work. As far as we can tell the following actions are also required:
- Restart your SharePoint PowerShell shell
- Run the Update() method on the Claim Provider Manager ($mgr = Get-SPClaimProviderManager and $mgr.Update() )
And now we can see that we can successfully encode the claim:
Conclusion #1: whenever you write a custom claim provider, make sure to include all the claim types you want to use for that Token Issuer. It doesn’t matter whether you only want to add them programmatically or if you want them to be available for regular users through the graphical interface.
However, after this we were still having issues. We were trying to add the encoded claim as a member of a SharePoint group. This would allow people having the specified claim to access the site we are securing. Here’s the command we executed:
- $tp = Get-SPTrustedIdentityTokenIssuer -Identity "Cust ADFS Provider"
- $url = https://sharepoint.customer.com
- $group = "Visitors"
- $claimType = http://schemas.customer.com/claims/entity
- $claimValue = "DepartmentX"
- $web = Get-SPWeb $url
- $SPgroup = $web.SiteGroups["$group"]
- $principal = New-SPClaimsPrincipal -ClaimValue $claimValue -ClaimType $claimType -TrustedIdentityTokenIssuer $tp
- $SPprincipal = New-SPUser -UserAlias $principal.ToEncodedString() -Web $web
- $SPgroup.AddUser($SPprincipal)
So we are still having issues with the claim types we added. The error makes me suspect the resolving capabilities of the custom claim provider. After some googling I finally found this post: Adding users and claims to a site from PowerShell Here’s the relevant part:
Conclusion #2: whenever you write a custom claim provider, make sure to provide fillResolve capabilities for your custom claim types. I don’t think you are obliged to add them to the fillResolve method which takes a string as value to resolve, but you have to add them to the fillResolve method which takes an SPclaim as value to resolve. You can then simply put an if statement to auto-resolve everything of the claimtypes you don’t want to be looked up.
you can add this in the protected override void FillResolve(Uri context, string[] entityTypes, SPClaim resolveInput, List<Microsoft.SharePoint.WebControls.PickerEntity> resolved) method
if (resolveInput.ClaimType == CustClaimType.Entity)
{
resolved.Add(GetPickerEntity(resolveInput.Value, resolveInput.Value, resolveInput.ClaimType));
return;
}
Some more background reading:
No Response to "SharePoint: EncodeClaim: ArgumentException for claimType"
Add Your Comment