Using OAuth to Authenticate Microsoft Dynamics NAV Web Services (OData and SOAP)

Microsoft Dynamics NAV 2016 supports the OAuth authentication protocol for SOAP and OData web services. This article is designed to help you understand the basics behind the use and configuration of OAuth authentication in Microsoft Dynamics NAV.

This article includes the following sections:

Introduction

The Starting Point: Microsoft Dynamics NAV Configured for Office 365 Single Sign-on

Creating a Custom Application that Connects to Dynamics NAV OData using Basic Authentication

Converting the Application to OAuth Authentication

Configure the App ID URI in the Microsoft Dynamics NAV Server

Register the Custom Application in the Azure Active Directory (AD) Tenant

Credential Lifetime

Summary

Appendix: Sample Code for Prompting for a User Name and Password

Introduction

OAuth is useful when Microsoft Dynamics NAV is configured for single sign-on with Office 365 because it lets users authenticate to Microsoft Dynamics NAV web services using their existing Office 365 credentials.

This article describes general aspects of the OAuth authentication protocol, including how to set it up for Microsoft Dynamics NAV. It also provides a guide on how to create a custom .NET application that connects to Microsoft Dynamics NAV web services and authenticates by using OAuth. The result will be a .NET console application that contains following code (with some adjustments to suit your environment):

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using MyNavClient.ServiceReference1;
using System;
class Program
{
    // Azure AD registrations
    // - the Azure AD tenant
    const string AadTenantId = "mytenant.onmicrosoft.com";
    // - this client application
    const string ClientId = "e64a621d-beb8-4e7d-bf0b-30e3e79651dd";
    const string ClientAppUri = "https://MyNavClient";
    // - the server that we want to call (Microsoft Dynamics NAV)
    const string ServerAppIdUri = "https://mynavserver/NAVAppIdUri";
    [STAThread]
    static void Main()
    {
        // Get access token from AAD. This will show the login dialog.
               var authenticationContext = new AuthenticationContext(
                   "https://login.windows.net/" + AadTenantId);
        AuthenticationResult authenticationResult =
            authenticationContext.AcquireToken(
            ServerAppIdUri, ClientId, new Uri(ClientAppUri));
        // Connect to the NAV web service
        var nav = new NAV(new Uri("https://mynavserver:7047/NAV/OData"));
        nav.BuildingRequest += (sender, eventArgs) => eventArgs.Headers.Add(
            "Authorization", authenticationResult.CreateAuthorizationHeader());
        foreach (var customer in nav.Customer)
        {
            Console.WriteLine("Found customer: " + customer.Name);
        }
        Console.ReadLine();
    }
}

When you run the application, a dialog appears where you can sign in to Azure Active Directory by using your organizational account. After you sign in, the application connects to the Microsoft Dynamics NAV OData web service to get a list of customers.

You will start by creating a custom application that connects to the Microsoft Dynamics NAV OData endpoint and authenticates by using Basic authentication. The subsequent sections cover the changes that you must make to authenticate by using OAuth. This should help make it clear what is required to take the next step for setting up OAuth authentication.

The Starting Point: Microsoft Dynamics NAV Configured for Office 365 Single Sign-on

This article assumes that you already have a Microsoft Dynamics NAV installation, and that you have configured it for single sign-on (SSO) with your Office 365 account. We will not cover the details of how to do this here. You can learn about single sign-on by watching the video How Do I: Enable Single Sign-On with Office 365 in Microsoft Dynamics NAV 2013 R2 or reading the topic How to: Set up Microsoft Dynamics NAV for Single Sign-on With Office 365 using Windows PowerShell. In addition to these instructions, make sure that you do the following:

  • Get the App ID URI

    When you configured Microsoft Dynamics NAV for single sign-on with Office 365, you had to register Microsoft Dynamics NAV as an application in a Microsoft Azure Active Directory (Azure AD), and also specify an APP ID URI. You will need the APP ID URI later to enable OAuth. You can get the ID from the Azure Management Portal by viewing the Microsoft Dynamics NAV application configuration in Active Directory. For more information, see Integrating Applications with Azure Active Directory.

  • Get the Azure Active Directory Tenant ID (AadTenantId)

    The Azure Active Directory Tenant ID identities the directory for the Microsoft Dynamics NAV application in Azure AD. The tenant ID can be the tenant's domain name or GUID. In most cases, you can use the domain name, which is typically in the form mytenant.onmicrosoft.com. There are different ways to get this information. You can get the domain name from the Domain settings for the AD tenant (directory) in the Azure Management Portal. Or you can extract the information from the URL in the browser when you open the AD tenant in the Azure Management Portal, as illustrated in the following URL:

    https://manage.windowsazure.com/*\[Domain name]#Workspaces/ActiveDirectoryExtension/Directory/[Tenant ID]*/directoryQuickStart

  • Set the Microsoft Dynamics NAV Server instance credential type to NavUserPassword

    To make sure that the procedures in this article work as expected, set the Credential Type setting (ClientServicesCredentialType) of the Microsoft Dynamics NAV Server instance to NavUserPassword. When this is the case, the Microsoft Dynamics NAV Server instance supports both NavUserPassword (Basic) and AccessControlService (Office 365) authentication.

    For more information, see Configuring Microsoft Dynamics NAV Server,

When configured for single sign-on, you will be prompted for your Office 365 credentials when you try to access Microsoft Dynamics NAV. To verify this, open a Microsoft Dynamics NAV client.

Exposing a Web Service

To illustrate the use of OAuth authentication on web services, the first thing to do is use the Microsoft Dynamics NAV client to publish/expose an object as a web service. For this article, use page 21 Customer Card from the CRONUS International Ltd. demonstration database and assign the page the service name “Customer”. For information about how to publish the page as a web service, see How to: Publish a Web Service. The following table depicts the resultant web service setup.

Object Type Object ID Object Name Service Name Published OData URL

Page

21

Customer Card

Customer

https://myserver: port/NAV/OData/Company('CRONUS%20International%20Ltd.')/Customer

In the OData URL, myserver is the computer that is running the Microsoft Dynamics NAV Server instance.

After you publish the web service, you can now enter the OData URL in the address of an Internet browser. When you do, you will be prompted for your user name and password. The user name and password that you enter is the user name and password of your Microsoft Dynamics NAV account; not your Office 365 user name and password. On the User Card in Microsoft Dynamics NAV, this information is specified by the User Name field in the General section and the Password field in the Microsoft Dynamics NAV Password Authentication section.

This illustrates the problem, which is, users must use different credentials when they use the Microsoft Dynamics NAV clients than when they use the Microsoft Dynamics NAV web services.

Creating a Custom Application that Connects to Dynamics NAV OData using Basic Authentication

You will start by creating an application that connects to the Microsoft Dynamics NAV OData web service by using Basic authentication. To do this, follow these steps:

  1. In Visual Studio, create a new C# Console Application project and name it “MyNavClient”.

  2. Add a service reference according to the following guidelines:

    1. In the Address field of the Add Service Reference dialog box, enter the base part of the Microsoft Dynamics NAV OData URL. This is the part of the URL up to and including “/OData”, for example, https://myserver:7047/NAV/OData.

    2. Choose GO, and enter your Microsoft Dynamics NAV user name and password when you are prompted.

      In the Service pane, you will see the OData feeds that Microsoft Dynamics NAV has exposed, which includes the Customer feed that you exposed earlier.

    3. Select the Customer service, and then choose OK.

      At this point, the wizard generates a service reference, which you can in the Solution Explorer pane and code editor of Visual Studio. The service reference includes some useful C# proxy classes (which are not shown) that make it easy to call the web service.

  3. In the code editor, write the following code. Replace myserver and port to suit your Microsoft Dynamics NAV Server instance.

    using MyNavClient.ServiceReference1;
    using System;
    using System.Net;
    using System.Runtime.InteropServices;
    using System.Text;
    class Program
    {
        [STAThread]
        static void Main()
        {
            // Get user credentials
            string userName;
            string password;
            PromptForCredentials(out userName, out password);
            // Connect to the Dynamics NAV web service
            var nav = new NAV(new Uri("https://myserver:port/NAV/OData"));
            nav.Credentials = new NetworkCredential(userName, password);
            foreach (var customer in nav.Customer)
            {
                Console.WriteLine("Found customer: " + customer.Name);
            }
            Console.ReadLine();
        }
        // NOTE: the PromptForCredentials method is included in the appendix
    }
    
  4. Press F5 to run the console application.

  5. Enter your Microsoft Dynamics NAV user name and password when you are prompted.

    You should see the list of customers in the console.

Converting the Application to OAuth Authentication

The next step is to abandon the use of the built-in Microsoft Dynamics NAV user name and password for authentication and use the Office 365 user name and password instead. This is a three-step process as described in this section.

Configure the App ID URI in the Microsoft Dynamics NAV Server

When Microsoft Dynamics NAV was registered in the Azure AD tenant, it was assigned an APP ID URI. You must get the APP ID URI from there and enter it in the Microsoft Dynamics NAV Server instance settings.

  1. If you do not know the APP ID URI for the Microsoft Dynamics NAV application, get it by using the Azure Management Portal.

    For more information, see The Starting Point: Microsoft Dynamics NAV Configured for Office 365 Single Sign-on.

  2. Using the Microsoft Dynamics NAV Server Administration tool, open the Microsoft Dynamics NAV Server instance for editing, and fill in the Azure Active Directory App ID URL field with the APP ID URI value. Restart the instance.

    For more information, see How to: Configure a Microsoft Dynamics NAV Server Instance.

Register the Custom Application in the Azure Active Directory (AD) Tenant

You also have to register your custom application in the Azure AD tenant (also referred to Azure AD directory) in which you registered Microsoft Dynamics NAV. This makes sense because Azure AD is the common “authority” that can issue security tokens that enable client applications to call server applications.

To register the custom application, use the Azure Management Portal to add it to Azure AD as a native client application. For information about how to do this, follow the instructions in Integrating Applications with Azure Active Directory. Use the following information as guide to help you determine some of the registration settings.

  • Add the custom application to the same Azure AD tenant (directory) as Microsoft Dynamics NAV.

  • Choose the Add an application my organization is developing option.

  • Give application a name such as MyNavClient,

  • Choose to add a native client application type.

  • Set the redirect URI to a valid URI for Azure AD to redirect to in response to an OAuth request, for example, https://MyNavClient..

    This is a logical URL that only acts as a unique identifier for the application. It does not have to refer to an actual endpoint; but is must be a valid URI.

  • On the Configuration tab, configure the custom application to have delegated permission to access the Microsoft Dynamics NAV application.

  • Make a note of the values of the CLIENT ID and REDIRECT URI properties. You will use this information in the next procedure.

Now the custom client application is registered in Azure AD, and it has the permission to call Microsoft Dynamics NAV web services on behalf of a signed-in user.

Change the Custom Application to use OAuth

The final task is to modify the custom application to use OAuth authentication. To complete this procedure, you must have the following information, most of which you should already have:

Information Description Example

Azure AD Tenant ID

This is the ID that is assigned to the Azure AD directory. For more information about finding this value, see The Starting Point: Microsoft Dynamics NAV Configured for Office 365 Single Sign-on.

mytenant.onmicrosoft.com

Client ID

This is the ID that is assigned to the custom application in Azure AD.

e64a621d-beb8-4e7d-bf0b-30e3e79651dd

Redirect URI

This is the redirect URI that you assigned the ID that is assigned to the custom application in Azure AD.

https://MyNavClient

App ID URI

The App ID URI that you assigned to the Microsoft Dynamics NAV application in Azure AD.

https://myserver/NAVAppIdUri

OData URL

The base part of the Microsoft Dynamics NAV OData URL. This is the part of the URL up to and including “/OData”. For more information, see Exposing a Web Service.

https://myserver:7047/NAV/OData

Once you have this information, follow these steps:

  1. In Visual Studio, open the custom application, and use the NuGet Package Manager to install the Microsoft.IdentityModel.Clients.ActiveDirectory package for the Active Directory Authentication Library.

    This library contains useful utilities for calling OAuth web services. You can read about the package at https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory.

  2. In the code editor, write the following code. Replace brackets [] with your values:

    using Microsoft.IdentityModel.Clients.ActiveDirectory;
    using MyNavClient.ServiceReference1;
    using System;
    class Program
    {
        // Azure AD registrations
        // - the Azure AD tenant
        const string AadTenantId = "[Azure Tenant ID];
        // - this client application
        const string ClientId = "[Client ID]";
        const string ClientAppUri = "[Redirect URI]";
        // - the server that we want to call (Microsoft Dynamics NAV)
        const string ServerAppIdUri = "[App ID URI]";
        [STAThread]
        static void Main()
        {
            // Get access token from AAD. This will show the login dialog.
            var authenticationContext = new AuthenticationContext("https://login.windows.net/" +
                AadTenantId);
            AuthenticationResult authenticationResult = authenticationContext.AcquireToken(
                ServerAppIdUri, ClientId, new Uri(ClientAppUri));
            // Connect to the Dynamics NAV web service
            var nav = new NAV(new Uri([Odata URL]"));
            nav.BuildingRequest += (sender, eventArgs) => eventArgs.Headers.Add(
                "Authorization", authenticationResult.CreateAuthorizationHeader());
            foreach (var customer in nav.Customer)
            {
                Console.WriteLine("Found customer: " + customer.Name);
            }
            Console.ReadLine();
        }
    }
    

    Notice the few changes that you had to make: You had to specify the IDs that were used when you registered the applications in Azure AD. Then, you had to add 3 lines of code to open the Office 365 logon page to get the OAuth access token.

  3. Press F5 to run the custom application.

    You should see the Office 365 Sign-in page.

  4. Enter your Office 365 user name and password.

    You should again see the list of customers from Microsoft Dynamics NAV.

Credential Lifetime

After having prompted for Basic credentials, the credential are persisted by application and used for as long as they are valid in Microsoft Dynamics NAV. However, the picture is more complicated for OAuth because the security tokens that are used for authentication have a limited lifetime. The code to obtain OAuth credentials was as follows:

AuthenticationResult authenticationResult = authenticationContext.AcquireToken(
            ServerAppIdUri, ClientId, new Uri(ClientAppUri));

The AuthenticationResult actually contains two tokens:

        string accessToken = authenticationResult.AccessToken;
        string refreshToken = authenticationResult.RefreshToken;

The accessToken is the one that is actually used when the client application calls the web service. The access token is relatively short-lived (one hour, subject to change), and when it expires, the client application needs a new access token.

The refreshToken lives much longer (6 months, subject to change), and it can be used to get a new access token:

        AuthenticationResult newAuthenticationResult =
                    authenticationContext.AcquireTokenByRefreshToken(refreshToken, ClientId);
        string newAccessToken = newAuthenticationResult.AccessToken;
        string newRefreshToken = newAuthenticationResult.RefreshToken;

By the way, this also gives a new refresh token, and in this manner, the client application can keep calling the Microsoft Dynamics NAV web services forever.

Summary

More and more companies adopt Office 365 and integrate Microsoft Dynamics NAV with Office 365 to obtain Single Sign-On. As this occurs, it also becomes important that customers can authenticate to Microsoft Dynamics NAV web services by using their universal credentials – the Office 365 user name and password. OAuth is the web service authentication protocol that makes this possible.

This article covered how to configure Microsoft Dynamics NAV web services for OAuth authentication. It also demonstrated how to create a simple .NET console application that connects to these web services. It is also possible to create other types of applications that authenticate using OAuth, such as modern Windows 8 apps, iOS apps, and Android apps. The Microsoft Azure Active Directory team has released libraries for all these platforms. See the following resources:

We hope you found this article useful and that you will make use of the OAuth capabilities of Microsoft Dynamics NAV 2016.

The Microsoft Dynamics NAV team.

Appendix: Sample Code for Prompting for a User Name and Password

The following code illustrates how you can use a Windows API to prompt for user name and password, which you can use for Basic authentication. This code will not be needed for OAuth authentication.

private static void PromptForCredentials(out string userName, out string password)
    {
        const int BufferSize = 200;
        // Set up variables 
        StringBuilder passwordBuffer = new StringBuilder(BufferSize + 1), 
             userBuffer = new StringBuilder(BufferSize + 1);
        var credUi = new NativeMethods.CREDUI_INFO();
        credUi.Size = Marshal.SizeOf(credUi);
        bool save = false;
        // Prompt the user 
        const NativeMethods.CREDUI_FLAGS Flags = NativeMethods.CREDUI_FLAGS.ALWAYS_SHOW_UI | 
           NativeMethods.CREDUI_FLAGS.GENERIC_CREDENTIALS |  
           NativeMethods.CREDUI_FLAGS.EXPECT_CONFIRMATION;
        NativeMethods.CredUIReturnCodes returnCode = 
           NativeMethods.CredUIPromptForCredentials(
           ref credUi, "servername", IntPtr.Zero, 0, userBuffer, BufferSize, passwordBuffer,
           BufferSize, ref save, Flags);
        if (returnCode == NativeMethods.CredUIReturnCodes.NO_ERROR)
        {
            userName = userBuffer.ToString();
            password = passwordBuffer.ToString();
            return;
        }
        userName = null;
        password = null;
    }
    private static class NativeMethods
    {
        internal struct CREDUI_INFO
        {
            internal int Size;
            internal IntPtr Parent;
            internal string MessageText;
            internal string CaptionText;
            internal IntPtr BannerBitmapHandle;
        }
        [DllImport("credui", CharSet = CharSet.Unicode)]
        internal static extern CredUIReturnCodes CredUIPromptForCredentials(
              ref CREDUI_INFO creditUR,
              string targetName,
              IntPtr reserved1,
              int error,
              StringBuilder userName,
              int maxUserName,
              StringBuilder password,
              int maxPassword,
              [MarshalAs(UnmanagedType.Bool)] ref bool save,
              CREDUI_FLAGS flags);
        [Flags]
        internal enum CREDUI_FLAGS
        {
            ALWAYS_SHOW_UI = 0x80,
            EXPECT_CONFIRMATION = 0x20000,
            GENERIC_CREDENTIALS = 0x40000,
        }
        internal enum CredUIReturnCodes
        {
            NO_ERROR = 0,
        }
    }