Even More “Things to Do When you Change the SharePoint STS Token Signing Certificate”

I recently changed the token signing certificate in my farm…it having expired from when I first changed it, since that is required to set up the trust with ACS in SharePoint Online for low trust apps and SharePoint hybrid features.  Assume the longer the sentence the more unhappy I am about having to do it…  🙂

Well, of course as luck would have it once I finished all that up, all of my low trust and high trust apps broke.  I expected my high trust apps to break, since I’ve blogged about this before.  I wasn’t really expecting the full breakdown of my low trust apps as well though, even though I’ve also had to blog about that scenario before as well:  https://samlman.wordpress.com/2015/03/02/updating-trust-between-onprem-farms-and-acs-for-apps-when-your-sharepoint-sts-token-signing-certificate-expires/.

Unfortunately, even using the tips in the previous blog post above did not fully solve my problems.  Amazingly, I was getting 401 Unauthorized errors in my low trust apps, which I traced back to a “certificate is not from a trusted root authority” in the ULS logs.  This is one of my favorite errors with the app model (ridiculously heavy sarcasm here), since they are so routinely generic and difficult to resolve.  Not only that, but the error is a little looney tunes in this scenario if you ask me.  What certificate is not trusted, and by whom?  Does my local SharePoint farm not trust it’s own SharePoint STS token signing cert?  That seems rather impossible.  Does it not trust the Microsoft SharePoint Online ACS certificate?  Equally illogical.  Does SharePoint Online ACS not trust my local farm’s STS token signing cert?  Seems like the only possible scenario.  Without going through a bunch of boring PowerShell I will just say that I ran the code (for a second and then third time) to create a New-MsolServicePrincipalCredential, without success.

Finally, I just ran the Connect-SPFarmToAAD cmdlet again, but this time with every possible “Remove*” option it offers:  -RemoveExistingACS -RemoveExistingSTS -RemoveExistingSPOProxy -RemoveExistingAADCredentials.  After doing that and trying my low trust application again, it started working.  Yay.  Yet another Apps for SharePoint tip to keep handy.

Changes To Know About When Your SharePoint STS Token Signing Certificate Expires – the Impact to Your High Trust Applications

This is a another follow up to my earlier post on changing the token signing certificate for the SharePoint STS as described here:  http://blogs.technet.com/b/speschka/archive/2014/05/06/updating-trust-between-onprem-farms-and-acs-for-apps-when-your-sharepoint-sts-token-signing-certificate-expires.aspx.  As I mentioned in that post, you will undoubtedly wind up in this situation if you configure your farm to use low trust apps, because as part of creating the trust with ACS you need to change the STS’ token signing certificate.  As part of that process, one of the side effects is that it changes the realm associated with your SharePoint farm.  The reason why that’s important to you as it relates to high trust apps is that the farm’s realm is part of the identifier used with the SPSecurityTokenIssuer used for high trust apps, as well as the identifier for individual apps.  For example, here’s what the identifier looks like for one of my SPTrustedSecurityTokenIsssuers:

9e000da5-800a-4f60-a855-057f5bf1d8ff@c98f41a0-e9d7-4d31-9ac4-813b81680177

The first part of the identifier (before the @sign) is the issuer ID for it; the part after the @sign is the realm for the farm.  The impact of this is that all of your high trust apps will no longer work after you change the token signing certificate for your farm’s STS.  The work-around to get things going is as follows:

  1. Delete your existing SPTrustedSecurityTokenIssuers (that you created, where you are using a certificate for the token issuer).  Use the Remove-SPTrustedSecurityTokenIssuer cmdlet.
  2. Re-create your SPTrustedSecurityTokenIssuers; you can use the same certificate and the same issuer ID as you had originally.  Use the New-SPTrustedSecurityTokenIssuer cmdlet.
  3. Re-create the client ID / application ID / App ID (these terms mean the same thing but are used fairly interchangeably) for each high trust app.  For example, go to the sites where you are using your apps, use appregnew.aspx to create a new App ID, then update your application to use the new App ID.

Once you do these steps your high trust applications should start working again.

SAML Support for SharePoint-Hosted Apps with ADFS 3.0

This is another case where I’m just passing information along here, based on the great work of others.  As you probably know, we did not have a good story for SharePoint-hosted apps in web application that uses SAML authentication with ADFS 2.0.  However, I have had reports from a couple of different teams now that they ARE working with ADFS 3.0.  The main differences that are needed to make this work include:

  • In ADFS you need to define a wildcard WS-Fed endpoint.  For example, normally for a SharePoint web application, in ADFS you create a relying party and set the WS-Fed endpoint to be something like https://www.foo.com/_trust/.  To do the same thing with apps, you take your apps namespace – assume it’s “contosoapps.com” – and add a WS-Fed endpoint like this:  https://*.contosoapps.com/_trust/.
  • Configure the SharePoint STS to send the wreply parameter.  You can do that with PowerShell that looks like this:

$sts = Get-SPTrustedIdentityTokenIssuer
$sts.UseWReplyParameter = $true
$sts.Update() 

One other thing to note – the behavior to use the wreply parameter is supposed to be turned on by default in an upcoming CU.  I heard it was the April 2014 CU actually but have not had a chance to see if that is really in there or not.  It won’t hurt to run the PowerShell above though.

This is good news, thanks for those of you that shared your experiences!

Debugging SharePoint Apps That Are Hosted In Windows Azure Web Sites

Today, I’m going to be the lazy human I’m so frequently accused of being by my somewhat faithful dog Shasta, and bring together two posts written by two other folks into one uber “ain’t it cool how this all works together post” by me.  Here are the two concepts we’re combining today:

Now, once our SharePoint App has been published to a Windows Azure web site, the error prone and/or forward-thinking amongst you may be wondering…um, great…so what do I do to track down bugs?  Well that’s where the second piece of brilliant advice that I had nothing to do with comes in.

Now, let’s briefly walk through the steps to combine these two nuggets of goodness:

  1. Create a SharePoint provider hosted app and verify that it works.
  2. Create an Azure web site and download publishing profile. (in Vesa’s video)
  3. Use appregnew.aspx to get a client ID and client secret. (in Vesa’s video)
  4. Publish the App to your Windows Azure site using the publishing profile, client ID and client secret retrieved in the previous steps. (in Vesa’s video)
  5. Create the app package, install it to your app catalog, and add it to your site. (in Vesa’s video)
  6. Open Server Explorer in Visual Studio 2013, right-click on the Windows Azure node and select Connect to Windows Azure…
  7. Expand to see all the Azure services, and then expand the collection of Web Sites.
  8. Right-click on the Azure web site where you published your provider-hosted app and select Attach Debugger.
  9. The browser opens to your Azure web site, and VS.NET starts up in debugging mode.  Set your breakpoints in your code and start debugging!

See the remotely debugging Azure web sites post for the details on pre-requisites, but in short you need Visual Studio 2013 and the Azure 2.2 SDK for VS 2013; you will find a link to that in the blog post. (NOTE:  that same post also describes how to do this with Visual Studio 2012 but I have not tried that)  This actually works pretty great and I was able to get a first-hand experience using it when I went through the steps for this blog post.  As it turns out, the SharePoint site where I installed my sample application uses the Url https://sps2.  Well, the problem of course is that in my Azure Web site, my code was trying to make a CSOM call to an endpoint at “sps2”.  That works great when I’m in my lab environment, but out in the interwebs that Azure lives in of course it cannot resolve to a simple NetBIOS name (remember, this code is running server side, not client side).  So as a result it was blowing up.  By using this cool new debugging feature I was able to find my issue, appropriately for this debugging post.  Here’s a screenshot of it in action:

 

Another 401 Unauthorized Tip for Working with SharePoint Apps

I’ve tried to update the related postings to this, but sometimes you need a call out to make sure it catches your attention so…here’s another troubleshooting tip for when you get a 401 unauthorized error when your app tries to access SharePoint content.  Suppose you have gotten everything working and then create a provider hosted app hosted in IIS instead of IIS Express (see here for more details on this process:  http://blogs.technet.com/b/speschka/archive/2013/06/12/converting-a-vs-net-web-for-a-provider-hosted-sharepoint-app-to-a-full-blown-web-or-console-application.aspx).  Despite that, when the code runs in your app you get access denied again.  Here’s the tip – set a breakpoint in TokenHelper.cs in the GetClaimsWithWindowsIdentity method, and then look at the identity.User.Value.  If you see a very short SID value, like S-1-5-17, then that probably means it’s the anonymous account for IIS.  The SID for a “real” user is much longer, something like S-1-5-21-1644491937-1935655697-1957994488-2138.  Remember that the way OAuth works (in the most common case with SharePoint Apps) is that it checks to make sure BOTH the app AND the user have rights to the content.  In most cases the anonymous user account will not have rights, and so you will get an access denied error message.  To fix this you need to go into IIS and find your provider hosted app, then disable Anonymous access and enable Windows authentication.  I recommend restarting the IIS virtual server for your hosted app, then try again.

Converting a VS.NET Web for a Provider Hosted SharePoint App to a Full Blown Web or Console Application

This post is yet another in my series of “how long of a post title I can come up with and still not convey the actual essence of the post” contest.  I’m sure you’ve all been following along at home and are thrilled to see another entry, but it was either this or create a title with like 63 words in it.  So…the point of this post is to take you through the typical development scenario for a SharePoint App – you open up Visual Studio 2012, you create a new SharePoint App project, and you configure it to be provider hosted using high trust (i.e. a certificate).  Now you have this SharePoint App, which is great, but you also have this little application web that VS.NET created for you and that uses a local IIS Express instance.  That’s actually also great to get you started and running, but of course you are going to have to move away from that as you go into QA and production (and honestly many times even in dev – in fact I almost always do this even in dev).  The process can be a little wonky to get down so I thought I’d document the steps for doing so.  I’m also going to show you how to make it work with a console application as well, because that can be a super useful scenario for doing things like timer jobs, etc. (perhaps the source of another post in the future…we’ll see, I’ve got kind of a cool solution going here).

So, how do we get from IIS Express to a SharePoint App as a full blown ASP.NET or console application?  Well, here goes:

  1. Create your application using the Visual Studio wizard.  It creates the SharePoint App as well as web application project that uses IIS Express.  From this point forward this web application project that VS.NET creates shall be referred to as the “original web app”.  Verify that everything is working correctly.
  2. Create your new application you are going to use – a web project or a console project.  Remember to use SSL if creating a web project.
  3. Copy the configuration information from the original web app; for:
    1. Web Project – copy the items in the <appSettings> of web.config to web.config of your new web project.
    2. Console App – Go into the Properties of the application, click on the Settings link on the left, then click on the link in the middle of the page that says “This project does not contain a default settings file.  Click here to create one.”  Create properties for each of the appSetting properties – copy in both the key (as the setting Name) and value (as the setting Value).  Make sure you make each setting an Application scope property (it is User by default).
  4. Create an App_Code folder and copy into it the TokenHelper.cs file from the original web project.  For a console application you can just create a new folder; for an ASP.NET application you should use the Add…Add ASP.NET Folder…App_Code menu option.
  5. Remove the “namespace” declaration from the TokenHelper.cs file.
  6. Add references so your application will compile; the exact ones will vary slighlty between an ASP.NET and console application, but here is a complete list so just make sure whichever application type you choose, you have all of these references:
    1. Microsoft.SharePoint.Client
    2. Microsoft.SharePoint.Client.Runtime
    3. Microsoft.IdentityModel
    4. Microsoft.IdentityModel.Extensions
    5. System.ServiceModel
    6. System.Web
    7. System.Web.Extensions
    8. System.IdentityModel

At this point, the steps diverge depending on what type of project you created.  If you created a web project:

  1. Create a default.aspx page (if you did not already – this assumes you are using ASP.NET web forms by the way and not MVC).
  2. Copy and paste the code from the code-behind in default.aspx in the original web app to your default.aspx.  You should not need to add a “using” statement for the App_Code folder.
  3. Open the AppManifest.xml file in your SharePoint App project and change the Start Page property to point to the default.aspx page you created in your new web project.
  4. In the IIS Manager, make sure that for your provider hosted site anonymous is disabled and Windows authentication is enabled.
  5. Press F5 to launch the Visual Studio .NET debugger, install the app and validate that the code works.

If you created a console app:

  1. Open the TokenHelper.cs file and edit it; find these lines of code:

        private static readonly string ClientId = string.IsNullOrEmpty(WebConfigurationManager.AppSettings.Get(“ClientId”)) ? WebConfigurationManager.AppSettings.Get(“HostedAppName”) : WebConfigurationManager.AppSettings.Get(“ClientId”);
        private static readonly string IssuerId = string.IsNullOrEmpty(WebConfigurationManager.AppSettings.Get(“IssuerId”)) ? ClientId : WebConfigurationManager.AppSettings.Get(“IssuerId”);

(and then a little below)

        private static readonly string ClientSigningCertificatePath = WebConfigurationManager.AppSettings.Get(“ClientSigningCertificatePath”);
        private static readonly string ClientSigningCertificatePassword = WebConfigurationManager.AppSettings.Get(“ClientSigningCertificatePassword”);

and replace them with these; note that you must replace “yourAppsNamespace” with the namespace for your application:

        private static readonly string ClientId = yourAppsNamespace.Properties.Settings.Default.ClientId;
        private static readonly string IssuerId = yourAppsNamespace.Properties.Settings.Default.IssuerId;

        private static readonly string ClientSigningCertificatePath = yourAppsNamespace.Properties.Settings.Default.ClientSigningCertificatePath;
        private static readonly string ClientSigningCertificatePassword = yourAppsNamespace.Properties.Settings.Default.ClientSigningCertificatePassword;

2.  The code you run in the console app is slightly different from a web application.  To simplify, I’m pasting here the code you get out of the box in default.aspx, and I’ve indicated with a comment above the lines of code that were changed to make this work in a console app.  Sorry, only C# here folks, if you want VB though this stuff should be easy to convert.

                // – NOTE:  You need to put the Url to the site collection you want to work with here
                Uri hostWeb = new Uri(“https://mySharePointUrl“);

                // – here we are using WindowsIdentity.GetCurrent instead of from an HttpRequest
                using (var clientContext = TokenHelper.GetS2SClientContextWithWindowsIdentity(hostWeb, WindowsIdentity.GetCurrent()))
                {
                    clientContext.Load(clientContext.Web, web => web.Title);
                    clientContext.ExecuteQuery();
                    // – here we are using Console.Write instead of Response.Write
                    Console.Write(clientContext.Web.Title);
                }

3.  Add a using statement to the program.cs (or .vb) file for System.Security.Principal
4.  Right-click on your console project and select the Set as Start Up Project option.
5.  Press F5 to launch console app and validate that the code works.

You should be good to go at this point.  I actually walked through this process with a console app while writing this post, so as every good developer says if you have problems…”well, it works on my machine!”  🙂  I’ve also used this method MANY times previously for web apps so this should be solid as well.

Missing Context Token in Low Trust App with SharePoint 2013

Should you decide that you want to write low trust apps for an on-premises SharePoint 2013 farm, there are a number of hoops you should expect to jump through (NOTE:  this assumes the SPNs for your web apps are already configured in the MsolServicePrincipal for your o365 tenant):

  1. Create a new app in Visual Studio; in the wizard you select provider hosted app on the first page, and then client secret on the second page.
  2. Add a New Web Site to your solution, configure it to use SSL, and add all the necessary references to it (usually Microsoft.IdentityModel, Microsoft.IdentityModel.Extensions, Microsoft.SharePoint.Client, and Microsoft.SharePoint.Client.Runtime).
  3. Copy the TokenHelper.cs file from the app web created by the Visual Studio wizard and paste it into your new web site – create an ASP.NET Folder in your project for App_Code and copy it in there, then remove the “namespace” from the file.
  4. Copy all the goo from the web.config in the app web that the Visual Studio wizard created, and paste it into the web.config for your new web site.
  5. Add a new web form to your new web site called Default.aspx.
  6. Copy the code from the default.aspx.cs file in the app web that the Visual Studio wizard created, and paste it into the default.aspx.cs file in your new web site.

Now…that seems like a lot of good stuff, and it is, but when you try and run the application you’ll probably get an error that looks like this:

Along with that, you’ll see the error message about the parameter ‘token’ cannot be a null or empty string (yeah, I just added that in for the search engines…you’re welcome  🙂  ).  If you try debugging it you’ll see that when the call is made in the code-behind to GetContextTokenFromRequest, the return value is null.  So this is basically saying you’re not getting the context token you need from SharePoint.  What this means is that in all likelihood you don’t have a synced up ClientId value between your new web app’s web.config, the AppManifest.xml file for the SharePoint App, and the SharePoint site. 

After trying a few different ways around this, I honestly found the best way to resolve this problem is to do the following – go into your site into the /_layouts/15/appregnew.aspx page.  Use that to generate a new ClientId and ClientSecret.  Complete that page to register those values for the App Principal in the site.  Now, paste the ClientId into the AppManifest.xml file (in the RemoteWebApplication element), and paste the ClientId AND the ClientSecret into the web.config for your new web application.

You will need to redeploy your SharePoint App at this point, which you can still do by pressing F5 in Visual Studio.  After that it *should* work, however you may get an Access Denied error message too (I had this happen once).  Just to make sure everything was squared away, I went into the Site Contents page, clicked the ellipsis next to my application, and then clicked on the Permissions link.  That page contains a link that says “If there’s something wrong with the app’s permissions, click here to trust it again”, and click it I did.  In all honesty, things get wrapped up enough that it may very well have worked if I had just tried it again, but it seemed like an interesting link.  🙂

Hopefully this gives you heads up and maybe a little background as you look to use low trust apps in provider hosted apps on premises.