SharePoint SSRS reports access denied after UPN suffix change

Symptoms:

Ok Picture this….You have a two-way external trust configured with corp.contoso.com and resource.farbrikam.com.  This trust allows all users to authenticate.  You also have a SharePoint 2010, 2013, or 2016 farm with SSRS and a web application configured to use Kerberos.  For argument sake we’ll state that the Kerberos authentication and Delegation is configured correctly and everything works.  We have preconfigured SSRS reports with the data sources set to use windows integrated authentication.

User, corp\UserA, has been accessing the reports without issues for some time now. This higher ups have decided to change the UPN for Corp\UserA from corp.contoso.com to SomeUPN.com. Ever since this UPN change our user, or any user who had their UPN changed in the Corp.Contoso.com domain, can no longer access the SSRS report.  The user can log into the SharePoint site without issues but can’t access the SSRS reports any more. After the UPN change we now receive the following error:

Error : Could not retrieve a valid windows identity for username ‘Corp\UserA’ with UPN ‘UserA@SomeUPN.com’. UPN is required when Kerberos constrained delegation is used. Exception: System.ServiceModel.Security.SecurityAccessDeniedException: Access is denied.

Why are we all of a sudden getting access denied??

Cause:

Well it is pretty obvious the UPN change is the issue, but why?

SSRS configuration relies upon the Claims to Windows Token Service to take their claims token and create a windows token to pass to SSRS as SSRS doesn’t understand claims.

So now how do we troubleshoot this to find out if the issue with the UPN change is with SharePoint?

Let’s take this Kerberos authentication outside of SharePoint and Claims To Windows Token Service

Rodney Viana has compiled a nice console application that takes this whole process outside of SharePoint

You can download this here:

https://rodneyviana.codeplex.com/downloads/get/816717

We simply run that on a WFE and put in the users UPN and it’ll work or it won’t.

When it works:

When it doesn’t work:

Ok great so we know that the issue is not with SharePoint.

So where is the issue at?

Well we know we are dealing with cross forest Kerberos authentication so the only other piece here would be the trust configuration.

So we take a look at the trusts configured with PowerShell:

 $myLocalDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
 $Trusts = $myLocalDomain.GetAllTrustRelationships()
 ForEach ($trust in $Trusts) 
 {
     Write-Host "SourceName:`t$($trust.SourceName)" -ForegroundColor Green
     Write-Host "TargetName:`t$($trust.TargetName)" -ForegroundColor Green
     Write-Host "TrustType:`t$($trust.TrustType)" -ForegroundColor Green
     Write-Host "TrustDirection:`t$($trust.TrustDirection)" -ForegroundColor Green
     Write-Host "Selective Authentication:`t$($myLocalDomain.GetSelectiveAuthenticationStatus($trust.TargetName))" -ForegroundColor Green
     Write-Host "SidFiltering:`t$($myLocalDomain.GetSidFilteringStatus($trust.TargetName))" -ForegroundColor Green
 }
 
Sample output:
 SourceName:        Corp.Contoso.com
 TargetName:        Resource.Fabrikam.com
 TrustType:        External
 TrustDirection:        Bidirectional
 Selective Authentication:        False
 SidFiltering:        True 

When we add an alternate UPN suffix to our domain this is called an explicit UPN suffix. Let me explain..

We have two kinds of UPN suffix’s:

  1. Implicit
    1. Default UPN created with the domain and contains a mapping with DNS
    2. Example:
      1. Domain: Corp.Contoso.com
      2. Implicit UPN: Corp.Contoso.com
  2. Explicit
    1. An Alternate UPN that will require UPN Suffix Routing for cross forest authentication
    2. Example:
      1. Domain: Corp.Contoso.com
      2. Explicit, or alternate, UPN: SomeOtherUPN.com

So now we know we are dealing with an Explicit UPN, which requires UPN Suffix Routing.

Ok sweet let’s set up that routing and be done with it right???

Wrong!!!

I wish it were that simple 🙂

In order to use UPN Suffix Routing we will need a Forest Trust not an External Trust.

Which means we’ll have to change our trust configuration

https://technet.microsoft.com/en-us/library/dd560679(v=ws.10).aspx

Resolution:

  1. Change the trust to a Forest trust from an External trust
    1. Enable UPN Suffix Routing

When you configure the forest trust you get to select all the alternate UPN Suffix’s you’d like routed

If the Explicit UPN was added after the trust was configured you’ll enable the Suffix routing in Domains and Trusts under the properties for your trust

If the trust can’t\won’t be changed then…..

  1. Change the UPN  back to the Implicit UPN
  2. Change how you are authenticating to the Data Source

IF option 3 is the way we are going we can use stored credentials to access the data source.

So that not everyone has access to all the reports because we’re using stored credentials we can use SharePoint’s security to control access to the reports regardless of how that report connects to its data source.

Or we can prompt for credentials, which most end users will hate.

Scripts:

Domain trusts out-put to file:

 param ( [String]$OutputFile
 )
 $myLocalDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
 $Trusts = $myLocalDomain.GetAllTrustRelationships()
 #Checking for Selective Authentication
 ForEach ($trust in $Trusts) {
 Write-OutPut "SourceName:`t$($trust.SourceName)"
 Write-OutPut "TargetName:`t$($trust.TargetName)"
 Write-OutPut "TrustType:`t$($trust.TrustType)"
 Write-OutPut "TrustDirection:`t$($trust.TrustDirection)"
 Write-OutPut "Selective Authentication:`t$($myLocalDomain.GetSelectiveAuthenticationStatus($trust.TargetName))"
 Write-OutPut "SidFiltering:`t$($myLocalDomain.GetSidFilteringStatus($trust.TargetName))"
 } 

Check Delegation to confirm Kerberos configuration

For a single account:

Get-ADObject -fi {(samAccountName -eq 'svcspapppool')} -prop samAccountName,msDS-AllowedToDelegateTo,servicePrincipalName,userAccountControl
| select DistinguishedName,ObjectClass,samAccountName,servicePrincipalName,
@{name='DelegationStatus';expression={if($_.UserAccountControl -band 0x80000){'AllServices'}else{'SpecificServices'}}}, @{name='AllowedProtocols';expression={if($_.UserAccountControl -band 0x1000000){'Any'}else{'Kerberos'}}}, @{name='DestinationServices';expression={$_.'msDS-AllowedToDelegateTo'}} 

More Information:

Great article that dives into C2WTS (also provides the resolution to the case in reason #1)