Creating Provider Hosted Apps for SharePoint 2013 when your IIS server and SharePoint Servers are in different (non-trusted) domains
I had a customer that wanted to do high trust apps for SharePoint 2013. However, their developer machines were in a different domain than their web servers. TokenHelper is designed to work with either Azure ACS or SharePoint/IIS servers in a Windows domain. After digging into the TokenHelper class that comes with your "”Apps for SharePoint 2013” Visual Studio project, I figured out a way to make this work.
The public method GetS2SClientContextWithWindowsIdentity calls the private method GetClaimsWithWindowsIdentity:
private static JsonWebTokenClaim[] GetClaimsWithWindowsIdentity(WindowsIdentity identity)
{
JsonWebTokenClaim[] claims = new JsonWebTokenClaim[]
{
new JsonWebTokenClaim(TokenHelper.NameIdentifierClaimType, identity.User.Value.ToLower()),
new JsonWebTokenClaim("nii", "urn:office:idp:activedirectory")
};
return claims;
}
If you look at the value of identity.User.Value.ToLower(), it turns out that that is a Windows SID. To make this work without a domain, you will have to get the SID of a user from your SharePoint server. You do that via PsGetSID from SysInternals or write a little PowerShell do it (see https://powershellers.blogspot.com/2009/06/how-to-get-computer-sid-using.html).
I extended TokenHelper via extension methods. I don’t like to change generated code in case it gets changed later (although I did have to mark the TokenHelper class partial).
Here is the code that I created so that you can pass a SID:
public partial class TokenHelper
{
public static ClientContext GetS2SClientContextWithWindowsSID(
Uri targetApplicationUri,
string sid)
{
string realm = string.IsNullOrEmpty(Realm) ? GetRealmFromTargetUrl(targetApplicationUri) : Realm;
JsonWebTokenClaim[] claims = GetClaimsWithWindowsSID(sid);
string accessToken = GetS2SAccessTokenWithClaims(targetApplicationUri.Authority, realm, claims);
return GetClientContextWithAccessToken(targetApplicationUri.ToString(), accessToken);
}
public static string GetS2SAccessTokenWithWindowsSID(
Uri targetApplicationUri,
string sid)
{
string realm = string.IsNullOrEmpty(Realm) ? GetRealmFromTargetUrl(targetApplicationUri) : Realm;
JsonWebTokenClaim[] claims = GetClaimsWithWindowsSID(sid);
return GetS2SAccessTokenWithClaims(targetApplicationUri.Authority, realm, claims);
}
private static JsonWebTokenClaim[] GetClaimsWithWindowsSID(string sid)
{
JsonWebTokenClaim[] claims = new JsonWebTokenClaim[]
{
new JsonWebTokenClaim(TokenHelper.NameIdentifierClaimType, sid),
new JsonWebTokenClaim("nii", "urn:office:idp:activedirectory")
};
return claims;
}
}
To call this from your app, do this:
TokenHelper.TrustAllCertificates();
var sharepointUrl = new Uri(Request.QueryString["SPHostUrl"]);
string sid = ""; //replace this
var clientContext = TokenHelper.GetS2SClientContextWithWindowsSID(sharepointUrl, sid);
A full explanation of the TokenHelper class is beyond the scope of this post but you might find this article helpful: https://msdn.microsoft.com/en-us/library/fp179901.aspx.