This is a pretty unique scenario, but it came up recently and exposed a little-known configuration "gotcha" with SharePoint.
Consider the following scenario:
-
You have two Trusted Providers (SAML auth) and are using them both for the same web application.
- For example, you have an Internal zone using URL https://teamsInternal.contoso.com that uses Trusted Provider "ADFS-Internal"
- And an External zone using URL https://teams.contoso.com, and Trusted Provider "ADFS-External"
- You create both Trusted Identity Token Issuers using the same token signing certificate, creating the "ADFS-External" one first.
- When internal users browse to the site, they are authenticated, but receive the "Sorry, this site has not been shared with you" Access Denied page.
- In reviewing the ULS logs and /or a Fiddler trace, you see that the Internal user is indeed authenticated, but is authenticated as an External user, which does not have permission to the site, thus the "access denied".
Notes:
- I cannot come up with a practical scenario for using two separate providers instead of handling both user types with one trusted provider, but it has happened. More than once.
- Please forgive the references to SharePoint 2010 and ADFS 2.0 in the above link. The steps are still valid for the most recent version of both.
- I'll use "ADFS" as my Trusted Provider example, but the same rules apply to all SAML providers (SiteMinder, Ping Federate, Okta, etc).
That's weird, why does that happen?
Both the Internal ("ADFS-Internal") and External ("ADFS-External") Trusted Identity Token Issuers have been configured to use the same token signing certificate.
Because SharePoint uses the certificate it receives from ADFS to match the Trusted Identity Token Issuer within SharePoint, it will match that certificate to only the first Trusted Identity Token Issuer in the list that uses that same certificate.
In this case, the result is that it will always match the certificate to the "ADFS-External" Token Issuer because it was the first one created, and appears first in the list.
The result is that every user will be authenticated as an External user, even when accessing the site using the Internal URL.
You're saying the user is Authenticated. Why do they get Access Denied?
Most of this goes back to the concept of Authentication (who are you) vs Authorization (what permission do you have).
However, in SharePoint, I find it's even more easily confused because the same physical person can authenticate to SharePoint as multiple different "users".
Continuing with my example above, the same person can authenticate using the External URL with the "ADFS-External" trusted provider, and with the Internal URL with the "ADFS-Internal" trusted provider. SharePoint sees those two users as completely separate. Knowing that SharePoint uses the name of the Trusted Provider as part of the users account name, it should become clear why:
i:0e.t|adfs-internal|josh@joroar.local is not the same user as i:0e.t|adfs-external|josh@joroar.local
Those two user accounts will always be treated by SharePoint as separate. There's no way to "merge" their permission sets, or anything of the like.
This concept is really just a variation on one I blogged about previously: https://blogs.technet.microsoft.com/spjr/2018/07/24/sharepoint-windows-user-not-equal-to-adfs-user/
How can I tell if I have this issue?
You should be able to run the following PowerShell to check which certificate each Trusted Identity Token Issuer is using:
Get-SPTrustedIdentityTokenIssuer | select name, signingcertificate | fl
Check the "Thumbprint" value on the SigningCertificate for both Token Issuers. If it's the same value, it's the same certificate.
What can be done?
If you're set on using two different Trusted Providers within the same web application, then one of them must use a different token signing certificate. How you do that on the SAML provider side varies by implementation (ADFS, SiteMinder, Ping, OKTA, etc), so I won't get into that here.
However, once you have a new token-signing certificate, updating SharePoint to match is quite simple. It's the same steps you would use when your token signing certificate expires and you need to update SharePoint to use a new one.
The example below assumes I got a new certificate for the "Internal" trusted provider, and I'm leaving the External one alone.
-- Update the Internal Token Issuer to use the new certificate using PowerShell:
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("C:newInternalCert.cer")
$ti = Get-SPTrustedIdentityTokenIssuer "ADFS-Internal"
Set-SPTrustedIdentityTokenIssuer $ti -ImportTrustCertificate $cert
-- Add the new certificate to the farm trust (Central Admin | Security | Manage Trust).
-- Make sure it's trusted at the Windows level by importing it (and any parent certificates in the cert chain) to the Trusted Root Authorities certificate store on the SharePoint servers.