Connecting to Microsoft Dynamics NAV OData service from Javascript

If you have ever tried to connect to NAV Web Services or OData services you will know that the biggest headache is getting the security to work (I have spent many days bashing my head against Kerberos). If you don’t need to impersonate the end-user things get a little simpler (create a UserPassword Service Tier, connect with a specific user and password) – the hard bit is when you do want/need to impersonate.

This post is about OData, and specifically OData from Javascript. Why was I talking about impersonation? Because if you can connect to a NAV OData Service from Javascript then you are going directly from the client (browser) to the service you are connecting directly, so you don’t need any middle tier to impersonate you.

The problem is if your website/javascript is served from a different machine to your NAV Service Tier (I’m yet to meet an IT manager who wants IIS anywhere near his Service Tiers) your browser will complain about Cross-Origin Resource Sharing (CORS or Cross-Domain requests) as this a recognised security hole (for a similar reason to why Kerberos exists).

I’ve searched for an answer to this a few times and came across this exact issue on stack overflow. The answer given never quite worked for me so I finally managed to provide my own answer that does seem to work, after reading this article and this page.

The answer seems to be that you need to use jsonp, which is designed to get around cross-domain restrictions (this example is using the jquery $.ajax function)

Javascript
$.ajax({
    url: 'http://Server:Port/DynamicsNAV80/OData/Service?$format=json&$callback=?',
    contentType: 'application/json; charset=utf-8',
    dataType: "jsonp",
    type: "GET",
    xhrFields: {
        withCredentials: true
    },
    dataType: "jsonp",
    success: function (data) {
        alert(JSON.stringify(data));
    },
    error: function (xhr, textStatus, errorMessage) {
        alert('Error: ' + errorMessage);
    }
});

Some Important Caveats:

  • In IE and Chrome this works as I expect – just passing through my credentials. In Firefox I am asked for a login twice, once for my site, once for the service, I don’t know if this is my Firefox settings or something I have missed in the Web.config. Reading up further on this it looks like Firefox applies more strict Cross Origin rules… Luckily for my app it is acceptable to ignore Firefox.
  • This only works with GET. You cannot use jsonp to do a POST, so you won’t be able to write anything to the NAV OData services using this technique.

Hope this helps someone 🙂

I’ve also created a Microsoft Connect suggestion to allow us to configure the CORS headers at the Service Tier level (so we don’t need to do tricks with JSONP). If you think this is useful please click the link below and up-vote it.

https://connect.microsoft.com/dynamicssuggestions/feedback/details/2238455/configurable-odata-access-control-allow-origin-list-for-cors

Advertisements

One thought on “Connecting to Microsoft Dynamics NAV OData service from Javascript

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s