Disclosure: I work for Microsoft. The views in this post are my own and not those of Microsoft.
The Problem: Authentication
When we’re discussing problems with writing a Windows Store app for CRM, the primary thing we need to talk about is authentication. After we discuss the problem, we’ll talk through 2 solutions for authenticating and writing code that communicates with CRM from a store app.
The Solutions: Sample SDK and Unsupported, Unsanctioned Goodness (for CRM Online on O365 Only)
- First we’ll walk through using the CRM Product Team’s sample SDK for Windows Store Apps. You may have used this already (I hope you have), but stay tuned, because there are some tricks that we can use to improve the developer experience, and we’ll identify those.
- Then, we’ll talk about using the Organization Service Odata endpoint directly from our Windows 8 Store App. Why, you might ask, am I talking about option 1 first if I have a solution that will let you call the Odata service directly? Because, young Jedi, this approach is non-sanctioned, has no path for official support, and if it breaks your apps, you’re on your own. But it’s still awesome. And I’m doing it last because I like suspense.
Why is there an authentication problem?
So why is there a problem authenticating with CRM from Windows Store apps?
When we’re building apps for CRM on other platforms, where we have access to the full .NET library, we use the Microsoft.Xrm.Sdk.dll library to connect to CRM. This library does quite a bit for us. Perhaps most importantly, it manages authentication for us. It has all the code in there that navigates through the steps the CRM web service exposes in compliance with the WS-Trust protocol. However, Microsoft.Xrm.Sdk.dll is dependent upon .NET 4.0 and WIF (Windows Identity Foundation). When we’re building Windows Store Apps, we have a lighter .NET profile that doesn’t include these resources.
There are 2 endpoints for the Organization Web Service that we use to access CRM data.
- The Odata endpoint is not available to external callers (for now – read on for solution 2 :) ).
- The SOAP endpoint uses the WS-Trust protocol to authenticate callers. WS-Trust itself doesn’t require .NET 4.0 or WIF, and for that matter, neither does the CRM SOAP endpoint. It just so happens that the code in Microsoft.Xrm.Sdk.dll uses those two resources for its own WS-Trust authentication. Without this library, we have to write our own WS-Trust implementation using the slimmed-down .NET profile available to us (hard), or we can use the sample SDK provided by the product team (easy).
Sample Windows Store App Project: Take Notes on Contacts
This sample project gives you a list of Contacts and lets you create a Note for each one:
Solution 1: The Sample SDK
- Sample SDK: http://blogs.msdn.com/b/crm/archive/2012/11/02/building-clients-for-windows-phone-and-windows-8-rt.aspx
- My Sample Project Code: https://github.com/andisimo/NotesByHand
Benefits:
- Authentication = Easy
- You’re building Win8 apps for CRM right away
Drawbacks:
- No LINQ
- No await/async – have to use EAP
- No early binding
- No support for Windows authentication – only IFD and CRM Online
Is the 4th bullet really a drawback? Not really, but I thought I’d note it here. If you really wanted to build an app that only can be used inside your company’s firewalls, you could write your own Windows Authentication mechanism.
Of the 3 drawbacks, the last 2 are actually easily rectified – but I won’t detail them here, because Marc Schweigert has already created a great video that walks through the steps you can take to get early bound entities and await/async methods:
Unfortunately, there’s no LINQ support; you’re stuck with FetchXML. Put it in a static class like I do in my sample app, and use the LINQPad solution Marc recommends if you want to.
Solution 2 (Unsupported): Call the Odata endpoint from the outside
- To install the Nuget package, run commandlet: Install-Package FedId.WinRT.Project.Scaffolding -Version 1.6.5.2
- My Sample Project Code: https://github.com/andisimo/CrmFedId (see the instructions on how to get the code working below)
Yes, this is groundbreaking. You’ve never been able to do this before, and you aren’t misunderstanding me. There is a way now to call the CRM Odata endpoint from a Windows Store app. It’s unsupported – and I’ll explain what that means below. This only works for CRM Online tenants running on the Office 365 cloud, not to LiveId tenants or to on-premise installations. You’ll also want to keep in mind that this approach has all of the limitations of the Odata endpoint (it only does CRUD operations over entities), so there are some scenarios where you may need to access the SOAP endpoint via the Sample SDK anyway. However, for most Windows Store Apps, CRUD over entities will probably be all you’ll ever need.
You can get the package by running the above commandlet from the Package Manager Console in Visual Studio with your Windows Store app project open.
The benefits of this approach are that you can use the modern code conventions we’ve been used to using since CRM 2011 was released. This is like writing a web resource that runs inside of CRM, because we’re using the same Odata endpoint! The authentication part is relatively easy. Let me correct myself – it is easy for US because a very smart programmer has done a substantial amount of work to build the assets that make this possible.
The drawbacks are that this approach is not supported. What does this mean? As CRM devs, when we hear “not supported”, we tend to think we’re talking about a forbidden no-no. That’s not the case with what I’m about to discuss. Remember, we’re building an app outside of CRM. How we authenticate from that app is not going to place our CRM deployment in an unsupported state. What unsupported means, in this instance, is that there is NO GUARANTEE that what we build using this approach won’t break in the future if something changes in CRM. This is not aligned with the CRM product group’s strategy and you should have no expectation that what I’m about to show you will merge with or become part of the officially recommended way of doing things in the future.
Now, why am I sharing it with you if I have to give such a stern disclaimer up front? Because what I’m about to show you is exciting, and at the very least, it’s a very compelling thing to test and try out. When you’ve carefully weighed your decision, some of you might decide to use it. Just know that any minor change in the CRM api could potentially cause this to stop working, and while that may be unlikely, it’s definitely possible. We have a major release coming out later this year, and you’ll want to keep your eye on that.
How Solution 2 Works
Solution 1 (The sample SDK from the CRM team) uses WS-Trust to authenticate via the SOAP endpoint, passing a request security token in the SOAP header. This is an established, solid approach to authentication, but there are problems. Since this all happens via the SOAP header, we are constrained to use the SOAP service, which introduces the developer productivity limitations we discussed earlier.
Authentication to the CRM endpoints is fundamentally nothing more than a requirement that a caller meet a certain criteria. The criteria the SOAP endpoint looks for is a valid token in the SOAP header. The criteria the OData endpoint looks for is a valid, encrypted cookie being passed in the request that identifies the caller.
The FedId WinRT Project Scaffolding collects the user’s credentials. It then walks through the steps a browser client goes through, inserting the credentials at the necessary places, to mimic the steps a browser takes in WS-Federation passive authentication. It collects the various tokens that are returned during the several required steps, in order to finally get a token that can be used to access the CRM Odata endpoint.
How to Use the FedId WinRT Project Scaffolding Package
- Download and install the WCF Data Services Tools for Windows Store Apps:
- Download the CSDL from CRM > Settings > Customizations > Developer Resources
- Create an empty windows store app
- Install the Nuget package from package manager console:
Install-Package FedId.WinRT.Project.Scaffolding -Version 1.6.5.2 - Add a Service Reference and point it to the location of the csdl file you downloaded. Name it OdataReference. It will have a context type to match your org name (like OdataReference.OrgNameContext). Giving your service reference a namespace other than “OdataReference” will require you to find and change a few using statements that are currently “using CrmFedId.OdataReference”.
What’s in the Sample Code
- There are only a few main components at work here:
- I’ve got a MainPage.xaml for signin, and a BasicPage1 and BasicPage2.xaml. Upon authentication, MainPage navigates to BasicPage1, which shows a gridview of Contacts. When you click (or tap – come on, this is Windows 8) on a Contact, BasicPage1 navigates to BasicPage2 and shows you a textbox that allows you to create a note for that contact.
- I also have a ContactsNotesViewModel class that has a few properties to store the data I get from CRM so the xaml pages (views) can bind to it, and some methods to get that data. The context for the CRM tenant is also instantiated and stored in the ViewModel, as well as a few events that help me keep track of the authentication and data responses. I have a static property of type ContactsNotesViewModel defined in App.xaml.cs and instantiated in the OnLaunched method of that class.
- Security.IdpCredentialsFlyout.xaml: this is the definition for the flyout. This ”Security” folder is added when you install the Nuget package. You can look at the codebehind for this page to see the event handler for when the user pushes the ”Sign In” button (called SignIn), how it handles the credentials, and ultimately calls the FedId.Instance.SignInAsync method and gets the token in the response.
- A class called FedId that manages security tokens, settings, things like that. It has a static property of its own type (FedId) called Instance, that you will use to access the actual tokens you get from CRM from elsewhere in your project code.
- You don’t need it, but I have an extension method, courtesy of Marc Schweigert again, that gives me an await/async-friendly ExecuteAsync<T> method with a generic type parameter. It’s definitely better to have it than not.
- And, finally, your Service Reference, which gives you the entity context for your CRM organization. Your context is at “OdataReference.[OrgName]context”.
How to Get the Sample Code Working
- Follow the steps in the section above, “How to Use the FedId WinRT Project Scaffolding Package“, with the EXCEPTION OF steps 3 and 4, creating a new Windows Store App project and installing the Nuget package. You already have your project in the sample code, and it already has the Nuget package installed.
- Once you have your Service Reference added, open your Find dialogue (ctrl + f) and search the ContactsNotesViewModel for the text “psecdemoContext”. You should find 3 instances of it – in the type declaration for a private field, a public property, and in the HaveToken() method that sets the public property. Change the type of these items to match your own [orgname]Context. Orgname = the name of your CRM organization.
- Use your find dialogue again to search for “psecdemo.” (psecdemo with a period). This is to find 2 URLs where you’ll need to insert your own organization name. One is in the ContactsNotesViewModel, and the other is in the MainPage.xaml.cs file.
- Build!
Code Flow
The main page loads (in the LoadState method). The first thing that happens there is that we subscribe to the following event:
FedId.Instance.ShowSettingsFlyout
The lengthy lambda expression that follows mostly makes sure that when the event is fired, the flyout where the user enters his/her credentials is displayed properly.
Next, we subscribe to the TokenReceived and ContactsLoaded events on the ContactsNotesViewModel. We’ll discuss these events in a moment when they actually get fired, in order to keep our walkthrough of the code chronologically sequenced.
So finally we get to the bottom of the LoadState method, where we find the first code that actually proactively does something:
if (!FedId.Instance.IsSecurityTokenValid())
{
var result = await FedId.Instance.SignInAsync
(https://psecdemo.crm.dynamics.com/);
}
else
{
App.ContactsNotesVM.HaveToken();
}
This code is checking the FedId.Instance property to see if there is a valid security token there. Sometimes there will be – for example, if you’ve already authenticated and your computer has stored the authentication cookie. If you haven’t authenticated, or if your cookie is expired, then there won’t be a valid security token, and the code will invoke the SignInAsync method. You can’t see this method other than its signature in the metadata viewer, but we know that somewhere in this method or in other code called by this method, the ShowSettingsFlyout event is triggered (the one we subscribed to at the very top of our LoadState method on MainPage.xaml.cs).
The user then enters credentials and clicks the “Sign In” button, triggering the
IdpCredentialsFlyout.SignIn
method. When that method gets a token back successfully (i.e. if result == true in the following code), we call the ContactsNotesViewModel.HaveToken() method:
if (result == true)
{
//The HaveToken method fires the TokenReceived event on our viewmodel
App.ContactsNotesVM.HaveToken();
As the comment there says, this HaveToken() method turns around and fires the TokenReceived event, after initializing the ViewModel’s context. There may or may not be a code smell here, calling a method on object1 to essentially trigger an event on object1 from object2, but it seemed like a solid way to get this sequence working properly in my sample.
public void HaveToken()
{
Ctx = new psecdemoContext(new Uri(
https://psecdemo.crm.dynamics.com/XRMServices/2011/OrganizationData.svc/));
TokenReceived();
}
Now, let’s go back to MainPage.xaml.cs. In our LoadState method, you should remember that we subscribed to the HaveToken() method. When this event is fired, we call the LoadContactsAsync method on our ViewModel:
App.ContactsNotesVM.TokenReceived += () =>
{
App.ContactsNotesVM.LoadContactsAsync();
};
The LoadContactsAsync method is where we have the code that actually interacts with the Odata service.
public async void LoadContactsAsync()
{
if (FedId.Instance.IsSecurityTokenValid() == false)
{
throw new InvalidOperationException(@"ContactsNotexViewModel.LoadContactsAsync cannot retrieve
contacts when the FedIde.Instance.IsSecurityTokenValid property is false. This property is set = true when the
security token is correctly received from the FedId.Instance.SignInAsync method call."); }
var query = from c in Ctx.ContactSet
select c;Ctx.SendingRequest += (sender, args) =>
args.RequestHeaders[HttpRequestHeader.Cookie] =
FedId.Instance.SecurityToken.SessionCookieHeader;
var results = await ((DataServiceQuery<Contact>)query).ExecuteAsync();
foreach (Contact c in results)
{
Contacts.Add(c);
}
this.IsDataLoaded = true;
Loaded();
}
The last thing this method does is trigger the ContactsNotesViewModel.Loaded event. We subscribed to this in our MainPage.LoadState method:
App.ContactsNotesVM.Loaded += async () =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
this.Frame.Navigate(typeof(BasicPage1));
});
};
As you can see, once we know the contacts have been loaded into our ViewModel, we are free to navigate to BasicPage1, where the databinding between the page and the ViewModel takes over and the contacts are displayed just like you saw in the picture at the top of the post.
Instead of using an event to tell us when the contacts were loaded, a better solution would be to make the ContactsNotesViewModel.Contacts property an ObservableCollection and implement the INotifyPropertyChanged interface on the ViewModel, which would allow us to navigate to BasicPage1 without worrying about whether we would get there before the contacts were loaded. The viewmodel would simply update the view with the data as it arrived.
But you’ll notice that there this isn’t the only less-than-optimal choice I’ve made for writing this Windows Store app. My goal was to show you two ways to access the CRM web services from the app, and I hope you’ve found at least one of them valuable!

