Thursday, April 10, 2014

Create a Provider Hosted App (High-trust) for SharePoint

SharePoint 2013 introduced the SharePoint App model for developers. Out of the three app models, SharePoint Hosted, Auto Hosted and Provider Hosted I’m creating and explaining the step by step approach to develop a simple Provider Hosted (High-trust) app in this post. This is not an introduction to SharePoint App model but an introduction to Provider Hosted (PH) Apps.

Diagram below denote my dev environment.

One VM for AD and DNS and the second VM hosts SharePoint 2013 and SQL 2012.

There are two types of PH Apps. Apps that can be hosted in Office 365 environments and the PH Apps that can be only hosted in On-Premises environments which are also called as High-trust apps.

Provider Hosted app consists of an App deployed in to SharePoint and a separately deployed web application. In a production environment the web application is normally deployed in a separate server or a separate server farm.

The reason why high-trust apps are only compatible with On-Premises environments is, it uses a certificate instead of a context token (OAuth) to make the trust between the two servers. So these apps require some sort of configuration on the SharePoint server as well as the remote server hosting the web application. SharePoint includes server-to-server security token service (STS) which provides access tokens for server-to-server authentication. The server-to-server STS enables temporary access tokens to access other application services including apps for SharePoint 2013. To establish a trust relationship between the SP Server and App we use a X.509 certificate and a few PowerShell cmdlets.

We need to create a .pfx file and a corresponding .cer file. First file which is the pfx, contains the private key which will be used by the remote web application to encrypt it’s communication to SharePoint server. The .cer file contains the public key which will be used by SharePoint server to decrypt the messages and to verify those messages come from the same remote web application. Also to verify that the remote web application has an access token from a token issuer that SharePoint trusts which in this case the certificate.

For the demonstration purposes I will use a self signed certificate instead of a certificate issued by a certificate authority.

Create and export a Test Certificate

Open IIS Manager in the SharePoint server and select server certificates.  
Screen Shot 2014-04-10 at 10.41.20 AM 

Click Create a self-signed certificate.
Screen Shot 2014-04-10 at 10.45.05 AM

Name the certificate. Mine is ProviderHostedHighTrust.
Screen Shot 2014-04-10 at 10.48.05 AM

As the next step, right click the certificate created, export it to a folder providing a password. It will create a file with a pfx extension.
Screen Shot 2014-04-10 at 11.05.02 AM

If your dev environment is not similar to mine and if you have a separate server to host the remote web application, please move the pfx file to the same.

Create the .cer file

Go to IIS Manager and open Server Certificates.
Screen Shot 2014-04-10 at 11.46.31 AM
On the details tab, click Copy to file, where it opens the certificate export wizard. Click next and move forward with the default option, “No, Do not export the private key”.
Screen Shot 2014-04-10 at 11.50.17 AM

Click next with default options and save the certificate.
Screen Shot 2014-04-10 at 11.54.50 AM Screen Shot 2014-04-10 at 11.55.56 AM Now we are done with certification creation & exporting part. But we have to make sure STS application pool identity as well as SharePoint Web Application; application pool identity have read permission to the location of the .cer file.

Configure SharePoint 2013 Server to use the Certificate and trust the App hosted in Remote Server.

What I have explained below is suited for a dev environment and NOT for a Production nor a staging server.
In the SharePoint Server, open the SharePoint 2013 Management Shell with Run as Administrator. Execute the cmdlets below.

Create a certificate Object

$publickeyPath = “C:\Certificates\ProviderHostedHighTrust.cer”

$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($publickeyPath)

Ensure that SharePoint treats the certificate as a root authority

New-SPTrustedRootAuthority -Name "ProviderHostedHighTrust" -Certificate $certificate

Screen Shot 2014-04-10 at 3.09.30 PM 
Get the ID of the authorization realm.

$realm = Get-SPAuthenticationRealm

To access data in SharePoint, my remote web application needs a access token, which is issued by a token issuer that SharePoint trusts.  As I’ve mentioned above the certificate is the token issuer.

Next step is a very important. If we look in to a production environment, each certificate is issued by a unique issuer which is represented by a GUID. A limitation of SharePoint, make sure any letters in GUID must be lower case.  But in my dev environment I’m using the same certificate for all Provider hosted high-trust app.

$specificIssuerId = "d250d0bc-d44e-4d8b-9e36-567817943628"

$fullIssuerIdentifier = $specificIssuerId + '@' + $realm

Now is the time to make the certificate a trusted token issuer.

New-SPTrustedSecurityTokenIssuer -Name "High Trust Demo Certificate" -Certificate $certificate -RegisteredIssuerName $fullIssuerIdentifier –IsTrustBroker

In the above cmdlet I have used a friendly name which is not a common scenario in a production environment. The reason is, name parameter must be unique, so its better to add a GUID as part of the name. You will see an output similar to below screen.

Screen Shot 2014-04-10 at 4.09.12 PM

Next do an iisreset command to register the token issuer immediately.

In a dev environment we have another issue to be solved. SharePoint does NOT accept self-signed certificates. So we need to turn off SharePoint's normal requirement that HTTPS be used when remote web applications call into SharePoint or else you will see a 403(forbidden) message. Turning off HTTPS is not recommended as form there onwards all traffic from the Remote Web Application to SharePoint wont be encrypted. But with a self-signed certificate that’s the only option for now.

Allowing OAuth over HTTP

$serviceConfig = Get-SPSecurityTokenServiceConfig

$serviceConfig.AllowOAuthOverHttp = $true


OK, Lets build the App in Visual Studio. I’m on VS 2013. You can use VS 2012 as well.

Screen Shot 2014-04-10 at 5.08.29 PM

Select “provider hosted” and provide a URL for debug purposes. For the remote web application I have selected Web Forms, if your prefer MVC, feel free to go ahead. Next comes the “Configure Authentication” screen. Select “use a certificate”. Values you provide here will be written to the Web.Config of the remote web application.

For the certificate location, browse and select the .pfx file you created in a previous step. Provide the password. And the issuer id is the GUID with lowercase letters. Mine is d250d0bc-d44e-4d8b-9e36-567817943628.

Screen Shot 2014-04-10 at 5.30.22 PM

Click finish and VS creates two projects for you. One, the App which will deployed to SharePoint and the second, the remote web application. You do not have to write any code, as the template have some code already in the Default.aspx.cs. But I added one more line. :)

Screen Shot 2014-04-10 at 5.58.48 PM

Good luck. Hit F5. It' asks you to Trust the app. Go ahead and trust it. Hurray!! If you followed me properly, you should get a screen similar to below.

Screen Shot 2014-04-10 at 6.03.25 PM

As you can see, below are the information written to the Web.Config file.


add key="ClientId" value="307490ca-d53b-4dcf-81d4-e7c4bdffb384" />

add key="ClientSigningCertificatePath" value="C:\Certificates\ProviderHostedHighTrust.pfx" />

add key="ClientSigningCertificatePassword" value="password" />

add key="IssuerId" value="d250d0bc-d44e-4d8b-9e36-567817943628" />


What you need to remember at this point is, still we are on a self-signed certificate and HTTP instead of HTTPS. So still you test your app with a domain signed or commercial certificate on HTTPS, your app is not ready for release. I’ll discuss more on domain signed certificates on another blog post.