Overview
With the introduction and growth of ASP.NET Core, we SharePoint/Office 365 developers need a story that allows us to build Add-ins on top of provider-hosted ASP.NET Core deployments. What we have now works with old school ASP.NET and MVC 5 (yes, that is now old J).
As I explained in my previous post, Developing the ASP.NET Core Authentication/Authorization Middleware for SharePoint Provider-Hosted Apps (Add-ins), I’ve explained why this might be appealing and the technical challenges we are faced with. I have put together a library that allows us to develop SharePoint Add-ins that run on ASP.NET Core and in this blog post I explain how you can get started with including it in your own ASP.NET Core projects.
We have now updated the library to .NET Core and ASP.NET Core RTM. Previously it was running on RC1 only.
If you just want to have a look, just get the sample project and run it. Please share your experiences and feedback, they are an important reminder to where we need to put effort in with the PnP team.
Before you start
- You don’t have to complete these steps manually; the PnP repository has a sample project located here: https://github.com/OfficeDev/PnP/tree/master/Solutions/AspNetCore.Authentication
- Make sure you are using Visual Studio 2015 Update 3. This is not required, but some new features in the tooling make things easier.
- You need to register your app and get a ClientId and ClientSecret. This is not detailed here as it is nothing new. By default, ASP.NET Core web applications run on https://localhost:5000
Things you need to know before you start (all are explained why here):
- At the time of writing (09.09.2016) there is no support for High-Trust Add-ins, yet. This is on our roadmap.
- Our PnP library still targets .NET Framework 4.5.1.
Adding SharePoint Authentication to ASP.NET Core
Step 1: Create a new ASP.NET Core project based on the Web Application template
Step 2: Change the target framework of the web application project
This might change in future. Currently, our PnP library only runs on .NET 4.5.1. See why in this post: Developing the ASP.NET Core Authentication/Authorization Middleware for SharePoint Provider-Hosted Apps (Add-ins)
Change this:
To this (you can, of course, keep the imports that you need):
Then, remove the dependency to Microsoft.NETCore.App (it is only for netcoreapp1.0 and above):
If you need the NETStandard library , just add it under dependencies:
Step 3: Add the Microsoft.SharePointOnline.CSOM NuGet package
You need this to write SP CSOM code that works with SharePoint J Get it here: https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM/
PS Command: Install-Package Microsoft.SharePointOnline.CSOM
Step 4: Add the OfficeDevPnP.Core.Framework.Authentication NuGet package
With the current release of VS Tooling and .NET Core projects (Preview 2 at the time of writing) you can’t add a reference to a DLL, you need to add it through a NuGet package.
As pointed out, also at the time of writing the PnP Core Authentication code is not part of the Core library (see roadmap later in this post, we are working on that). This means that you need to bundle the OfficeDevPnP.Core.Framework.Authentication DLL into a NuGet package.
You can do this following the steps outlined on the NuGet site (https://docs.nuget.org/create/creating-and-publishing-a-package ) or just using Nuget Package Explorer (click here).
UPDATE (18.09.2016):
I have added a ready NuGet package to the project. You can find it here:
- https://github.com/OfficeDev/PnP/pull/1527/commits/fdb8de00ac6ee8d3efc1eb2c13a7e86c69c87540
- https://github.com/OfficeDev/PnP/tree/master/Solutions/AspNetCore.Authentication
Step 5: Add other necessary NuGet packages to your project.json
You will need these:
Step 6: Configure your Service Collection and pipeline in Startup.cs
Now it is time to add code. I hope you are impressed with the minimal footprint.
Add using OfficeDevPnP.Core.Framework.Authentication; and using OfficeDevPnP.Core.Framework.Authentication.Events;.
Include AddSession() and AddAuthentication() to your service collection.
public void ConfigureServices(IServiceCollection services){// Add framework services.services.AddMvc();//Add Session to the service collectionservices.AddSession();//add the authentication middleware and point SP as the default authentication sign-in schemeservices.AddAuthentication(sharedOptions =>sharedOptions.SignInScheme = SharePointAuthenticationDefaults.AuthenticationScheme);}
Then, go ahead and configure your pipeline to include the middleware:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){//required to store SP Cache Key session data//must also call AddSession in the IServiceCollectionapp.UseSession();//Add SharePoint authentication capabilitiesapp.UseSharePointAuthentication(new SharePointAuthenticationOptions(){ClientId = Configuration[“SharePointAuthentication:ClientId”],ClientSecret = Configuration[“SharePointAuthentication:ClientSecret”],AutomaticAuthenticate = true, //set to false if you prefer to manually call Authenticate on the handler.//OPTIONAL: CookieAuthenticationScheme = “AspNet.ApplicationCookie”,//Handle events thrown by the auth handlerSharePointAuthenticationEvents = new SharePointAuthenticationEvents(){OnAuthenticationSucceeded = succeededContext => {return Task.FromResult<object>(null);},OnAuthenticationFailed = failedContext => {return Task.FromResult<object>(null);}}});
NOTE: Some web applications/add-ins will require multiple authentication mechanisms. The library is built to allow this and co-exist with other Authentication middleware.
NOTE 2: Keep in mind that this is a pipeline, so order matters. The right place will depend on your app.
Step 7: Add your ClientId and ClientSecret
Configurations in ASP.NET Core happen in the appsettings.json file. Add the following under the root object:
Step 8: Modify your Kestrel Web Server to run on HTTPS
Since we’re doing Add-in authentication based on the OAuth protocol, we need to run over SSL. ASP.NET Core can run both on IIS and on Kestrel, I prefer Kestrel. This is what you need to do:
In Program.cs, change this:
public static void Main(string[] args){var host = new WebHostBuilder().UseKestrel().UseContentRoot(Directory.GetCurrentDirectory()).UseIISIntegration().UseStartup<Startup>().Build();host.Run();}
To this:
public static void Main(string[] args){var host = new WebHostBuilder().UseKestrel(options =>{options.UseHttps(@”..\..\certificates\localhost_ssl.pfx”, “pass@word1”);options.NoDelay = true;}).UseUrls(“https://localhost:5000”).UseContentRoot(Directory.GetCurrentDirectory()).UseStartup<Startup>().Build();host.Run();}
You can stick it in a try/catch if you wish. I have also added a IgnoreSslErrorsConnectionFilter class in the PnP sample to get rid of SSL handshaking errors with untrusted certificates. This is optional.
The SSL certificate is committed to the certificates folder. Note the https://localhost:5000 URL. Make sure everything runs at this point.
Make sure your project is firing up HTTPS://localhost:5000 and your F5 is not kicking off IIS Express, but rather the actual web application (which runs it as a console application now). This will start Kestrel.
Step 9: Add some CSOM code
You are all set. Write some CSOM Code to test:
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);var spLists = new List<SharePointListViewModel>();if (spContext == null) return View();//build a client context to work with datausing (var clientContext = spContext.CreateUserClientContextForSPHost()){if (clientContext != null){var lists = clientContext.Web.Lists;clientContext.Load(lists);clientContext.ExecuteQuery();foreach (var list in lists){spLists.Add(new SharePointListViewModel() { ListTitle = list.Title });}}}
Step 10: Test it!
Now that everything is set, go to the SharePoint Online site where your app is configured, then click it’s link. It will go through AppRedirect.aspx and then lead your browser to https://localhost:5000 if everything is configured right. The ASP.NET Code PnP middleware will intercept (based on the SPHostUrl query string) and get the context token, work through it and eventually allow you to instantiate the SPContext object needed to work with CSOM data. Pretty cool, hey?
Summary
Overall, it takes 10 steps to heaven J We are working hard to improve everything we can in regards to the developer experience, that is the fun parth in building tooling and API’s.
Please take the time to give feedback, share your issues or even high five. Microsoft and the PnP team need to see activity and the need for this library, so we have justification to increase its priority.
- Raise issues on GitHub: https://github.com/officedev/pnp
- Post questions or thanks on Lithium: aka.ms/officedevpnpyammer
- Use the hashtag on Facebook and Twitter: #OfficeDevPnP (and mine is @RadiAtanassov)
Roadmap for the ASP.NET Core Authentication library
As mentioned, things are still evolving. We have tons of issues to solve in terms of dependencies and figure out how to make it easier to plug-and-play all of this. It might seem hard at first, but so where Apps when they first came out. The PnP team is working hard to make it easier for developers and this is all done in our free time. Please help us out with constructive feedback and contributions https://github.com/OfficeDev/PnP .
Here is a list of targets that we have:
- Enhance the sample to demonstrate the usage of App-Only access tokens.
- Enhance the sample to demonstrate on-the-fly authentication through the Authentication Code flow.
- Remove dependencies from Microsoft.IdentityModel.Extensions and framework assemblies
- Implement High-Trust authentication capabilities
- Add to the current OfficeDev PnP Core library
- Build a true .NET Core App compatible library