79
Microsoft Dynamics ® AX Developing secure mobile apps for Microsoft Dynamics AX 2012 White Paper This document describes how to develop mobile client apps to communicate with Microsoft Dynamics AX from phone or tablet platforms. Authors: Jagruti Pandya and Rob Drollinger, Software Engineers May 2013 http://go.microsoft.com

Developing Secure Mobile Apps for Microsoft Dynamics …download.microsoft.com/download/E/7/C/E7C983FE-004E-42C1-A6EB...6 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

  • Upload
    lamcong

  • View
    226

  • Download
    1

Embed Size (px)

Citation preview

Microsoft Dynamics

®

AX

Developing secure mobile

apps for Microsoft Dynamics

AX 2012

White Paper

This document describes how to develop mobile client apps to communicate with Microsoft Dynamics AX from phone or tablet

platforms.

Authors: Jagruti Pandya and Rob Drollinger, Software Engineers

May 2013

http://go.microsoft.com

2 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Table of Contents

Introduction ................................................................................................ 4 Technical overview ................................................................................................................ 4 An Application Integration Framework custom service ............................................................... 5 Active federation for claims-based authentication to the Windows Azure Service Bus by using ACS

and ADFS on the client .......................................................................................................... 6

Outline of the walkthroughs........................................................................ 6

Design and create the AIF service in Microsoft Dynamics AX 2012 ............. 7 Overview ............................................................................................................................. 7 Development requirements .................................................................................................... 7 Create the data contract ........................................................................................................ 8 Create the data members for the data contract......................................................................... 8 Create the service class ......................................................................................................... 9 Create the service operations ................................................................................................. 9 Create the service contract ...................................................................................................10 Create a privilege to secure the service operation ....................................................................11 Create a basic inbound integration port ..................................................................................11 Verify that the service has been correctly deployed ..................................................................12

Establish a listener to the Windows Azure Service Bus ............................. 12 A middle-tier WCF service .....................................................................................................13 AIF Windows Azure Service Bus Adapter .................................................................................14 Comparing the Middle-tier WCF Service and the AIF Windows Service Bus Adapter ......................14 Create the middle-tier WCF service ........................................................................................15

Prerequisites .................................................................................................................... 15 Overview ......................................................................................................................... 16 Development requirements ................................................................................................ 16 Create the service contract and operation contract ................................................................ 16 Add a service reference of the AIF service ............................................................................ 18 Call the AIF service operations ........................................................................................... 20 Set up the Service Bus relay and deploy the listening endpoint for the middle-tier WCF service .. 22 Validate and extract contents from incoming messages ......................................................... 27 Build and deploy the middle-tier WCF Windows service .......................................................... 30

Deploy the AIF service using the AIF Windows Azure Service Bus Adapter. ..................................30 Prerequisites .................................................................................................................... 30 Overview ......................................................................................................................... 31 Authentication Overview .................................................................................................... 31 Create Custom Authentication Classes ................................................................................. 31 Registering the authentication component ........................................................................... 33 Encryption Key Containers ................................................................................................. 34 Publish AIF Service using the Service Bus Adapter ................................................................ 35

3

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Develop the client to communicate data to the middle-tier WCF service ... 38 Development requirements ...................................................................................................38 Overview ............................................................................................................................38 Create a Windows Phone application ......................................................................................38

Add the middle-tier WCF service reference ........................................................................... 38 Lay out and set up the UI controls for required user input ...................................................... 40

Implement active federation and claims-based authorization for the mobile client ......................................................................................................... 42

Prerequisites (configuring the trusts) ......................................................................................42 Overview ............................................................................................................................43 Development requirements ...................................................................................................44 Implementation ...................................................................................................................44

Setup .............................................................................................................................. 44 Get user input .................................................................................................................. 46 Create and send the request for security token ..................................................................... 48 Create the ACS payload ..................................................................................................... 52 Additional notes and guidelines .......................................................................................... 56

Authenticate the user and send the data to the service ............................ 56

Developing RESTful JavaScript mobile apps for Microsoft Dynamics AX 2012 ......................................................................................................... 60

Design and create the AIF service in Microsoft Dynamics AX 2012..............................................61 Create the middle-tier RESTful service ....................................................................................61

Prerequisites .................................................................................................................... 62 Development requirements ................................................................................................ 62 Create the data contract, service contract, and operation contract .......................................... 62 Add a service reference of the AIF service ............................................................................ 65 Call the AIF service operations ........................................................................................... 65 Configure the RESTful service bindings and deploy the listening endpoint on Service Bus........... 65 Validate and extract contents from incoming JSON messages ................................................. 68

Create an HTML5/JavaScript app to communicate data to the WCF middle-tier RESTful service ......71 Implement active federation and claims-based authorization for the mobile client by using

JavaScript ...........................................................................................................................71 Send the request payload to the REST service .........................................................................74

Additional resources ................................................................................. 77

4 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Introduction

This document describes how to create mobile client applications (apps) that enable Microsoft Dynamics AX users to communicate information with Microsoft Dynamics AX 2012.

Microsoft offers applications for key mobile scenarios on certain platforms and devices that are compatible with Microsoft Dynamics AX 2012. Microsoft Dynamics customers and partners have a rich ecosystem and powerful story for customizing and extending Microsoft Dynamics AX for the needs of individual organizations and industries. One important goal of this document is to empower our customers and partners to use Microsoft Dynamics AX to create delightful user experiences from any

device that works with their customizations.

This document provides walkthroughs of a solution that addresses the simple user scenario of an

employee capturing information about expenses that the employee incurred while traveling. The document is only meant to teach you the fundamentals of getting devices anywhere in the world talking to Microsoft Dynamics AX. The scenarios you can choose to implement with these lessons are up to your business requirements and your imagination. You can easily envision several exciting

scenarios, such as time management, access to customer information while traveling to a customer site, creating sales orders, managing your projects on the road, or just checking up on the factory from across town on your phone or tablet.

Technical overview

The solution architecture described in this document lets users receive information and send

transactions to Microsoft Dynamics AX 2012, even if they are not in the same domain or network as the on-premises instance of Microsoft Dynamics AX. For example, the solution lets clients access a Microsoft Dynamics AX service that is running behind a firewall. The solution has the following requirements:

An Application Integration Framework (AIF) service communicates data to and from Microsoft Dynamics AX 2012.

Users provide their corporate credentials in the mobile client to interact with Microsoft Dynamics AX 2012 services created for their scenarios.

Only authenticated and authorized users can communicate with Microsoft Dynamics AX services by using client applications.

5

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

The following diagram illustrates how different components interact to enable the mobile app to communicate with Microsoft Dynamics AX.

FIREW

ALL

MOBILECLIENT APPLICATION

Active Directory Federation Services

(ADFS)

AD DOMAIN CONTROLLER

AX 2012AOS, SQL + AIF service

Windows Azure

SERVICE BUS

ACCESS CONTROLSERVICE (ACS)

TOKEN SIGNINGCERTIFICATE

HTTP RELAY BINDING SHA

RE

D SE

CR

ET

MIDDLE-TIER WCF SERVICE OR

IIS 7.5 AIF ROUTING SERVICE

RST: REQUEST FOR SECURITY TOKENRSTR: REQUEST FOR SECURITY TOKEN RESPONSE

Figure 1 Architectural overview of the entire mobile solution

An Application Integration Framework custom service

Design an AIF service that can be consumed for the necessary business scenario. To do this, you will need to do the following:

Create AIF service and data contracts, and deploy a basic inbound port to expose the service operations for consumption.

Implement the service methods in an X++ classes to perform data operations with Microsoft

Dynamics AX 2012.

The AIF service alone works well for clients who want to consume the service when they are in the

same network or domain. However, for mobile scenarios, this would not be useful, because the mobile client will need to communicate with the AIF service hosted on an Application Object Server (AOS) instance that is deployed behind a corporate firewall. Instead of configuring changes in the firewall, such as exposing an Internet Information Services (IIS) server externally to expose the on-premises service, we make use of a secured Service Bus relay.

The Microsoft Windows Azure Service Bus and its relayed messaging capability enable applications on other networks to communicate with a system or application that reside on-premises on another

network or behind a firewall.

6 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

We provide two development patterns that leverage the Service Bus’s relayed message capability:

A custom-built middle-tier WCF service This pattern involves building a middle-tier WCF service that establishes a listener for the Service Bus and routes messages to Microsoft Dynamics AX services according to the routing

behavior that the developer chooses.

Publishing a service using the AIF Windows Azure Service Bus Adapter This pattern leverages the AIF Windows Azure Service Bus Adapter, which provides a Service Bus listener, hosts the listener in IIS, and routes messages to the AIF service that was deployed using the adapter.

You have the flexibility to decide which pattern best fits your application and business requirements. The development patterns are described in Establish a listener to the Windows Azure Service Bus. A

table comparing their features is included.

Note: The example mobile application described in this document uses the middle-tier WCF service. A service deployed with the AIF Windows Azure Service Bus Adapter can be consumed by following the same guidance.

Active federation for claims-based authentication to the Windows

Azure Service Bus by using ACS and ADFS on the client

The Service Bus’s dedicated Access Control Service (ACS) plays a very important role in this solution, controlling the authorization to call a service registered on the Service Bus. It enforces authorization

by requiring that the client provide a security token that is issued by a trusted identity provider that authenticates the user.

We use active federation to authenticate the user and acquire the user’s identity claims. This involves the mobile client actively requesting a security token (containing a set of claims identifying the user) from the corporate Active Directory Federation Services (AD FS) 2.0 by using the WS-Trust protocol. The client will then present this security token containing the claims to the ACS, which will then grant

a simple web token (SWT) as a form of authorization for the client to securely send messages via the Service Bus.

For the mobile solution, you will need to use an existing corporate AD FS as an identity provider (IdP) to authenticate the user credentials originating from the app. The AD FS will also be used as the security token service (STS) to provide identity claims about the user that will eventually be consumed by the Microsoft Dynamics AX 2012.

We will walk you through implementing the described solution in detail. We will also provide sample

code and configuration guidance to help you develop mobile applications for Microsoft Dynamics AX 2012 by using services.

Outline of the walkthroughs

The rest of the document will walk you through the components that you need to implement to create

secure mobile applications for Microsoft Dynamics AX 2012.

In these walkthroughs, we will be using a simple unreconciled expense capture scenario to illustrate a sample mobile application. In this scenario, an employee of a company that uses the Microsoft Dynamics AX 2012 Time and expense management feature will use the mobile application to capture details of an expense that the employee incurs when on the move.

We will use this scenario in all our services, and also in client code samples.

You will need to do the following walkthroughs in this document:

1. Design and create the AIF service in Microsoft Dynamics AX 2012

2. Establish a listener to the Windows Azure Service Bus

7

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. Develop the client to communicate data to the middle-tier WCF service

4. Implement active federation and claims-based authorization for the mobile client

5. Authenticate the user and send the data to the service

Design and create the AIF service in Microsoft Dynamics AX 2012

Overview

As mentioned in earlier, our example illustrates how a Microsoft Dynamics AX user employee can submit expenses from a mobile client when the user is on the move. When the expense makes it into Microsoft Dynamics AX, the expense shows up in the system as an unreconciled expense, which the

employee can then add to an expense report.

We need to implement an AIF service that accepts this expense data coming from the middle-tier WCF Service, processes it, and then pushes it into the Microsoft Dynamics AX 2012 database.

In this walkthrough, we will guide you through the implementation and deployment of the custom AIF

service for our mobile example. We will be using some of the existing expense data types and also the existing TrvUnreconciledExpenseTransaction table (which comes with the Travel and expense module in Microsoft Dynamics AX 2012).

We will create a service contract for the AIF service that will be exposed to the clients consuming this service. In our expense capture example, the middle-tier WCF service will consume the AIF service that we create (named UnreconciledExpenseService).

For more guidance about creating custom AIF services, see Walkthrough: Exposing an X++ Class as a Data Contract [AX 2012].

Note: The following example uses a standard implementation of custom AIF service functionality. If you are already familiar with this, you can skip this section.

Note: Although this example walks you through exposing a custom AIF service, you can apply the same principles to utilize Microsoft Dynamics AX document services or system services, such as the query service.

The following points summarize the walkthrough article mentioned earlier:

1. Create the data contract. This is the data object that is passed into the service call.

2. Create the data members that will be exposed as part of the data contract.

3. Define the service class.

4. Implement the service operations offered by the service contract.

5. Add the service class to the Application Object Tree (AOT).

6. Create a basic inbound port for the service to deploy the service.

7. Activate the port to make it consumable by external clients.

Development requirements

To complete this walkthrough, you will need the following:

Microsoft Dynamics AX 2012 installed and configured, together with the Active Directory server

A development license for Microsoft Dynamics AX 2012

8 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

For our sample code, which covers an expense capture scenario:

The Travel and expense management module in Microsoft Dynamics AX 2012

The Human resources module in Microsoft Dynamics AX 2012

Microsoft Dynamics AX users added and mapped to workers, with the Employee role

Create the data contract

1. In the Developer Workspace, create a class in the AOT named UnreconciledExpenseRecord. Set the RunOn property to Called from.

2. In the class declaration, define the data members. For our expense capture scenario, we want the

user to send the expense amount, currency, expense date, and some notes.

3. Apply the DataContractAttribute attribute to the class.

X++

[DataContractAttribute]

public class UnreconciledExpenseRecord

{

TransDate transactionDate;

TrvFreeText notes;

AmountCur transactionCurrencyAmount;

CurrencyCode transactionCurrencyCode;

}

Create the data members for the data contract

Add new methods in the class, and apply the DataMemberAttribute attribute to these methods.

X++

[DataMemberAttribute]

public TrvFreeText parmNotes(TrvFreeText _notes = notes)

{

notes = _notes;

return notes;

}

[DataMemberAttribute]

public AmountCur parmTransactionCurrencyAmount(

AmountCur _transactionCurrencyAmount = transactionCurrencyAmount)

{

transactionCurrencyAmount = _transactionCurrencyAmount;

return transactionCurrencyAmount;

}

[DataMemberAttribute]

public CurrencyCode parmTransactionCurrencyCode(

CurrencyCode _transactionCurrencyCode = transactionCurrencyCode)

{

transactionCurrencyCode = _transactionCurrencyCode;

return transactionCurrencyCode;

}

9

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

X++

[DataMemberAttribute]

public TransDate parmTransactionDate(TransDate _transactionDate = transactionDate)

{

transactionDate = _transactionDate;

return transactionDate;

}

Create the service class

Create a class in the AOT named UnreconciledExpenseService, and set the RunOn property to

Server.

The class declaration is as follows.

X++

/// <summary>

/// The <c>TrvUnreconciledExpenseService</c> is the unreconciled

/// expense transaction Web service class.

/// </summary>

public class UnreconciledExpenseService

{

// These macros are used to specify the SubCode on AifFaults.

// Their values will not be translated allowing the consumer

// of the service to identify the cause

// of the fault and take appropriate action.

#DEFINE.ParameterValidationError('ParameterValidationError')

#DEFINE.UnreconciledExpenseCreationFailed('UnreconciledExpenseCreationFailed')

}

Create the service operations

In the UnreconciledExpenseService class, create a public method named createRecord, which will take a reference of an unreconciled expense transaction that the user submitted and insert the data into the TrvUnreconciledExpenseTransaction table.

X++

[SysEntryPointAttribute(true)]

public recId createRecord(UnreconciledExpenseRecord _unreconciledExpenseRecord)

{

TrvUnreconciledExpenseTransaction unreconciledExpenseTrans;

recId createdRecId;

recId workerId;

if (!_unreconciledExpenseRecord) // An instance of data contract class is required

{

throw error(Error::wrongUseOfFunction(funcname()));

}

10 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

X++

workerId = DirPersonUser::findUserWorkerReference(curUserId());

//Validates if user is related to a worker in AX

if (workerId == 0)

{

throw AifFault::faultList("@SYS335749", #ParameterValidationError);

}

ttsbegin;

unreconciledExpenseTrans.TransDate = _unreconciledExpenseRecord.parmTransactionDate();

unreconciledExpenseTrans.Worker = workerId;

unreconciledExpenseTrans.Notes = _unreconciledExpenseRecord.parmNotes();

unreconciledExpenseTrans.TransactionCurrencyAmount =

_unreconciledExpenseRecord.parmTransactionCurrencyAmount();

unreconciledExpenseTrans.TransactionCurrencyCode =

_unreconciledExpenseRecord.parmTransactionCurrencyCode();

if (unreconciledExpenseTrans.validateWrite())

{

unreconciledExpenseTrans.insert();

}

ttscommit;

createdRecId = unreconciledExpenseTrans.RecId;

if (!createdRecId)

{

//Creation of record failed

throw AifFault::faultList("@SYS335750, #UnreconciledExpenseCreationFailed);

}

return createdRecId;

}

As you can see in the preceding code, we are fetching the worker who is associated with the expense based on a current user ID. As you will see in the Create the middle-tier WCF service section, the call to the service operation is made under the context of the mobile Microsoft Dynamics AX user submitting the request by setting the CallContext property. Therefore, the curUserId value will be

the Microsoft Dynamics AX user ID of the original user submitting the request.

Create the service contract

To create the service contract that is made available to clients consuming the service, create a new service in the Services node of the AOT that implements the service class we created (UnreconciledExpenseService). You must also add the operation exposed by the class

(createRecord). For guidance, see Walkthrough: Exposing an X++ Class as a Data Contract [AX 2012].

11

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Create a privilege to secure the service operation

At this point, we want to create a special privilege to help provide secure access when the createRecord method is called. We require that this privilege be added to the Employee role (AOT name: HCMEmployee), so that only those users who have this privilege call the createRecord service method.

Create a privilege and add the operation to the Entry Points object of the Privilege.

1. In the Development workspace go to AOT > Security > Privileges > Right click and New Privilege.

2. Add a privilege and name it UnreconciledExpenseServiceCreate.

3. Go to the Entry Point node and right click and add a New Entry point and set:

Property Value

Name UnreconciledExpenseServiceCreate

ObjectType ServiceOperation

ObjectName UnreconciledExpenseService

ObjectChildName createRecord

AccessLevel Invoke

4. You can now add this Privilege to the Duty TrvTravelAndExpenseServiceOperations. (AOT> Security>Duties>New Privilege)

Note: This duty is already incorporated in the HCMEmployee role’s list of duties.

Note: If you have Dynamics AX 2012 R2 installed, you will also need to add two more privileges

(LogisticsAddressCountryRegionView and LogisticsPostalAddressView) to the TrvTravelAndExpenseServiceOperations duty for the above implemented createRecord operation to work correctly.

Create a basic inbound integration port

The following instructions pertain to the middle-tier WCF service only. When using the AIF Windows Azure Service Bus

Adapter, do not create a “basic” inbound integration port. Instead, go to Deploy the AIF service using the AIF Windows

Azure Service Bus Adapter.

In order to deploy the service we must create a basic inbound integration port.

First, we need to register the service in the AOT:

Go to the Service that we created in the step above: \Services\UnreconciledExpenseService.

12 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Right-click > Add-Ins > Register service. The AIF services window will open. Verify if the service that you created is in the list of AIF services. Close the form.

Next, we need to activate the port in order to make it available to external clients:

Click System Administration > Setup > Services and Application Integration Framework > Inbound

ports.

Click New to create a new inbound port for this service. Specify a Port name for example: UnreconciledExpense

Click on Service operations to add a required service operation. In our example, add operation UnreconciledExpenseService.createRecord from the list of remaining service operations and then close.

Click Activate to activate the port.

Verify that the service has been correctly deployed

1. In the Inbound ports form, copy the WSDL URI.

2. Open the WSDL URI in a browser to view the WSDL file. To consume the service, clients need to add the WSDL URI address as the service reference to generate the service proxy.

Establish a listener to the Windows Azure Service Bus

Both the AIF service that is published using the Service Bus adapter and a middle-tier WCF service will establish a listener to the Windows Azure Service Bus. This listener is an out-bound connection to the Service Bus on which incoming messages from clients are relayed. A message relayed in this manner is then routed to Microsoft Dynamics AX by a routing service hosted in IIS 7.5 (if using the Service

Bus adapter) or by the routing service in the middle-tier WCF service.

13

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

A middle-tier WCF service

Creating a WCF service that deploys its listening endpoint on a Windows Azure Service Bus namespace involves the following tasks:

Define a service contract that is in line with the requirements of the AIF service contract (that is, clients pass data that is required by the AIF service per the business scenario).

Define a URI that is used to listen on the Service Bus—for example, https://<AzureNamespace>.servicebus.windows.net/Expense/.

Set up a secure channel (HTTP relay binding) with the Service Bus.

Extract information from the incoming message sent by the client. (The client application creates its request by using the service proxy generated from the WCF service, and sends the request to this endpoint URI. The Service Bus will relay the message to the middle-tier WCF service). The

WCF service then calls the AIF service and passes all the data the AIF service needs.

It is very important that only authorized users be allowed to send and receive messages through the Service Bus. In addition, we require that only authorized users be able to make calls to the WCF service. These users exist in an enterprise’s Active Directory Domain Services and can be

authenticated by a deployed Active Directory Federation Service (AD FS).

Furthermore, we need to call the AIF service in the context of the authorized user, and therefore need information about the user in the data that is passed from the client to the WCF service.

14 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

AIF Windows Azure Service Bus Adapter

The AIF Windows Azure Service Bus Adapter extends the existing AIF functionality and uses IIS 7.5 to provide a method to deploy services by using cloud computing. The following infrastructure helps accomplish this:

IIS 7.5

The Service Bus adapter leverages IIS to host Microsoft Dynamics AX services published with an HTTP adapter, or by using the new Service Bus adapter. IIS hosts the Service Bus listener and a routing service (both of which are WCF services) that work in tandem to pass messages

from the Service Bus to Microsoft Dynamics AX.

Authentication Classes

Each call to Microsoft Dynamics AX services through the Service Bus must be authenticated.

With the Service Bus adapter hotfix, the AIF now allows registering authentication classes to authenticate inbound Service Bus messages and extract the user’s Microsoft Dynamics AX credentials. Registering authentication classes is a one-time configuration step, and the authentication classes can be used across multiple Service Bus namespaces and published

services after they are registered.

AIF Service Bus Namespace Registration

Registering a Service Bus namespace is a one-time step for each namespace you wish to use. Registration includes supplying the namespace name, access key credentials, authentication classes, and X.506 signing certificate that is used to sign the ADFS SAML token. The AIF uses all of these in order to establish trust with the Service Bus before opening a connection.

AIF Windows Azure Service Bus Adapter

After you have registered a Service Bus namespace with AIF, you can begin publishing Microsoft Dynamics AX services by using the AIF Windows Azure Service Bus Adapter. The process of publishing Microsoft Dynamics AX AIF services has not changed. Create a new port

(using the form AifInboundPorts form), select the AIF Windows Azure Service Bus Adapter, and then select the service operations to expose on the port. After you activate the port, your service will be accessible from the cloud. For more information about adapters, see

http://msdn.microsoft.com/EN-US/library/gg751348.aspx.

All of these items are described in detail in Deploy the AIF service to the Azure Service Bus.

Comparing the Middle-tier WCF Service and the AIF Windows Service Bus Adapter

Use the following table to compare the capabilities and requirements of the Middle-tier WCF service and the AIF Windows Azure Service Bus Adapter. Both options provide solutions for mobile application development, but they differ in implementation, infrastructure, and technical capabilities. The following table highlights the differences.

Middle-tier WCF Service AIF Windows Azure Service Bus Adapter

Configuration and Setup

Requires developing the Middle-tier WCF service.

Can be configured by an administrator. Configuring custom authentication may require a developer.

IIS Does not require IIS Requires IIS 7.5 to host the Service Bus listener.

Failover Support

Failover is handled by installing multiple middle-tier WCF services on separate machines.

Failover is handled through available IIS failover strategies.

15

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Multiplicity Can listen to multiple Service Bus namespaces simultaneously from one middle-tier WCF service instance.

Each Service Bus namespace must be registered with exactly one IIS website.

Routing to multiple AX

instances

Each middle-tier WCF service can serve multiple AX instances. The WCF service developer creates this routing behavior.

An IIS instance can host multiple websites. Each IIS website can serve a different Microsoft Dynamics AX instance. Each website is tied to exactly one Service Bus namespace within a Microsoft Dynamics AX instance. We recommend that you do not share a website across Microsoft Dynamics AX instances.

REST support Can be configured to expose a RESTful endpoint, or any other service contract type and binding that is possible in WCF as a façade for the backing AIF service.

Not currently supported. The SOAP service contract exposed to the client on Service Bus is always identical to the service contract as defined in Microsoft Dynamics AX.

Protocol support

Endpoints hosted on Service Bus can support any transport (such as HTTP andNet.Tcp) or messaging (such as SOAP and JSON) protocols available for a WCF service, including custom message encoders or other service behaviors (enabling compression or other message manipulation or inspection, for example).

Supports only HTTPS for service calls.

Logging and eventing

As part of configuring the Middle-tier WCF

service, a developer must write a logging service.

Logs connection status in IIS event log.

Authentication Endpoints can be either authenticated or unauthenticated (to allow client bootstrapping traffic, for example).

Endpoints must always be authenticated, so it is the client’s responsibility to know which identity provider to authenticate against.

Choosing between the two approaches is primarily a matter of balancing customizability with

development costs. The middle-tier WCF service has higher development costs because it requires you to manually create and install a WCF service that listens to the Service Bus and routes service calls to Microsoft Dynamics AX. However, with the middle-tier WCF service you can use the messaging protocols of your choice, expose different contracts to your clients, provide custom message routing behavior, and serve multiple installations of Microsoft Dynamics AX or other back-end systems.

The Service Bus adapter has a lower development cost because automatically creates a WCF service and hosts it in IIS. By using the Service Bus adapter, your only development costs are in configuration: providing Service Bus information (namespace, access key), AD FS information (certificate thumbprint), and registering authentication classes. However using the Service Bus adapter does not allow customization of the WCF service that is hosted in IIS. The WCF service hosted in IIS can perform only the action of authenticating and routing service calls. The routing behavior

only supports routing relayed messages to the installation of Microsoft Dynamics AX that the service was published from.

Next, we will walk through the steps that are necessary to build the middle-tier WCF service, followed by the steps that are necessary to publish a service using the AIF Windows Azure Service Bus Adapter.

Create the middle-tier WCF service

Prerequisites

An X.509 token signing certificate is installed on the AD FS 2.0 server and on the machine running the WCF service, in the Trusted Root Certification Authorities store. For guidance, see Microsoft Dynamics AX Connector for Mobile Applications.

You have the thumbprint from that certificate.

16 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

A Windows Azure Service Bus namespace has been created, and the shared secret and issuer name for the namespace are available. For guidance, see Microsoft Dynamics AX Connector for Mobile Applications.

The machine that the middle-tier WCF service runs on should be in the same domain or on the

same network as the Microsoft Dynamics AX 2012 AOS machine (which can be the same machine or a different one).

Overview

The following steps are required to create the WCF SOAP-based service that will receive service requests from the mobile client, relayed by the Service Bus.

For the following example, we will create the WCF service as a Windows service.

Development requirements

Microsoft Visual Studio 2010 and the Microsoft .NET Framework version 4.

The Service Bus component (Microsoft.ServiceBus.dll), which is included with the Windows Azure Libraries for .NET. To install it, visit the Windows Azure SDK download page.

The Windows Identity Foundation runtime, which can be downloaded from Windows Identity

Foundation (WIF) SDK. Download the 4.0 version for Visual Studio 2010 and the .NET Framework version 4.0.

For more information about the WIF SDK, see Windows Identity Foundation SDK.

Create the service contract and operation contract

1. Open Visual Studio, and create a new Windows Service .NET Framework version 4 project named ExpenseConnectorService.

17

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

2. Rename the Service1.cs class ConnectorService.cs. This class contains the OnStart and OnStop methods for the Windows service, which we will use to open a listening endpoint.

C#

using System.ServiceModel;

using System.ServiceProcess;

namespace ExpenseConnectorService

{

public partial class ConnectorService : ServiceBase

{

private ServiceHost host;

public ConnectorService()

{

InitializeComponent();

}

protected override void OnStart(string[] args)

{

// Deploy the endpoint

}

protected override void OnStop()

{

// Close the endpoint connection

}

}

}

3. Add the System.ServiceModel reference to the project, and include the System.ServiceModel namespace in all the following classes.

4. Add a new C# interface for the service contract, named IExpenseService, to the project, and create the service contract and operation contract as shown here.

C#

[ServiceContract(Name = "ExpenseServiceContract",

Namespace = "http://samples.microsoft.com/DynamicsAx/")]

public interface IExpenseServiceContract

{

[OperationContract]

long CreateExpense(DateTime dateTime, decimal amount, string currency, string comments);

}

18 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

5. Create another C# class for the service operation implementation.

Per the contract we created, create a class named ExpenseService, which implements the IExpenseServiceContract interface.

C#

[ServiceBehavior(Name = "ExpenseService")]

public class ExpenseService : IExpenseServiceContract

{

public long CreateExpense(DateTime dateTime, decimal amount, string currency, string

comments)

{

// Implementation

}

}

Any client consuming this service will make a call to the service’s CreateExpense operation and

will be required to pass information as stated in the method parameters.

Later, we will add code to this method that will process the incoming SOAP message in the following way:

Extract the Security Assertion Markup Language (SAML) token from the header of the message. The token is issued by the identity provider (the corporation’s Active Directory Federation Service).

Perform token validation.

Extract the claim assertion that was requested (the windowsaccountname claim).

Use the expense data embedded in the SOAP message body, and make a call to the AIF service operation.

All the processing, validating, and extracting of claims from the token is facilitated by the Windows Identity Foundation libraries.

Add a service reference of the AIF service

We need to generate a client proxy of the AIF service to gather the service contract, bindings, and address for the AIF endpoint. To add the service reference, we use the WSDL exposed by the inbound port that was activated in the Design and create the AIF service in Microsoft Dynamics AX 2012 section.

19

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

1. Go to Solution Explorer, right-click References, and then select Add service reference. In the Add Service Reference form, enter the WSDL address http://AOSMachine:8101/DynamicsAx/Services/UnreconciledExpense.

You will see the createRecord operation exposed by the service. Edit the namespace, naming it

AXExpenseServiceReference, and then click OK to add the reference to the project.

The reference shows up in the Service References node in Solution Explorer. Also observe that the client proxy file named Reference.cs is generated within the project in a folder (\Service References).

2. Observe that several changes have automatically been made to the app.config file in the project with regard to the bindings, security protocols, and so on, and also the URI of the endpoint deployed to enable the middle-tier service to communicate with the AIF endpoint on Microsoft

Dynamics AX. Verify that the following configuration values are created in the app.config file.

20 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

NetTcpBinding specification for connecting to the AIF endpoint exposed on the AOS server

APP.CONFIG

<system.serviceModel>

<bindings>

<netTcpBinding>

<binding name="NetTcpBinding_UnreconciledExpenseService" closeTimeout="00:01:00"

openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"

transactionFlow="false"

transferMode="Buffered" transactionProtocol="OleTransactions"

hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288"

maxBufferSize="65536" maxConnections="10" maxReceivedMessageSize="65536">

<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"

maxBytesPerRead="4096" maxNameTableCharCount="16384"/>

<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>

<security mode="Transport">

<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>

<message clientCredentialType="Windows"/>

</security>

</binding>

</netTcpBinding>

</bindings>

</system.serviceModel>

Definition of the endpoint address, binding configuration, and contract of the AIF service

APP.CONFIG

<client>

<!-- This address should be set to the URI of the endpoint deployed on AX.

It should be of the form:

"net.tcp://<AOS_MACHINE_NAME>:8201/DynamicsAx/Services/<INBOUND_PORT_NAME>" -->

<endpoint address="net.tcp://AOSMachine:8201/DynamicsAx/Services/UnreconciledExpense"

binding="netTcpBinding" bindingConfiguration="NetTcpBinding_UnreconciledExpenseService"

contract="AXExpenseServiceReference.UnreconciledExpenseService"

name="NetTcpBinding_UnreconciledExpenseService">

</endpoint>

</client>

As shown in the <client> element, the endpoint address can be configured to point to a machine that hosts the AOS machine on which the AIF service is deployed and activated. In this way, the

middle-tier service can be run on any machine, provided that it is on the same network as the AOS machine, to make the service call by using the NetTcp binding.

Call the AIF service operations

After you have added the service reference, the next step is to use its operation contract and make the necessary method call.

21

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

1. Include the AIF service namespace ExpenseConnectorService.AXExpenseServiceReference in the ExpenseService class.

C#

using ExpenseConnectorService.AXExpenseServiceReference;

2. Create a new private method named SubmitExpenseToAX, which will do the following:

1. Populate the values of the UnreconciledExpenseRecord data member of the UnreconciledExpenseService AIF service

2. Call UnreconciledExpenseService’s createRecord operation

3. Return the result (the RecID value returned by the AIF service operation)

Later, we will call this method in the exposed service operation (CreateExpense).

C#

private long SubmitExpenseToAX(DateTime dateTime, decimal amount, string currency,

string comments, string windowsAccountName)

{

UnreconciledExpenseRecord record = new UnreconciledExpenseRecord()

{

parmNotes = comments,

parmTransactionCurrencyAmount = amount,

parmTransactionDate = dateTime,

parmTransactionCurrencyCode = currency

};

using (UnreconciledExpenseServiceClient client = new

AXExpenseServiceReference.UnreconciledExpenseServiceClient())

{

UnreconciledExpenseRecord expenseRecord = record;

CallContext callContext = new CallContext() { LogonAsUser = windowsAccountName };

return client.createRecord(callContext, expenseRecord);

}

}

The preceding method creates an instance of the service’s client, sets the data member values, and then makes the final call to the createRecord operation. Also notice the CallContext object that is passed into the service call. In Microsoft Dynamics AX, values such as the user, company,

and so on can be used when the service call is executed and are sent in the message header from the service client by using the CallContext object.

In our example, we want to pass the mobile user’s information when making the createRecord

call, so that the unreconciled expense is created in the context of the user.

LogonAsUser has been set to windowsAccountName. This is the value of the claim that was requested from the AD FS (in the form domain\userAlias) and identifies the user who submitted the request from the client. Remember that this user must exist in the Microsoft Dynamics AX

system, and because Microsoft Dynamics AX uses the same Active Directory service as the identity provider, it will recognize and then be able to authorize this user.

22 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Set up the Service Bus relay and deploy the listening endpoint for the middle-tier

WCF service

To configure the middle-tier service’s endpoint to listen on the Service Bus, we need to update the app.config file as follows:

Add a BasicHttpRelayBinding binding for communicating with the Service Bus.

Provide the service contract name and the service endpoint address.

Set up the required binding configuration by specifying Service Bus credentials.

1. Define the BasicHttpRelayBinding configuration by adding the following under the <bindings> element in the <system.serviceModel> section.

APP.CONFIG

<basicHttpRelayBinding>

<binding name="BasicHttpRelayBinding_ServiceBus">

<security mode="Transport" relayClientAuthenticationType="RelayAccessToken"/>

</binding>

</basicHttpRelayBinding>

The preceding configuration sets the binding to have end-to-end transport security. We also set the value of the relayClientAuthenticationType parameter to RelayAccessToken, which forces clients of the service to authenticate to the Service Bus before sending across any messages.

As shown in Figure 1, to connect to the Service Bus, the client presents the Service Bus with the security token (SWT) issued by the ACS.

23

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

2. Define configuration values for the endpoint behavior.

APP.CONFIG

<behaviors>

<endpointBehaviors>

<behavior name="sharedSecretClientCredentials">

<transportClientEndpointBehavior credentialType="SharedSecret">

<clientCredentials>

<!-- The issuerName & issuerSecret here should be set to the values

for the service account on Service Bus you wish to use to listen.

By default, the namespace will come with an admin user (issuerName) of

"owner" with a 256-bit secret key (issuerSecret) available in the

Windows Azure management portal.-->

<sharedSecret issuerName="owner"

issuerSecret="xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxx="/>

</clientCredentials>

</transportClientEndpointBehavior>

</behavior>

</endpointBehaviors>

</behaviors>

As shown in the preceding configuration, transportClientEndpointBehavior is used to specify the Service Bus credentials for the endpoint that will be deployed on the Service Bus.

The shared secret values of issuerName and issuerSecret are values of Default Issuer and Default Key of your namespace that was set up in Windows Azure Management Portal.

Note: If you want to collect the necessary information from the user at run time via a UI,

System.ServiceModel and Microsoft.ServiceBus provide APIs to set all these configuration values programmatically.

3. Deploy the listening endpoint.

To specify the service contract for the middle-tier service, the binding, and the behavior configuration (all of which were defined in the preceding points), add the following code snippet in the app.config file, under the <services> element.

APP.CONFIG

<services>

<service name="ExpenseConnectorService.ExpenseService">

<endpoint address="" behaviorConfiguration="sharedSecretClientCredentials"

binding="basicHttpRelayBinding"

contract="ExpenseConnectorService.IExpenseServiceContract"/>

<host>

<baseAddresses>

<!-- This baseAddress should be set to the URI you intend to

listen to on the Service Bus. It should be of the form:

"https://<APPFABRIC_NAMESPACE>.servicebus.windows.net/Expense/" -->

<add baseAddress="https://contosomobile.servicebus.windows.net/Expense/"/>

</baseAddresses>

</host>

</service>

</services>

24 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

4. Deploy the metadata endpoint for the service.

To generate a client proxy for our mobile client, we will need to expose a metadata endpoint address.

Under the <behaviors>/<serviceBehaviors> node, add the following. Make sure that you

enable the serviceMetadata node.

APP.CONFIG

<serviceBehaviors>

<behavior name="serviceMetadata">

<!-- To receive exception details in faults for debugging purposes,

set the value below to true. Set to false before deployment to

avoid disclosing exception information -->

<serviceDebug includeExceptionDetailInFaults="False"/>

<!--Enable this element when publishing metadata-->

<serviceMetadata />

</behavior>

</serviceBehaviors>

We now need to update the <services> section that we used to specify the service contract, binding, and behavior configurations. Set behaviorConfiguration to serviceMetadata, and then

add a local MEX endpoint.

APP.CONFIG

<services>

<service name="ExpenseConnectorService.ExpenseService"

behaviorConfiguration="serviceMetadata">

<endpoint address="" behaviorConfiguration="sharedSecretClientCredentials"

binding="basicHttpRelayBinding"

contract="ExpenseConnectorService.IExpenseServiceContract"/>

<endpoint contract="IMetadataExchange" binding="mexHttpBinding"

address="http://localhost/mex" />

<host>

<baseAddresses>

<!-- This baseAddress should be set to the URI you intend to listen on the Service

Bus

It should be of the form:

"https://<APPFABRIC_NAMESPACE>.servicebus.windows.net/Expense/" -->

<add baseAddress="https://contosomobile.servicebus.windows.net/Expense/"/>

</baseAddresses>

</host>

</service>

</services>

The client proxy that consumes this service can then be generated by using the http://<MiddleTierServiceMachineName>/mex metadata URI.

25

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

5. We also need to update the app.config file to register the preceding Service Bus behavior and binding extensions.

APP.CONFIG

<extensions>

<behaviorExtensions>

<add name="transportClientEndpointBehavior"

type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement,

Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35"/>

</behaviorExtensions>

<bindingExtensions>

<add name="basicHttpRelayBinding"

type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement,

Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35"/>

</bindingExtensions>

</extensions>

6. Finally, open the Service Bus connection, and start listening on the endpoint.

Note: The on-premises service connects to the relay service over ports 9350–9354; however, if these are unavailable, the service will try to call back to port 80 (HTTP) or 443 (HTTPS).

Add the following code snippets to the OnStart method in the ConnectorService class.

C#

protected override void OnStart(string[] args)

{

// Note that all binding, endpoint, service, behavior configuration

// for this ServiceHost is located in the app.config

host = new ServiceHost(typeof(ExpenseConnectorService.ExpenseService));

WriteToEventViewer("Opening the Service endpoint connection " +

host.BaseAddresses[0].ToString());

try

{

host.Open();

WriteToEventViewer(string.Format("Listening on: {0}",

host.Description.Endpoints.Find(

typeof(ExpenseConnectorService.IExpenseService)).Address));

}

catch (Exception e)

{

WriteToEventViewer(e.Message);

}

}

26 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

private void WriteToEventViewer(string eventMessage)

{

string source = "Expense WCF Service";

if (!EventLog.SourceExists(source))

EventLog.CreateEventSource(source, "Application");

EventLog.WriteEntry(source, eventMessage, EventLogEntryType.Information);

}

C#

protected override void OnStop()

{

host.Close();

}

You can also close the connection in the OnStop method. There are several events you may want to hook into and log, so that you can monitor the status of the relay binding and other such

events. You can log events in the event viewer by using System.Diagnostics.

27

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Validate and extract contents from incoming messages

The next step is to inspect the message coming from the client. The incoming SAML message contains a header that holds the windowsaccountname claim in the security token. This claim is issued by

the AD FS 2.0. For more information about requesting claims, see the Implement active federation and claims-based authorization for the mobile client section. Windows Identity Foundation is used to validate the security token and the issuer, after which we extract the claim that we need to make the AIF service call.

28 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

1. Update the app.config file, adding configuration values for handling the SAML security token issued by the AD FS.

APP.CONFIG

<microsoft.identityModel>

<service>

<securityTokenHandlers>

<securityTokenHandlerConfiguration>

<audienceUris mode="Never"/>

<issuerNameRegistry

type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry,

Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35">

<trustedIssuers>

<!-- The STS that issues the SAML token exchanged

at ACS must be added as a trusted issuer here.

The thumbprint & name values should be obtainable from the

public signing certificate exposed on the STS' federation metadata -->

<add thumbprint="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

name=""/>

</trustedIssuers>

</issuerNameRegistry>

</securityTokenHandlerConfiguration>

</securityTokenHandlers>

</service>

</microsoft.identityModel>

APP.CONFIG

<configSections>

<section name="microsoft.identityModel"

type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection,

Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35"/>

</configSections>

The issuer (also known as the identity provider—in our case, the corporate AD FS) uses a token

signing certificate to digitally sign the SAML token. Therefore, the thumbprint of the token signing certificate must be specified in the service’s configuration as shown in the first code snippet, in the <trustedIssuers> section. This will be used to validate the digital signature when the token is validated.

2. Add Microsoft.IdentityModel and System.IdentityModel references to the project, and add

the following namespaces to the ExpenseService.cs file.

C#

using System.IdentityModel.Tokens;

using Microsoft.IdentityModel.Claims;

using Microsoft.IdentityModel.Configuration;

3. Add an implementation to the CreateExpense service operation to do the following:

1. Extract the security token from the custom SOAP header PassthroughBinarySecurityToken.

This header information is passed by the mobile client calling the service.

29

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

2. Inspect the SAML token.

3. Use WIF to validate the token by using the thumbprint and other configuration values from the service configuration.

4. Extract the required claim (windowsaccountname) from the token.

5. Make the call to the SubmitExpenseToAX method, which will make the AIF service call.

C#

public long CreateExpense(DateTime dateTime, decimal amount, string currency, string

comments)

{

string samlTokenHeader =

(string)OperationContext.Current.IncomingMessageHeaders[OperationContext.Current.Incoming

MessageHeaders.FindHeader("PassthroughBinarySecurityToken", "")].ToString();

string encodedSamlToken = samlTokenHeader.Split('<', '>')[2];

byte[] binToken = Convert.FromBase64String(encodedSamlToken);

string samlToken = new string(Encoding.UTF8.GetChars(binToken));

// Load the app.config settings where we specify the audience & issuer that we'll

// accept in a token

var config = new ServiceConfiguration();

var handler =

config.SecurityTokenHandlers[

Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml11TokenProfile11];

ClaimsIdentityCollection claimsIdentity = null;

// Convert the raw token into something that can be inspected

using (XmlReader reader = XmlReader.Create(new StringReader(samlTokenString)))

{

SecurityToken token = handler.ReadToken(reader);

// This is the primary WIF call that

// 1) Performs all the token validation

// a. Format, token type, key type, version, etc.

// b. Expiration

// c. Audience/AppliesTo/Relying party

// d. Issuer

// e. Signature

// 2) generates a ClaimsIdentityCollection that contains what the app actually //

cares about

claimsIdentity = handler.ValidateToken(token);

}

IPrincipal principal = new ClaimsPrincipal(claimsIdentity);

IClaimsIdentity identity = (IClaimsIdentity)principal.Identity;

windowsAccountName = identity.Claims.Single(claim => claim.ClaimType ==

"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname").Value;

30 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

return SubmitExpenseToAX(expenseData, windowsAccountName);

}

Build and deploy the middle-tier WCF Windows service

1. Build the entire project.

2. Add the ProjectInstaller.cs file, and create an installer (Setup project) for the Windows service by following the guidance at Walkthrough: Creating a Windows Service Application in the Component Designer.

3. Make sure that you add the primary output from the ExpenseConnectorService project to the installer and all its dependencies (Microsoft.ServiceBus.dll, Microsoft.IdentityModel.dll, and the

.NET Framework dependencies).

The user account that the service is deployed and run should be the .NET Business Connector proxy account. By using a proxy, you guarantee that .NET Business Connector can connect on behalf of Microsoft Dynamics AX users when it authenticates with an AOS instance. For more information about how to create and set up the .NET Business Connector proxy account, see Specify the .NET Business Connector proxy account [AX 2012].

Also, note the following requirements for the .NET Business Connector proxy account:

It must be a Windows domain account.

It must be a dedicated account (used only by .NET Business Connector).

It must have a password that does not expire.

It must not have interactive logon rights.

It must not be a Microsoft Dynamics AX user.

In addition, it is important that the .NET Business Connector proxy user account be added as an Administrator on the machine running the service (so that it has access to the ports required to

deploy listening endpoints on the Service Bus).

4. Run the installer, and provide the .NET Business Connector proxy user’s user name and password, which will run the WCF Windows service.

Deploy the AIF service using the AIF Windows Azure Service Bus

Adapter

Prerequisites

The Service Bus component (Microsoft.ServiceBus.dll v1.8), which is included with the Windows

Azure Libraries for .NET. To install it, visit the Windows Azure SDK download page. (The Microsoft.ServiceBus.dll must be placed in the “Bin” folder of the website that the service is

deployed to)

You have installed the AIF Windows Azure Service Bus Adapter Hotfix: http://support.microsoft.com/kb/2845539

You have installed the AX Web Services on IIS 7.5.

An X.509 token signing certificate is installed on the AD FS 2.0 server and on the machine that is

running the WCF service, in the Trusted Root Certification Authorities store. For more information, see Microsoft Dynamics AX Connector for Mobile Applications.

You have the thumbprint from that certificate.

31

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

A Windows Azure Service Bus namespace has been created, and the shared secret and issuer name for the namespace are available. For more information, see Microsoft Dynamics AX Connector for Mobile Applications.

Overview

The following steps enable publishing an AIF service that listens to messages incoming from the Azure Service Bus, without a middle-tier WCF service.

You must register your Windows Azure Service Bus namespace with the AIF before you can publish services to the Service Bus. Registration requires that you supply the X++ and WCF authentication classes that will authenticate incoming Service Bus messages. Go to Create the authentication classes, and then go to Register your Service Bus namespace with the AIF. Next, see Publish your AIF service.

Authentication overview

The Service Bus requires each on-premises service to be authenticated and authorized to “listen” on a

particular address before establishing a new relay connection. Clients must also be authenticated and

authorized before the Service Bus will relay messages on their behalf. The Service Bus relies on ACS

for authenticating services and clients.

Service authentication

Microsoft Dynamics AX services use a “shared secret” token provider to authenticate with the Service

Bus. The shared secret is provided to the AIF when you Register your Service Bus Namespace.

Client authentication

The following two types of client authentication are required:

Service Bus authentication Clients are required to provide a “send” claim in order to be able to send messages to a

service on the Service Bus. The ACS must trust the identity provider used by the client. This must be set up as described in Microsoft Dynamics AX Connector for Mobile Applications.

Microsoft Dynamics AX authentication When the Service Bus relays a message to the on-premises service, the caller identity is used

to log on to Microsoft Dynamics AX. This caller identity is determined by calling a custom

authentication component to parse the incoming message token and to provide a valid claims

identity. The user specified by the claims identity must be a valid Microsoft Dynamics AX user.

Sample authentication component

A sample ADFS authentication component is provided here:

http://blogs.msdn.com/b/aif/archive/2013/04/29/aif-windows-azure-service-bus-adapter.aspx.

You can use it as it is or modify it to suit your needs. This component searches for an ADFS token in a

custom message header titled PassthroughBinarySecurityToken. If this token is found, the token is

validated by using the trusted issuer thumbprint of the ADFS STS and the claims that are extracted. A

Windows Account Name claim type identifies the user account. For more information, see

http://blogs.msdn.com/b/willpe/archive/2010/10/25/windows-authentication-adfs-and-the-access-

control-service.aspx.

Create custom authentication classes

A custom authentication component has two parts: An X++ class that implements the AifAuthenticationManager interface and provides

configuration information. A .NET class that implements the System.ServiceModel.ServiceAuthenticationManager

interface to provide runtime authentication.

32 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

AifAuthenticationManager interface

This X++ interface must be implemented by an X++ authentication manager class. This interface is used by the services framework to get information that is used to configure and deploy the

custom authentication runtime component.

X++

interface AifAuthenticationManager

{

AifAuthenticationManagerName getName();

str getAuthenticationManagerType();

str getAuthorizationPolicyType();

AifAssemblyName getAuthenticationManagerAssemblyName();

Map getAppSettings();

MenuItemNameDisplay getConfigurationDisplayMenuItem;

}

Interface methods:

AifAuthenticationManagerName getName() Returns the friendly name of the component. This is displayed for selection in the ServiceBus configuration form.

str getAuthenticationManagerType()

Returns the .NET type of the WCF custom authentication class in the runtime assembly.

str getAuthorizationPolicyType()

Returns the .NET type of the WCF authorization policy class in the runtime assembly.

AifAssemblyName getAuthenticationManagerAssemblyName()

Returns the name of the authentication assembly that contains the WCF custom authentication class.

Map getAppSettings()

Returns custom settings that are required by the .net authentication component at authentication time. These settings are available in the AppSettings section of the web.config

file, which is located in the IIS website directory. Returns null if app settings are not required.

MenuItemNameDisplay getConfigurationDisplayMenuItem

Returns the name of the display menu item for the configuration form of this component. Returns the empty string if no configuration form is available.

33

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Custom authentication component

A class that implements the following interfaces can perform custom authentication: System.ServiceModel.ServiceAuthenticationManager

System.IdentityModel.Policy.IAuthorizationPolicy

The System.ServiceModel.ServiceAuthenticationManager interface contains the ReadOnlyCollection

method.

C#

ReadOnlyCollection<IAuthorizationPolicy> Authenticate(

ReadOnlyCollection<IAuthorizationPolicy> authPolicy,

Uri listenUri,

ref Message message)

The implementation of this method can inspect the request message and headers, perform the custom

authentication, and set the authenticated principal on the message as a property.

The System.IdentityModel.Policy.IAuthorizationPolicy interface has a the properties and the Evaluate

method shown in the following example:

C#

bool Evaluate(

EvaluationContext evaluationContext,

ref Object state

)

The implementation of the Evaluate method sets the authenticated principal and identity on the

security context of the message.

Registering the authentication component

Before an authentication component can be used, it must be registered with the Services framework.

The registerAuthenticationManager and unregisterAuthenticationManager methods on the

AifAuthenticationHelper class must be used to register and unregister the authentication component.

Create an X++ job that calls these X++ methods to register/unregister the authentication

components. When a component is registered, the .NET assembly is uploaded to the database so that

it is accessible to all AOS instances. The file path that you use must grant read permissions to the AOS

service account. For more information about the AOS service account, see

http://technet.microsoft.com/en-us/library/ee355089.aspx and http://technet.microsoft.com/en-

us/library/ee355089.aspx and http://technet.microsoft.com/en-us/library/jj585430.aspx.

The following code shows the methods and describes the parameters:

X++

static public void registerAuthenticationManager(

AifAuthenticationManagerClass authenticationManagerClass,

FilePath assemblyFolder,

boolean updateExisting = false)

34 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

AuthenticationManagerClass is class ID of the X++ authentication manager class AssemblyFolder is the path of the folder that contains the .net authentication manager

assembly. UpdateExisting is the flag indicating that any existing assembly in the database should

updated with the assembly in the folder.

X++

static public void unregisterAuthenticationManager(

AifAuthenticationManagerClass authenticationManagerClass)

authenticationManagerClass is the class ID of the X++ authentication manager class

Encryption key containers

Encryption is used to protect confidential data in the web.config file. This requires a machine-level key container to be created and configured on all the involved machines. We have provided scripts

for this process. Download the scripts here: http://blogs.msdn.com/b/aif/archive/2013/04/29/aif-windows-azure-service-bus-adapter.aspx. These scripts use the IIS configuration utility aspnet_regiis.exe to manage the key containers.

1. Create an exportable machine-level key container on the IIS computer. Go to the directory where you want to export the container before running this script. In this example we use the root of the C drive.

Windows Command Prompt

C:\> CreateKeyContainer “MyKey”

2. Export the key container to an XML file. The following script will export the key container

to MyKey.xml.

Windows Command Prompt

C:\> ExportKeyContainer “MyKey”

3. Import the key container into each machine (machine running IIS and machine running the AOS).

Windows Command Prompt

C:\> ImportKeyContainer “MyKey” “MyKey.xml”

4. On each machine, grant the appropriate users access to the key containers.

For the IIS Machine, this user is the AppPool identity (which is the same as the BC proxy account). For the AOS machine, this is the AOS account (Network Service or domain account).

For a Domain account:

Windows Command Prompt

C:\> GrantAccessToKeyContainer “MyKey” “domain\user”

35

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

For a Network account:

Windows Command Prompt

C:\> GrantAccessToKeyContainer “MyKey”

5. Delete the exported MyKey.xml files. In this example, we exported the MyKey file to the

root of the C drive. This is important to prevent unauthorized access to the key container.

Publish AIF Service using the Service Bus Adapter

We are now going to publish the UnreconciledExpense service operation that we created in Create the service operation.

Register your Service Bus namespace

1. Open the Microsoft Dynamics AX Client.

Click System administration > Setup > Services and Application Integration

Framework > Azure Service Bus Configuration .

2. Provide Service Bus details in the Azure Service Bus Configuration form:

a. Supply your Azure Service Bus namespace, which was created when you registered

the namespace by following instructions in Microsoft Dynamics AX Connector for

Mobile Applications.

b. Supply your Azure Service Bus issuer name and issuer secret.

c. For Deployment website, select the IIS website to deploy the service on.

d. For Class name, specify the authentication class that you registered.

e. Click Configure. The Mobile Authentication Configuration form is shown.

i. Enter the certificate thumbprint (from your ADFS).

ii. Click Close.

f. For the RSA key container name, type the name of the key container that you created

previously in the Encryption key containers section.

g. For a description, provide a description for the Service Bus namespace, as shown in

the following illustration:

36 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

h. Click Close.

Deploy your AIF service to the Azure Service Bus

To create a new port to publish your service on:

1. Click System Administration > Services and Application Integration Framework >

Inbound Ports.

2. Click New to create a new port.

3. Type the name of the port. It is a best practice to incorporate the name that you used

for the Azure Service Bus namespace on the Azure Service Bus Configuration form (2-

a).

4. Type a description of the port to provide a description of the services that this port

hosts.

5. Select Azure Service Bus for Adapter.

6. Click the button beside the URI field to open the Select Azure Service Bus

Namespace form, and select the namespace that you created.

7. Click OK.

37

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

8. Click the Service Operations button, which is located below Service Contract

customizations.

9. Find the UnreconciledExpense service from Create the expense service operations in

the right-hand pane.

i. Select all of the operations on your service that you want to publish by

highlighting each one, and then clicking the < button.

ii. Click Close.

10. In the Inbound Ports form, highlight your port in the left-hand pane.

11. Click Activate.

12. The UnreconciledExpense Service is now published to IIS 7.5. The URL to access the

Microsoft Dynamics AX service through the Service Bus is displayed in the URI: field,

as shown in the previous illustration. For the example in this document, the URI field

should be:

https://ContosoMobile.servicebus.windows.net/UnreconciledExpense/xppservice.svc

You may now refer to the remainder of this document to develop the client that will

communicate with Microsoft Dynamics AX using the AX service that you have published to the

Windows Azure Service Bus.

38 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Develop the client to communicate data to the middle-tier WCF service

In this example and the sample code provided, we have made use of a Windows Phone application to represent a client for the backend service, but you are by no means limited to that. Clients could be anything ranging from Windows 8 apps in C# or JavaScript to .NET services to websites.

Development requirements

Visual Studio 2010 with Windows Phone SDK 7.1 with the 7.8 update installed, or Visual Studio 2012 with Windows Phone SDK 8.0 installed.

The Service Bus component (Microsoft.ServiceBus.dll), which is included with the Windows Azure

Libraries for .NET. To install it, visit the Windows Azure SDK download page.

Overview

This section will guide you through creating a Windows Phone client application that will consume the hosted Expense service on the Service Bus.

First, you will create a Windows Phone application project and generate a client proxy to consume the middle-tier service. Then you will lay out the controls on the UI for accepting the required input from

the user and handling all the control and page events.

Create a Windows Phone application

Open Visual Studio, and create a Windows Phone app project—for example, ContosoMobileApp.

For more information about Windows Phone development, see Getting started with developing for

Windows Phone. A recommended way for developing Windows Phone apps is to use the MVVM pattern

for Windows Phone apps. See Developing a Windows Phone Application using the MVVM Pattern.

Add the middle-tier WCF service reference

1. Right-click References, and add a service reference. You will need to enter the MEX URL that was specified in the Create the middle-tier WCF service section.

Note: The middle-tier service must be running at this point, and its metadata endpoint must be

enabled, so that the client can fetch the metadata of the service and generate the client proxy file (Reference.cs).

39

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

2. Notice that a ServiceReferences.Clientconfig file is created. Make sure that the following binding

information for the client exists.

APP.CONFIG

<configuration>

<system.serviceModel>

<bindings>

<basicHttpBinding>

<binding name="BasicHttpRelayBinding_ExpenseServiceContract"

maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">

<security mode="Transport" />

</binding>

</basicHttpBinding>

</bindings>

<client>

<endpoint address="https://contosomobile.servicebus.windows.net/https/ExpenseService/"

binding="basicHttpBinding"

bindingConfiguration="BasicHttpRelayBinding_ExpenseServiceContract"

contract="ExpenseServiceReference.ExpenseServiceContract"

name="BasicHttpRelayBinding_ExpenseServiceContract" />

</client>

</system.serviceModel>

</configuration>

40 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

If you want to access your MEX endpoint outside your domain during development, you could also consider hosting the WCF service’s MEX endpoint on the Service Bus itself.

Lay out and set up the UI controls for required user input

After adding the service reference, look at the Reference.cs client proxy file that is generated. You will see a method such as CreateExpenseAsync. This is the service operation that the app will call to send across expense data. As you can see in the generated proxy, the values that need to be passed in are the date, amount, currency string, and comments.

C#

public void CreateExpenseAsync(

System.DateTime dateTime, decimal amount, string currency, string comments)

{

this.CreateExpenseAsync(dateTime, amount, currency, comments, null);

}

Also remember that, in addition to sending the expense data, the app is required to do the following:

Authenticate to the Service Bus when making the service call.

Send the claims that identify the user sending the expense data, in the form of a SAML assertion token.

We will walk you through the authentication implementation in the Implement active federation and claims-based authorization for the mobile client section.

Based on these requirements, the app gathers the following data from the user:

Data for the service operation

Data for the authentication

41

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Data for the service operation

In the app project, create a new page, MainPage.xaml. We will design this page (together with its MainPage.xaml.cs file) to store the expense data.

The user enters the expense data and then clicks the Upload button. We will see later how the

data is sent across to the service in the UploadClick event handler.

42 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Data for the authentication

In the app project, create a new page, Settings.xaml. We will design and implement this page (together with its Settings.xaml.cs file) to store the data required for authentication. This data is

taken as input from the user.

The user name, password, service connection name (Windows Azure namespace), and authentication server URL (the AD FS endpoint) are then used to authenticate the user for the service operations.

The next step is to implement active federation for claims-based authentication to the Windows Azure Service Bus by using ACS and AD FS.

Implement active federation and claims-based authorization for the mobile client

Prerequisites (configuring the trusts)

1. Create the Windows Azure namespace and configure the Service Bus, as explained in Microsoft Dynamics AX Connector for Mobile Applications.

2. Add the Service Bus as the relying party in the ACS. In this way, the ACS is responsible for providing security to the Service Bus. For more information, see the “Configuring the Access Control Service; Configure the relying party applications” section in Microsoft Dynamics AX Connector for Mobile Applications.

43

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. Set up trust between AD FS 2.0 and the ACS.

The Active Directory server acts as the identity provider. It contains information about the corporate users and authenticates a user’s identity. Configure AD FS on the Active Directory server. The AD FS is also a security token service (STS) that provides security tokens to

requestors.

Configure AD FS to trust only requests coming from the ACS of the Service Bus for the namespace that you created. For example, add the endpoint https://contosomobile-sb.accesscontrol.windows.net as a relying party in the AD FS by providing the federation metadata URL exposed by the ACS. For more information, see the “Configuring an Active Directory Federation Service for authentication” section in Microsoft Dynamics AX Connector for Mobile Applications.

Configure the ACS to trust claims coming from the AD FS. To do this, go to your namespace’s Management Portal for the ACS, and add the AD FS as an identity provider in the Identity

Provider configuration section. You will need to add the federation metadata URL exposed by the AD FS server. For more information, see the “Configuring the Access Control Service; Add and configure the identity provider” section in Microsoft Dynamics AX Connector for Mobile Applications.

4. Map incoming claims to outgoing claims in the ACS. These claims will be inspected by Service Bus.

An incoming claim of the windowsaccountname type should be mapped to an outgoing claim of the net.windows.servicebus.action type with a value of Send. (For more information, see the “Configuring the Access Control Service; Configure rule groups” section in Microsoft Dynamics AX Connector for Mobile Applications.) This will ensure that any authenticated user having the windowsaccountname claim sent by the AD FS is authorized to send a message through the Service Bus.

5. Set up trust between the middle-tier WCF service and the corporate AD FS.

The AD FS uses an X.509 token signing certificate issued by a CA to digitally sign the SAML token

containing the claims about the user. For more information, see the “Configuring an Active Directory Federation Service for authentication; Add/Configure the token signing certificate” section in Microsoft Dynamics AX Connector for Mobile Applications.

When setting up the trust, observe the following guidelines:

The X.509 token signing certificate needs to be installed in the Trusted Root Certification store

on the machine that hosts the middle-tier WCF service.

The thumbprint of the certificate should be made available to this service. By using this thumbprint, the service can verify that the claims are from an authorized and trusted issuer.

Overview

After collecting the information from the user on the mobile device, we now need to submit the data to Microsoft Dynamics AX. Only those users who are authenticated are authorized to send this data through the Service Bus to Microsoft Dynamics AX. The ACS and AD FS (which acts as an identity

provider and a security token service) cooperate to authenticate and authorize Service Bus operations. The claims obtained from the identity provider are also used to extract information about the user in the middle-tier service. Authorization of Microsoft Dynamics AX users according to their Microsoft

Dynamics AX roles and privileges will be handled by the Microsoft Dynamics AX instance itself.

We use active federation and the WS-Trust security protocol to request a security token (containing the required claim) from the identity provider (corporate AD FS).

After the security token is presented to the ACS, it recognizes the identity of the user. As was mentioned in the prerequisites, the incoming claims are mapped to the Send outgoing claims that are recognized by the Service Bus for which the ACS is providing security. A claim is then issued to the client by the ACS in the form of a simple web token (SWT).

44 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

When the client is ready to send its message through the Service Bus endpoint, it presents the SWT, thus granting it permission to send the message. For our solution, the client is also required to send across to the middle-tier service, the SAML assertions token that it received from the AD FS. The service then extracts the assertion claims, as we saw in the walkthrough for the middle-tier WCF

service.

The following steps will show how we implement the required authentication described earlier.

Development requirements

You can implement the authentication described in the next section in the same Windows Phone app

project or in a compatible Windows Phone class library, which you can then reference in the app (if you plan to reuse the authentication code).

If you are implementing a client (Windows Phone 8 or Windows 8 Store app) in Visual Studio 2012,

consider creating a Portable Class Library for the authentication and including the library in your client application.

Implementation

We will walk you through implementing the authentication by using sample code to show you how the Expense Capture mobile application uses the SAML and SWT tokens to securely pass data through the Service Bus to Microsoft Dynamics AX.

Setup

1. In the phone app (ContosoMobileApp) that we created earlier, create a new class named AuthenticationProvider, and include the System.Net reference in it.

C#

using System.Net

2. Create an event for notification about completion of authentication. This event should provide notification about errors and also success in authentication.

C#

/// <summary>

/// Delegate type for handling authentication completed events

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

public delegate void AuthenticationCompletedEventHandler(object sender,

AuthenticationMessageArgs e);

45

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Here, AuthenticationMessageArgs is a class that defines custom EventArgs for storing custom exception messages and a Boolean value for success.

C#

public class AuthenticationMessageArgs: EventArgs

{

public AuthenticationMessageArgs(AuthenticationMessage authenticationMessage)

{

this.AuthenticationMessage = authenticationMessage;

}

public AuthenticationMessage AuthenticationMessage { get; private set; }

}

public class AuthenticationMessage

{

public AuthenticationMessage(string message, bool isSuccess)

{

this.Message = message;

this.IsSuccess = isSuccess;

}

public string Message { get; set; }

public bool IsSuccess { get; set; }

}

C#

/// <summary>

/// Subscribe to this event to be notified of authentication completion messages,

/// both succeeded & failed.

/// </summary>

public event AuthenticationCompletedEventHandler AuthenticationCompleted;

/// <summary>

/// The On Completed method to be called

/// </summary>

/// <param name="args"></param>

private void OnAuthenticationCompleted(AuthenticationMessageArgs args)

{

AuthenticationCompletedEventHandler handler = AuthenticationCompleted;

if (handler != null)

{

handler(this, args);

}

}

46 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. Define member variables, such as those for storing the user credentials, and response SAML and SWT tokens.

C#

UserCredentials credentials;

string azureNamespace = String.Empty;

string stsEndpoint = String.Empty;

string requestSecurityTokenPayload = String.Empty;

string requestSecurityTokenResponse = String.Empty;

DateTime stsAuthStartTime;

string acsPayload = String.Empty;

string samlAssertionToken = String.Empty;

string swtAcsToken = String.Empty;

Get user input

The next thing we need to do is accept the user input—that is, the user name (in the form domain\user alias), password, Federation Server (AD FS) endpoint URI, and Windows Azure namespace.

C#

public AuthenticationProvider(

string userName, string password, string windowsazureNamespace, string stsEndpointUrl)

{

credentials = new UserCredentials(userName, password);

azureNamespace = windowsazureNamespace;

stsEndpoint = stsEndpointUrl;

}

After the Windows Azure namespace is provided, we can define the following endpoints, which are required for the authentication process.

C#

/// <summary>

/// This read-only property is the relying party that is configured in ADFS. This value tells the

STS how

/// to respond (which token format, whether it's encrypted, which claims to include, token

lifetime, etc.)

/// </summary>

public string AppliesTo

{

get

{

return "https://" + azureNamespace + "-sb.accesscontrol.windows.net";

}

}

/// <summary>

/// This read-only property is the actual ACS endpoint we post the SAML token to, to acquire the

SWT

/// </summary>

public string AcsEndPoint

{

47

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

get

{

return "https://" + azureNamespace + "-sb.accesscontrol.windows.net/WRAPv0.9/";

}

}

/// <summary>

/// This read-only property is the relying party that's configured in SB's ACS.

/// The value is a hint to the STS as to which rules to perform. By default, it's

/// http://[namespace].servicebus.windows.net/, but more specific endpoint configurations are

/// possible if needed.

/// </summary>

public string RelyingParty

{

get

{

return "http://" + azureNamespace + ".servicebus.windows.net/";

}

}

/// <summary>

/// This read-only property is the actual endpoint exposed on ServiceBus that the final service

/// call & security tokens will be sent to.

/// </summary>

public string ServiceEndpoint

{

get

{

return "https://" + azureNamespace + ".servicebus.windows.net/Expense/";

}

}

48 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Create and send the request for security token

Now we can create the request for security token (RST) and actively send the request to the identity provider (AD FS).

1. Create the RST payload.

Create a string named StsUrlPayload with the following SOAP message format for the payload.

C#

/// <summary>

/// This is the actual payload of the SOAP message that will be sent to the STS

/// </summary>

private string StsUrlPayload = @"<s:Envelope xmlns:s=""http://www.w3.org/2003/05/soap-

envelope""

xmlns:a=""http://www.w3.org/2005/08/addressing""

xmlns:u=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-

1.0.xsd"">

<!--Header-->

<s:Header>

<a:Action s:mustUnderstand=""1"">http://docs.oasis-open.org/ws-sx/ws-

trust/200512/RST/Issue</a:Action>

<a:To s:mustUnderstand=""1"">{0}</a:To>

<o:Security s:mustUnderstand=""1"" xmlns:o=""http://docs.oasis-

open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"">

<u:Timestamp u:Id=""_0"">

<u:Created>{1}Z</u:Created>

<u:Expires>{2}Z</u:Expires>

</u:Timestamp>

<o:UsernameToken u:Id=""uuid-ea4cdc24-712d-4af7-9128-acb3db03b55f-1"">

<o:Username>{3}</o:Username>

<o:Password o:Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-

username-token-profile-1.0#PasswordText"">{4}</o:Password>

</o:UsernameToken>

</o:Security>

49

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

</s:Header>

<s:Body>

<trust:RequestSecurityToken xmlns:trust=""http://docs.oasis-open.org/ws-sx/ws-

trust/200512"">

<wsp:AppliesTo xmlns:wsp=""http://schemas.xmlsoap.org/ws/2004/09/policy"">

<a:EndpointReference>

<a:Address>{5}</a:Address>

</a:EndpointReference>

</wsp:AppliesTo>

<trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-

trust/200512/Bearer</trust:KeyType>

<trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-

trust/200512/Issue</trust:RequestType>

<trust:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</trust:TokenType>

</trust:RequestSecurityToken>

</s:Body>

</s:Envelope>";

2. Insert the values for the highlighted parts in the StsUrlPayload string, and assign it to requestSecurityTokenPayload.

C#

this.stsAuthStartTime = DateTime.UtcNow;

//Setting Expires time to request time + 5 minutes

requestSecurityTokenPayload =

String.Format(this.StsUrlPayload, this._stsEndpoint, this.stsAuthStartTime.ToString("s")

+ ".000",

this.stsAuthStartTime.AddMinutes(5).ToString("s") + ".000", credentials.Username,

credentials.Password, this.AppliesTo);

50 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. The SendRequestSecurityToken method is used to send the request across to the AD FS. These are asynchronous SOAP message requests, and callback methods are used to write to the request stream and receive the response.

C#

/// <summary>

/// Create the RST payload containing the user's credentials

/// Send the RST to the STS in a SOAP message using HttpWebRequest

/// </summary>

private void SendRequestSecurityToken()

{

this.stsAuthStartTime = DateTime.UtcNow;

requestSecurityTokenPayload = String.Format(this.StsUrlPayload, this._stsEndpoint,

this.stsAuthStartTime.ToString("s") + ".000",

this.stsAuthStartTime.AddMinutes(5).ToString("s") + ".000", credentials.Username,

credentials.Password, this.AppliesTo);

try

{

HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(stsEndpoint);

httpWebRequest.ContentType = "application/soap+xml; charset=utf-8";

httpWebRequest.Method = "POST";

httpWebRequest.BeginGetRequestStream(

new AsyncCallback(RequestSecurityTokenStreamCallback), httpWebRequest);

}

catch (Exception e)

{

//Fire the event to be handled by the App in case there was an error during

authentication

OnAuthenticationCompleted(new AuthenticationMessageArgs(

new AuthenticationMessage(e.Message,false)));

}

}

51

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

private void RequestSecurityTokenStreamCallback(IAsyncResult asynchronousResult)

{

HttpWebRequest httpWebRequest = (HttpWebRequest)asynchronousResult.AsyncState;

Stream requestStream = null;

try

{

using (requestStream = httpWebRequest.EndGetRequestStream(asynchronousResult))

{

if (requestStream != null)

{

byte[] bytes = Encoding.UTF8.GetBytes(requestSecurityTokenPayload);

requestStream.Write(bytes, 0, bytes.Length);

}

}

httpWebRequest.BeginGetResponse(

new AsyncCallback(RequestSecurityTokenResponseStreamCallback), httpWebRequest);

}

catch (Exception e)

{

OnAuthenticationCompleted(new AuthenticationMessageArgs(new

AuthenticationMessage(e.Message, false)));

}

}

4. The requestSecurityTokenResponse message contains the SAML token containing the windowsaccountname claim for the user. After extracting the request for security token

response (RSTR) (by using the GetResponseStringFromResponse method), we call the SendTokenToAcs method.

C#

/// <summary>

/// Helper method to extract the response string from an HttpWebResponse object.

/// </summary>

/// <param name="response">The HttpWebResponse object</param>

/// <returns>the response string contained in the http response.</returns>

public static string GetResponseStringFromResponse(HttpWebResponse response)

{

string responseString = string.Empty;

if (response != null)

{

Stream streamResponse = null;

try

{

streamResponse = response.GetResponseStream();

using (StreamReader streamRead = new StreamReader(streamResponse))

{

52 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

streamResponse = null;

responseString = streamRead.ReadToEnd();

}

}

finally

{

if (streamResponse != null)

{

streamResponse.Dispose();

}

}

}

return responseString;

}

Create the ACS payload

1. The next step is to extract the SAML claims from the RSTR and construct the ACS payload.

GetSamlTokenFromResponseString is a utility method that looks for the <saml:Assertion> element in the response string and returns the element’s contents as the SAML token.

C#

public static string GetSamlTokenFromResponseString(string responseString)

{

string samlToken = string.Empty;

53

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

// Parse the xml to find the <saml:Assertion> tag as per SAML11 standard.

// This is the ADFS token

StringReader reader = null;

try

{

reader = new StringReader(responseString);

using (XmlReader xmlparser = XmlReader.Create(reader))

{

reader = null;

while (xmlparser.Read())

{

switch (xmlparser.NodeType)

{

case XmlNodeType.Element:

string name = xmlparser.Name;

if (String.Equals(xmlparser.Name, "saml:Assertion"))

{

samlToken = xmlparser.ReadOuterXml();

}

break;

}

}

}

}

finally

{

if (reader != null)

{

reader.Dispose();

}

}

return samlToken;

}

C#

/// <summary>

/// Extracts the SAML assertions from the RSTR and sends a request to the ACS for a SWT token

/// </summary>

private void SendTokenToAcs()

{

const string acsPayloadFormat =

@"wrap_scope={0}&wrap_assertion={1}&wrap_assertion_format=SAML";

samlAssertionToken =

Utilities.GetSamlTokenFromResponseString(requestSecurityTokenResponse);

if (!String.IsNullOrEmpty(samlAssertionToken))

{

acsPayload = String.Format(acsPayloadFormat, Uri.EscapeDataString(RelyingParty),

Uri.EscapeDataString(samlAssertionToken));

54 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

try

{

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(AcsEndPoint);

request.ContentType = @"application/x-www-form-urlencoded";

request.Method = "POST";

request.BeginGetRequestStream(

new AsyncCallback(RequestAcsTokenStreamCallback), request);

}

catch (WebException e)

{

OnAuthenticationCompleted(new AuthenticationMessageArgs(

new AuthenticationMessage(e.Message, false)));

}

}

else

{

OnAuthenticationCompleted(new AuthenticationMessageArgs(

new AuthenticationMessage("SAML Token from STS is empty", false)));

}

}

2. The ACS payload containing the SAML token is written to the request stream and sent to the ACS endpoint.

C#

private void RequestAcsTokenStreamCallback(IAsyncResult asynchronousResult)

{

HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

Stream requestStream = null;

try

{

using (requestStream = request.EndGetRequestStream(asynchronousResult))

{

if (requestStream != null)

{

byte[] bytes = Encoding.UTF8.GetBytes(acsPayload);

requestStream.Write(bytes, 0, bytes.Length);

}

}

request.BeginGetResponse(new AsyncCallback(RequestAcsTokenResponseCallback),

request);

}

catch (WebException e)

{

OnAuthenticationCompleted(new AuthenticationMessageArgs(new

AuthenticationMessage(e.Message, false)));

}

}

55

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. The ACS sends back a response containing the SWT security token that is required to authenticate to the Service Bus.

C#

private void RequestAcsTokenResponseCallback(IAsyncResult asynchronousResult)

{

HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

try

{

HttpWebResponse response =

(HttpWebResponse)request.EndGetResponse(asynchronousResult);

string rawAcsResponse = Utilities.GetResponseStringFromResponse(response);

SwtAcsToken = Uri.UnescapeDataString(rawAcsResponse.Split('&').Single(value =>

value.StartsWith("wrap_access_token=",

StringComparison.OrdinalIgnoreCase)).Split('=')[1]);

if (!String.IsNullOrEmpty(this.SwtAcsToken))

{

OnAuthenticationCompleted(new AuthenticationMessageArgs(new

AuthenticationMessage("Security Token from ACS issued successfully", true)));

}

}

catch (WebException e)

{

// The ACS server has likely sent back an error response

string responseString =

Utilities.GetResponseStringFromResponse((HttpWebResponse)e.Response);

OnAuthenticationCompleted(new AuthenticationMessageArgs(

new AuthenticationMessage(responseString, false)));

}

catch (System.FormatException)

{

// Error parsing ACS token; it is in an invalid format

OnAuthenticationCompleted(new AuthenticationMessageArgs(

new AuthenticationMessage("Invalid ACS Token Format", false)));

}

catch (System.ArgumentOutOfRangeException)

{

// Error parsing ACS token; it is in an invalid format

OnAuthenticationCompleted(new AuthenticationMessageArgs(

new AuthenticationMessage("Invalid ACS Token Format", false)));

}

catch (Exception e)

{

OnAuthenticationCompleted(new AuthenticationMessageArgs(

new AuthenticationMessage(e.Message, false)));

}

}

The SwtAcsToken value is extracted from the raw response string sent by the ACS, as shown in the preceding code.

56 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

At this point a non-empty SWT with no other errors or exceptions implies that the authentication was successful.

Additional notes and guidelines

To keep this exercise as simple and focused as possible, this code has been boiled down to its essence and only contains the key principles required to understand the solution. In a production-level application, you would want to take into account additional considerations, including your platform and functional requirements. For example, your app does not have to request fresh tokens from both IdPs every time it needs to make a service call. Because of this, it would be useful to implement some local storage or caching of the security tokens until their expiration time. That expiration time is adjustable on both AD FS and the ACS. Choose a token lifetime that makes sense for your scenario and security

requirements; for example, more business-sensitive applications should have shorter token lifetimes, whereas low business-impact applications could have longer token lifetimes.

Regarding platform support, if you have access to the WIF libraries (for example, if you are writing a .NET client), feel free to use them, because they will offer you slightly more robust RST and RSTR processing. If you are working on any other platform, you may either search for library support on that platform or follow the same pattern that you have implemented earlier.

Finally, when storing data in durable storage, always be sure to encrypt secret information, such as the user’s credentials; this includes the security tokens and even the Service Bus secrets in the app.config file.

Authenticate the user and send the data to the service

After authenticating the user by using active federation as described in the Implement active federation and claims-based authorization for the mobile client section, the client can send its request to the service endpoint. We now need to use the AuthenticationProvider object within the Windows Phone app.

1. As is shown in the ContosoMobileApp application, when the user clicks the Submit/Save button,

we will handle the UploadClick event in the following way.

C#

private void UploadClick(object sender, EventArgs e)

{

Submit();

}

2. In the Submit method, we initialize the AuthenticationProvider object, subscribe to its AuthenticationCompleted event, and then call the IssueToken method.

We pass in the user data that we collect from the Settings.xaml page to initialize the AuthenticationProvider object; the following code shows an example of the user input that can

be passed in.

57

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

The IssueToken method is the starting point for the multiple asynchronous calls.

C#

public void Submit()

{

// parameters are domain\\userAlias, user's password, Azure Namespace & ADFS endpoint URL

authenticator = new AuthenticationProvider("contoso\\userAlias", "password",

"contosmobile",

"https://contosoadfs.com/adfs/services/trust/13/usernamemixed");

authenticator.AuthenticationCompleted += authenticator_AuthenticationCompleted;

authenticator.IssueToken();

}

C#

/// <summary>

/// Handle the Authentication completed event and then submit the expense using the tokens

/// if the authentication was successful

/// </summary>

private void authenticator_AuthenticationCompleted(object sender, AuthenticationMessageArgs

e)

{

if (e.AuthenticationMessage.IsSuccess)

{

// Authentication was successful. Now submit the expense through service bus,

// using the SWT and SAML token values exposed by the AuthenticationProvider

CreateExpense();

}

else

{

RaiseSubmitCompleted(new Exception(e.AuthenticationMessage.Message));

}

}

58 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. After the IssueToken asynchronous method is completed, the AuthenticationCompleted event is fired. We then check whether the authentication was successful.

If the authentication was successful, the app is now in possession of the SWT (the token to authenticate to the Service Bus) and the SAML token (the token containing the

windowsaccountname claim that is used to set the call context of the AIF service call). We then insert the two tokens into a custom SOAP header of the message. The body of the message will contain the expense data we want to send to the middle-tier WCF service.

4. Add a method named CreateExpense that creates the message as described in the previous step and sends it to the actual service endpoint on the Service Bus—that is, https://<AzureNamespace >servicebus.windows.net/Expense/.

A call is then made to the CreateExpenseAsync service operation by using the middle-tier service’s ExpenseServiceContractClient client proxy.

C#

private void CreateExpense()

{

ExpenseServiceReference.ExpenseServiceContractClient expenseService =

new ExpenseServiceReference.ExpenseServiceContractClient();

expenseService.Endpoint.Address = new System.ServiceModel.EndpointAddress(

new Uri(SettingsViewModel.ServiceEndpoint));

expenseService.CreateExpenseCompleted +=

new EventHandler<CreateExpenseCompletedEventArgs>(OnCreateExpenseCompleted);

// Get the channel context scope so we can add message headers to it

using (new OperationContextScope(expenseService.InnerChannel))

59

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

{

// Grab the raw SAML token and stuff it in a byte array

byte[] binToken = Encoding.UTF8.GetBytes(authenticator.SamlAssertionToken);

// Add the SAML token to a custom SOAP header

var customSecurityHeader =

MessageHeader.CreateHeader("PassthroughBinarySecurityToken", "",

Convert.ToBase64String(binToken));

OperationContext.Current.OutgoingMessageHeaders.Add(customSecurityHeader);

// Add the SWT token to a SOAP header as SB is expecting

OperationContext.Current.OutgoingMessageHeaders.Add(

new AcsHeader(authenticator.SwtAcsToken));

// Finally, call the actual service to create our expense.

expenseService.CreateExpenseAsync(

ExpenseDate, Amount, Amount == 0? null : Currency, Comment);

}

}

C#

/// <summary>

/// This is the Custom (SOAP header) format that Service Bus requires a token

/// from ACS to exist in the message. This header will be stripped out by SB

/// and thus will not exist when the message gets to the service.

/// </summary>

/// <remarks>

/// Leave all these hard-coded values alone, SB is expecting

/// a very particular format for this header.

/// </remarks>

private class AcsHeader : MessageHeader

{

private string token;

public AcsHeader(string token)

{

this.token = token;

}

public override string Name

{

get { return "RelayAccessToken"; }

}

public override string Namespace

{

get { return "http://schemas.microsoft.com/netservices/2009/05/servicebus/connect"; }

}

60 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

protected override void OnWriteHeaderContents(

XmlDictionaryWriter writer, MessageVersion messageVersion)

{

writer.WriteStartElement("BinarySecurityToken", "http://docs.oasis-

open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

writer.WriteAttributeString("Id", "http://docs.oasis-open.org/wss/2004/01/oasis-

200401-wss-wssecurity-utility-1.0.xsd",

string.Format("uuid:{0}", Guid.NewGuid().ToString("D")));

writer.WriteAttributeString("ValueType", "http://schemas.xmlsoap.org/ws/2009/11/swt-

token-profile-1.0");

writer.WriteAttributeString("EncodingType", "http://docs.oasis-

open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");

byte[] binToken = Encoding.UTF8.GetBytes(token);

writer.WriteBase64(binToken, 0, binToken.Length);

writer.WriteEndElement();

}

}

The request is then sent to the endpoint on the Service Bus. The Service Bus authorizes the incoming message to be relayed through it to the middle-tier WCF service, by examining the SWT. The expense data and the SAML token are then passed to the middle-tier service.

The Service Bus also relays back the response from the WCF service after the operation is completed. An event is raised to notify about completion.

In this example, you can also create a custom completed notification event to handle the response (success or error messages) within the application and send a message that can be viewed by the

user. In the preceding code sample, we subscribe to a custom event, CreateExpenseCompleted, to accomplish this.

Developing RESTful JavaScript mobile apps for Microsoft Dynamics AX 2012

Creating secure mobile apps for Microsoft Dynamics AX 2012 is not restricted to clients that are built on the .NET runtime, such as Windows Phone and Windows Store apps. As we indicated earlier, you can also create mobile apps by using cross-platform technologies such as HTML5 and JavaScript.

The solution architecture for creating such apps remains the same, as described in the Technical overview section. This means that you can still create secure apps for mobile clients by using active federation and claims-based identity for authentication, given the user’s corporate credentials and using the Windows Azure Service Bus relay to transport the messages from the client to the middle-

tier WCF service, which in turn would send the data across to Microsoft Dynamics AX by using AIF services.

61

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

The following table demonstrates a mapping between apps that use the .NET Framework and apps that use HTML5 and JavaScript with respect to the various components in the architecture.

.NET Framework HTML5/JavaScript

Microsoft Dynamics AX AIF service

Creating AIF services is described in the Design and create the AIF service in Microsoft Dynamics AX 2012 section.

No change

Middle-tier WCF service A SOAP-based service with a BasicHttpRelayBinding binding. The SAML token is in the SOAP header.

A RESTful service with a WebHttpRelayBinding binding. The SAML token is in the request body.

Configuration (AD FS, Windows Azure Service Bus, ACS)

The configuration required for setting up AD FS, token signing certificates, and the Windows Azure Service Bus and ACS is described in Microsoft Dynamics AX Connector for Mobile Applications.

No change

Active federation for authentication

Implemented by using .NET technologies (WCF and System.NET APIs). For more information, see the Implement active federation and claims-based authorization for

the mobile client section.

No change in request payloads to AD FS.

Implemented by using JavaScript and JQuery for asynchronous communication.

Fetching tokens, claims, and communication to the WCF service

Implemented by using .NET technologies (WCF and System.NET APIs).

The SAML token with claims is sent in a custom SOAP header, together with the SWT for the Service Bus.

For more information, see the Authenticate the user and send the data to the service section.

No change in the request for a SWT sent to the ACS.

However, the SAML token is sent in the request body of the JSON payload. The SWT is sent in the HTTP Authorization header.

Mobile client UI Accepts user input.

Implemented by using .NET technologies (for example, for Windows Phone and Windows Store apps).

Accepts user input.

Can be implemented by using HTML5, for example.

The following walkthrough provides guidance in creating RESTful JavaScript mobile apps and uses the same expense capture example that was used in earlier sections.

Design and create the AIF service in Microsoft Dynamics AX 2012

The steps to create the AIF service for our expense example remain the same as described in the Design and create the AIF service in Microsoft Dynamics AX 2012 section.

Create the middle-tier RESTful service

This section will now walk you through creating a RESTful service by using WCF. You can create this service in a way that is very similar to the WCF SOAP service that we created in the Create the middle-tier WCF service section, except that we now create and configure the service to deploy RESTful service endpoints on the Service Bus.

Before you complete this walkthrough, you could also see the Create the middle-tier WCF service

section to help you understand the following:

Setting up the Service Bus relay and deploying the listening endpoint

62 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Using Windows Identity Foundation to validate incoming messages and extract the user’s claims

Adding the AIF service reference

Building and creating an installer, and deploying the Windows service

Prerequisites

An X.509 token signing certificate is installed on the AD FS server and on the machine running the WCF service, in the Trusted Root Certification Authorities store. For guidance, see Microsoft Dynamics AX Connector for Mobile Applications.

You have the thumbprint from that certificate.

A Windows Azure Service Bus namespace has been created, and the shared secret and issuer name for the namespace are available. For guidance, see Microsoft Dynamics AX Connector for

Mobile Applications.

The machine that the middle-tier WCF service runs on should be in the same domain or on the same network as the Microsoft Dynamics AX 2012 AOS machine (which can be the same machine or a different one).

Development requirements

Visual Studio 2010 and the .NET Framework version 4

The Service Bus component (Microsoft.ServiceBus.dll), which is included with the Windows Azure Libraries for .NET. To install it, visit the Windows Azure SDK download page.

The Windows Identity foundation runtime, which can be downloaded from Windows Identity Foundation SDK. Download the 4.0 version for Visual Studio 2010 and the .NET Framework version 4.0.

For more information about the WIF SDK, see Windows Identity Foundation SDK.

Create the data contract, service contract, and operation contract

1. Open Visual Studio, and create a new Windows Service .NET Framework version 4 project named ExpenseConnectorService.

2. Add the System.ServiceModel.Web reference to the project.

3. Rename the Service1.cs class ConnectorService.cs. This class contains the OnStart and OnStop methods for the Windows service, which we will use to open a listening endpoint.

63

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

4. Include the System.ServiceModel.Web namespace in this class.

C#

using System;

using System.ServiceModel.Web;

using System.ServiceProcess;

namespace ExpenseConnectorService

{

public partial class ConnectorService : ServiceBase

{

private WebServiceHost host;

public ConnectorService()

{

InitializeComponent();

}

protected override void OnStart(string[] args)

{

// Deploy the endpoint

}

protected override void OnStop()

{

// Close the endpoint connection

}

}

}

5. Add the System.Runtime.Serialization reference to the project.

6. Add a new C# class for the data contract, named ExpenseData, to the project, and include the System.Runtime.Serialization namespace. Add the data members to this serializable object, as shown here.

C#

[DataContract]

public class ExpenseData

{

[DataMember]

public decimal Amount { get; set; }

[DataMember]

public string Comments { get; set; }

[DataMember]

public string CurrencyCode { get; set; }

[DataMember]

public string Date { get; set; }

}

64 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

7. Add the System.ServiceModel reference to the project.

8. Add a new C# interface for the service contract, named IExpenseRestService, to the project, and create the service contract and operation contract as shown here. Include the System.ServiceModel namespace.

C#

[ServiceContract(Name="ExpenseRestServiceContract", Namespace =

"http://samples.microsoft.com/DynamicsAx/")]

public interface IExpenseRestServiceContract

{

[OperationContract]

long CreateExpense(string adfsToken, ExpenseData expenseData);

}

9. Create another C# class for the service operation implementation, which implements

IExpenseRestServiceContract. Include the System.ServiceModel.Web namespace in this class.

C#

using System;

using System.IO;

using System.Linq;

using System.ServiceModel.Web;

using System.Xml;

namespace ExpenseConnectorService

{

public class ExpenseRestService: IExpenseRestServiceContract

{

[WebInvoke(

UriTemplate = "Expense?Action=Create", //

URI:"https://<azurenamespace>.servicebus.windows.net/ExpenseRestService/Expense?Ac

tion=Create"

RequestFormat = WebMessageFormat.Json,

ResponseFormat = WebMessageFormat.Json,

BodyStyle = WebMessageBodyStyle.WrappedRequest)]

public long CreateExpense(string adfsToken, ExpenseData expenseData)

{

// Implementation

}

}

10. The CreateExpense service operation needs to be handled by the WCF REST programming

model. To do this, we need to specify the following:

WebInvoke attribute for the service operation: This lets us map the service operation to the HTTP verb POST and place the SAML token in the body of the HTTP request.

UriTemplate: This is the URI that is mapped to the operation that the client will send its request to.

The endpoint that we deploy on the Service Bus will be in the form

https://<azurenamespace>.servicebus.windows.net/ExpenseRestService, and therefore the CreateExpense service operation will be mapped to https://<azurenamespace>.servicebus.windows.net/ExpenseRestService/Expense?Action=Create, as shown in the preceding code.

65

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

RequestFormat and ResponseFormat: These indicate that we will be sending messages to and from the client in the form of JSON payloads.

Observe the two parameters in the service operation. The first is adfsToken, which is the SAML token that is acquired from the corporate AD FS by the client. This token contains the

windowsaccountname claim that identifies the user making the request and will be used to set the CallContext property when the AIF service call is made. For more information about the CallContext property, see the Call the AIF service operations section.

The second parameter is data that comes from the client. This contains the expense data we defined in the serializable data contract.

Both these parameters exist in the incoming JSON body of the payload.

Add a service reference of the AIF service

See the Add a service reference of the AIF service section.

Call the AIF service operations

Create a new private method named SubmitExpenseToAX. For this example, pass in the windowsAccountName string and the ExpenseData object. For more information, see the Call the

AIF service operations section.

C#

private long SubmitExpenseToAX(ExpenseData expenseData, string windowsAccountName)

{

UnreconciledExpenseRecord record = new UnreconciledExpenseRecord()

{

parmNotes = expenseData.Comments,

parmTransactionCurrencyAmount = expenseData.Amount,

parmTransactionDate = DateTime.Parse(expenseData.Date),

parmTransactionCurrencyCode = expenseData.CurrencyCode

};

using (UnreconciledExpenseServiceClient client = new

AXExpenseServiceReference.UnreconciledExpenseServiceClient())

{

UnreconciledExpenseRecord expenseRecord = record;

CallContext callContext = new CallContext() { LogonAsUser = windowsAccountName };

return client.createRecord(callContext, expenseRecord);

}

}

Configure the RESTful service bindings and deploy the listening endpoint on

Service Bus

The Set up the Service Bus relay and deploying the listening endpoint for the middle-tier WCF service section describes in detail the bindings required for a SOAP service to communicate with the Service Bus. In a very similar way, we need to set up a WebHttpRelayBinding binding to deploy the RESTful service’s listening endpoint on the Service Bus. You will need to update the app.config file to add the binding and specify the Service Bus credentials.

66 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

1. Define the WebHttpRelayBinding configuration by adding the following under the <bindings> element in the <system.serviceModel> section. Set the relayClientAuthenticationType parameter to RelayAccessToken, which forces clients of the service to authenticate to the Service Bus before sending across any messages.

APP.CONFIG

<bindings>

<webHttpRelayBinding>

<binding name="WebHttpRelayBinding_ServiceBus">

<security mode="Transport" relayClientAuthenticationType="RelayAccessToken"/>

</binding>

</webHttpRelayBinding>

</bindings>

2. Define configuration values for the endpoint behavior.

APP.CONFIG

<behaviors>

<endpointBehaviors>

<behavior name="sharedSecretClientCredentials">

<transportClientEndpointBehavior credentialType="SharedSecret">

<clientCredentials>

<!-- The issuerName & issuerSecret here should be set to the values

for the service account on Service Bus you wish to use to listen.

By default, the namespace will come with an admin user (issuerName) of

"owner" with a 256-bit secret key (issuerSecret) available in the

Windows Azure management portal. -->

<sharedSecret issuerName="owner"

issuerSecret="xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxx="/>

</clientCredentials>

</transportClientEndpointBehavior>

</behavior>

</endpointBehaviors>

</behaviors>

67

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. Deploy the listening endpoint. Add the following code snippet in the app.config file, under the <services> element.

APP.CONFIG

<services>

<service name="ExpenseConnectorService.ExpenseRestService">

<endpoint address="" behaviorConfiguration="sharedSecretClientCredentials"

binding="webHttpRelayBinding"

contract="ExpenseConnectorService.IExpenseRestServiceContract"/>

<host>

<baseAddresses>

<!-- This baseAddress should be set to the URI you intend to

listen to on the Service Bus. It should be of the form:

"https://<APPFABRIC_NAMESPACE>.servicebus.windows.net/Expense/" -->

<add baseAddress="https://contosomobile.servicebus.windows.net/ExpenseRest/"/>

</baseAddresses>

</host>

</service>

</services>

4. We also need to update the app.config file to register the preceding Service Bus behavior and binding extensions.

APP.CONFIG

<extensions>

<behaviorExtensions>

<add name="transportClientEndpointBehavior"

type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement,

Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35"/>

</behaviorExtensions>

<bindingExtensions>

<add name="webHttpRelayBinding"

type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement,

Microsoft.ServiceBus, Version=1.7.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35"/>

</bindingExtensions>

</extensions>

68 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

5. Finally, open the Service Bus connection, and start listening on the endpoint.

Add the following code snippets to the OnStart method in the ConnectorService class.

C#

protected override void OnStart(string[] args)

{

// Note that all binding, endpoint, service, behavior configuration

// for this WebServiceHost is located in the app.config

host = new WebServiceHost(typeof(ExpenseConnectorService.ExpenseRestService));

WriteToEventViewer("Opening the Service endpoint connection " +

host.BaseAddresses[0].ToString());

try

{

host.Open();

WriteToEventViewer(string.Format("Listening on: {0}",

host.Description.Endpoints.Find(

typeof(ExpenseConnectorService.IExpenseRestServiceContract)).Address));

}

catch (Exception e)

{

WriteToEventViewer(e.Message);

}

}

C#

private void WriteToEventViewer(string eventMessage)

{

string source = "Expense WCF Service";

if (!EventLog.SourceExists(source))

{ EventLog.CreateEventSource(source, "Application"); }

EventLog.WriteEntry(source, eventMessage, EventLogEntryType.Information);

}

C#

protected override void OnStop()

{

host.Close();

}

Validate and extract contents from incoming JSON messages

The Validate and extract contents from incoming messages section explains, in detail, more about the SAML token and the claims extracted, and also the use of WIF to validate the token from the trusted issuer.

You will need to process the incoming JSON message to extract the claims and the expense data. The

client sends a POST request containing the parameter values for adfsToken and expenseData in the request body itself;, therefore, you can easily extract the claims from the adfsToken parameter and the ExpenseData object from the expenseData parameter.

69

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

You will also need to add the configuration required by Windows Identity Foundation to handle the incoming SAML tokens (that is, the thumbprint for the X.509 token signing certificate, as described in the Validate and extract contents from incoming messages section).

1. Update the app.config file under the <configuration> node, adding configuration values for

handling the SAML security token issued by the AD FS.

The issuer (also known as the identity provider—in our case, the corporate AD FS) uses a token signing certificate to digitally sign the SAML token.

APP.CONFIG

<microsoft.identityModel>

<service>

<securityTokenHandlers>

<securityTokenHandlerConfiguration>

<audienceUris mode="Never"/>

<issuerNameRegistry

type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry,

Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35">

<trustedIssuers>

<!-- The STS that issues the SAML token exchanged

at ACS must be added as a trusted issuer here.

The thumbprint & name values should be obtainable from the

public signing certificate exposed on the STS' federation metadata -->

<add

thumbprint="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

name=""/>

</trustedIssuers>

</issuerNameRegistry>

</securityTokenHandlerConfiguration>

</securityTokenHandlers>

</service>

</microsoft.identityModel>

APP.CONFIG

<configSections>

<section name="microsoft.identityModel"

type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection,

Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35"/>

</configSections>

2. Add Microsoft.IdentityModel and System.IdentityModel references to the project, and add the following namespaces to the ExpenseRestService.cs file.

C#

using System.IdentityModel.Tokens;

using System.Security.Principal;

using Microsoft.IdentityModel.Claims;

using Microsoft.IdentityModel.Configuration;

70 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

3. Add an implementation to the CreateExpense service operation to do the following:

1. Extract the security token containing the SAML assertions from the adfsToken parameter value. This information is passed by the mobile client calling the service.

2. Use WIF to validate the token by using the thumbprint and other configuration values from the

service configuration.

3. Extract the required claim (windowsaccountname) from the token.

4. Make the call to the SubmitExpenseToAX method, which will make the AIF service call. Pass the expenseData value in the call that will be sent to the AIF service.

C#

[WebInvoke(

UriTemplate = "Expense?Action=Create", //

URI:"https://<azurenamespace>.servicebus.windows.net/ExpenseRestService/Expense?Action

=Create"

RequestFormat = WebMessageFormat.Json,

ResponseFormat = WebMessageFormat.Json,

BodyStyle = WebMessageBodyStyle.WrappedRequest)]

public long CreateExpense(string adfsToken, ExpenseData expenseData)

{

string windowsAccountName = string.Empty;

// Extract the 'adfsToken' from the message body

string samlTokenString = Uri.UnescapeDataString(adfsToken);

// Load the app.config settings where we specify the audience & issuer that we'll

// accept in a token

var config = new ServiceConfiguration();

var handler =

config.SecurityTokenHandlers[

Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml11TokenProfile11];

ClaimsIdentityCollection claimsIdentity = null;

// Convert the raw token into something that can be inspected

using (XmlReader reader = XmlReader.Create(new StringReader(samlTokenString)))

{

SecurityToken token = handler.ReadToken(reader);

// This is the primary WIF call that

// 1) Performs all the token validation

// a. Format, token type, key type, version, etc.

// b. Expiration

// c. Audience/AppliesTo/Relying party

// d. Issuer

// e. Signature

// 2) generates a ClaimsIdentityCollection that contains what the app actually //

cares about

claimsIdentity = handler.ValidateToken(token);

}

71

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

C#

IPrincipal principal = new ClaimsPrincipal(claimsIdentity);

IClaimsIdentity identity = (IClaimsIdentity)principal.Identity;

windowsAccountName = identity.Claims.Single(claim => claim.ClaimType ==

"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname").Value;

return SubmitExpenseToAX(expenseData, windowsAccountName);

}

Create an HTML5/JavaScript app to communicate data to the WCF

middle-tier RESTful service

Mobile apps can be created by using commonly known web technologies, such as HTML5, CSS3, and

JavaScript. HTML5 and style sheets can be combined to produce impressive user interfaces, which you can use to obtain user input. In our expense capture example, the client could be designed to capture the following user input:

Expense data, such as the amount, currency, date, and comments

Authentication data, such as the following:

The user’s alias and password

The Windows Azure Service Bus namespace hosting the back-end service’s endpoint

The endpoint URL of the AD FS server that is required for active federation

This document will not cover the creation of the user interface itself, but will instead focus on the client-side authentication and service calls.

Implement active federation and claims-based authorization for the

mobile client by using JavaScript

We now move on to implementing the authentication required for communicating to the back-end middle-tier RESTful service through the Service Bus. To help understand more about the authentication process, the prerequisites, and the configuration of trusts between AD FS and the ACS,

the ACS and the Service Bus, and AD FS and the middle-tier WCF service, see the Implement active federation and claims-based authorization for the mobile client section.

The code samples below will demonstrate how you can achieve the following in JavaScript (using AJAX for asynchronous communication):

Send AD FS a request for security token (RST) containing the user’s credentials

Extract the claim (SAML token) from the request for security token response (RSTR) returned from

the AD FS

Send a request containing the claim token in exchange for a simple web token (SWT) from the Service Bus’s ACS.

Extract the SWT from the response received from the ACS.

72 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

In the following sample, we define a JavaScript AuthenticationProvider object that contains methods for fetching the SAML token from AD FS and the SWT from the ACS.

JAVASCRIPT

function AuthenticationProvider() {

// ADFS token variables

var _ADFSEndpoint = 'https://contosoadfs.com/adfs/services/trust/13/usernamemixed';

var _ADFSEncodedToken = '';

var _ACSEncodedToken = '';

// user credentials (to be obtained from the user interface)

var _userName = 'contoso\\userAlias';

var _password = 'password';

// Azure namespace

var _serviceNamespace = 'contosomobile';

// Gets encoded SAML Token from ADFS in response to the Request for Security Token (RST)

this.getADFSToken = function getADFSToken(success, error) {

// prepare parameters for the web-service call

var ADFSUrlPayload = ["<s:Envelope xmlns:a='http://www.w3.org/2005/08/addressing\'

xmlns:s='http://www.w3.org/2003/05/soap-envelope'>",

"<s:Header>",

"<a:Action s:mustUnderstand='1'>http://docs.oasis-

open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>",

"<Security s:mustUnderstand='1'

xmlns:u='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'",

" xmlns='http://docs.oasis-open.org/wss/2004/01/oasis-

200401-wss-wssecurity-secext-1.0.xsd'>",

"<UsernameToken u:Id='45dcb005-1a5b-4c9d-b26e-

cb9ab35f7b26'>",

"<Username>", _userName, "</Username>",

"<Password Type='http://docs.oasis-

open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>", _password,

"</Password>",

"</UsernameToken>",

"</Security>",

"<a:To s:mustUnderstand='1'>", _ADFSEndpoint, "</a:To>",

"</s:Header>",

"<s:Body>",

"<trust:RequestSecurityToken

xmlns:trust='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>",

"<wsp:AppliesTo

xmlns:wsp='http://schemas.xmlsoap.org/ws/2004/09/policy'>",

"<a:EndpointReference>",

"<a:Address>https://", _serviceNamespace, "-

sb.accesscontrol.windows.net/</a:Address>",

"</a:EndpointReference>",

"</wsp:AppliesTo>",

"<trust:RequestType>http://docs.oasis-open.org/ws-

sx/ws-trust/200512/Issue</trust:RequestType>",

"<trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-

trust/200512/Bearer</trust:KeyType>",

"</trust:RequestSecurityToken>",

73

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

JAVASCRIPT

"</s:Body>",

"</s:Envelope>"].join("");

// Ajax call to send the request to AD FS

$.ajax({

url: _ADFSEndpoint + "/",

type: "POST",

contentType: "application/soap+xml",

dataType: "xml",

data: ADFSUrlPayload,

success: function (data, textStatus, jqXHR) {

var response = jqXHR.responseText;

// Get the SAML assertion token from the response

var startIndex = response.indexOf("<saml:Assertion");

if (startIndex != -1) {

var endIndex = response.indexOf("/saml:Assertion");

var _ADFSRawToken = response.substring(parseInt(startIndex),

(parseInt(endIndex) + parseInt(16)));

_ADFSEncodedToken = encodeURIComponent(_ADFSRawToken);

// Fire the successful event

if (success && $.isFunction(success)) {

success(_ADFSEncodedToken);

}

}

},

error: function (jqXHR, textStatus, errorThrown) {

// Fire the failure event

if (error && $.isFunction(error)) {

error(textStatus, errorThrown);

}

}

});

}

// Get the ACS SWT token by sending the ACS the ADFSEncodedToken containing the identity

// claims about the user (windowsaccountname) in a specific format

this.getACSToken = function getACSToken(success, error) {

$.ajax({

type: "POST",

url: "https://" + _serviceNamespace + "-sb.accesscontrol.windows.net/WRAPv0.9/",

contentType: "application/x-www-form-urlencoded",

data: 'wrap_scope=http%3a%2f%2f' + _serviceNamespace +

'.servicebus.windows.net%2f&wrap_assertion=' + _ADFSEncodedToken + '&wrap_assertion_format=SAML',

dataType: "text",

success: function (data, textStatus, jqXHR) {

var response = decodeURIComponent(jqXHR.responseText);

74 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

JAVASCRIPT

// Get the SWT token from the response

var endIndexToken = response.indexOf('&wrap_access_token_expires_in');

_ACSEncodedToken = response.substring(18, endIndexToken);

// Fire the successful event

if (success && $.isFunction(success)) {

success(_ACSEncodedToken);

}

},

error: function (jqXHR, textStatus, errorThrown) {

// Fire the failure event

if (error && $.isFunction(error)) {

error(textStatus, errorThrown);

}

}

});

}

}

Send the request payload to the REST service

After the expense data is captured from the user, the data, together with the authentication tokens, needs to be sent in the request to the back-end service operation CreateExpense.

In the following code sample, we create a ServiceRequest object whose send method does the

following:

Create a request message containing the SWT in the header, and the SAML token together with the user data (expense data in our example), in the request body

Send the message to the endpoint URI of the RESTful service operation through the Service Bus relay.

JAVASCRIPT

function ServiceRequest() {

this.send = function send(adfsEncodedToken, acsEncodedToken, success, error) {

// Create the payload for the RESTful service at the backend containing the expenseData

// and the adfstoken

var expenseObj = {

"Amount": "100",

"Comments": "Expense of 100 EUR",

"CurrencyCode": "EUR",

"Date": "02/02/2013"

};

var payload = {

"adfsToken": adfsEncodedToken,

"expenseData": expenseObj

};

// The token sent to Service Bus relay needs to be in a particular format

75

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

JAVASCRIPT

var relayToken = 'WRAP access_token="' + acsEncodedToken + '"';

var payloadJSON = JSON.stringify(payload);

// Make the AJAX call to invoke the service operation mapped to a specific URL

// The relay token goes into the header of the request going through Service Bus

$.ajax({

type: "POST",

url:

'https://contosomobile.servicebus.windows.net/ExpenseRestService/Expense?Action=Create',

beforeSend: function (jqXHR) {

jqXHR.setRequestHeader('Authorization', relayToken);

},

contentType: 'application/json; charset=utf-8',

data: payloadJSON,

processData: false,

datatype: "json",

success: function (data, textStatus, jqXHR) {

// Fire the success event

if (success && $.isFunction(success)) {

success(data);

}

},

error: function (jqXHR, textStatus, errorThrown) {

// Fire the failure event

if (error && $.isFunction(error)) {

error(textStatus, errorThrown);

}

}

});

}

}

Finally, use the AuthenticationProvider object implemented earlier to begin the series of

asynchronous calls to the getADFSToken and getACSToken methods, and then send across the request to invoke the service operation in the middle-tier service.

JAVASCRIPT

<script type="text/javascript">

var adfsToken = '';

var acsToken = '';

var authProvider = new AuthenticationProvider();

//Fire off the asynchronous calls on clicking a submit button for example

$('#submit').click(function (evt) {

//Support cross domain requests

$.support.cors = true;

authProvider.getADFSToken(adfsSuccess, adfsError);

});

var adfsError = function (textStatus, errorThrown) {

console.log(textStatus + ": " + errorThrown);

76 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

JAVASCRIPT

}

var adfsSuccess = function (_ADFSEncodedToken) {

adfsToken = _ADFSEncodedToken;

authProvider.getACSToken(acsSuccess, acsError);

}

var serviceRequest = new ServiceRequest();

var acsError = function (textStatus, errorThrown) {

console.log(textStatus + ": " + errorThrown);

}

var acsSuccess = function (_ACSEncodedToken) {

acsToken = _ACSEncodedToken;

serviceRequest.send(adfsToken, acsToken, submitSuccess, submitError);

}

var submitSuccess = function (result) {

console.log("Success!");

}

var submitError = function (textStatus, errorThrown) {

console.log(textStatus + ": " + errorThrown);

}

</script>

77

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Additional resources

Microsoft Dynamics AX Connector for Mobile Applications

Walkthrough: Exposing an X++ Class as a Data Contract [AX 2012]

Walkthrough: Creating a Windows Service Application in the Component Designer

Specify the .NET Business Connector proxy account [AX 2012]

Getting started with developing for Windows Phone

Developing a Windows Phone Application using the MVVM Pattern

Download Windows Azure

Download Windows Identity Foundation SDK

Windows Identity Foundation SDK

78 DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

The computer code, including developer tools and sample code (“software”) included with this document is made available to you

under the software license agreement that appear below.

Microsoft Dynamics AX Sample License

This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the

license, do not use the software.

1. Definitions

The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the same meaning here as under U.S. copyright

law.

A “contribution” is the original software or any additions or changes to the software.

A “contributor” is any person that distributes its contribution under this license.

“Licensed patents” are a contributor’s patent claims that read directly on its contribution.

2. Grant of Rights

(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each

contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative

works of its contribution, and distribute its contribution or any derivative works that you create.

(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor

grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale,

import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.

3. Conditions and Limitations

(A) No Trademark License - This license does not grant you rights to use any contributors’ name, logo, or trademarks.

(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent

license from such contributor to the software ends automatically.

(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are

present in the software.

(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may

only do so under a license that complies with this license.

(E) The software is licensed “as-is.” You bear the risk of using it. The contributors give no express warranties, guarantees or

conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose

and non-infringement.

(F) Platform Limitation- The licenses granted in sections 2(A) & 2(B) extend only to the software or derivative works that operates

with Microsoft Dynamics AX.

79

DEVELOPING SECURE MOBILE APPS FOR MICROSOFT DYNAMICS AX 2012

Microsoft Dynamics is a line of integrated, adaptable business management solutions that enables you and your people to make business decisions with greater confidence. Microsoft Dynamics works like and with familiar Microsoft software, automating and streamlining financial, customer relationship, and supply chain processes in a way that helps you drive business success.

U.S. and Canada Toll-Free 1-888-477-7989

Worldwide +1-701-281-6500

www.microsoft.com/dynamics

This document supports a demonstration of how to create a mobile app for use with Microsoft Dynamics 2012. This document is

provided for informational purposes only and Microsoft makes no warranties, either express or implied, in this document.

Information in this document, including URL and other Internet Web site references, is subject to change without notice. The entire

risk of the use or the results from the use of this document remains with the user. Unless otherwise noted, the companies,

organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted in examples herein are

fictitious. No association with any real company, organization, product, domain name, e-mail address, logo, person, place, or event

is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the

rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted

in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the

express written permission of Microsoft Corporation.

This is a preliminary document and may be changed substantially prior to final commercial release of the software described herein.

The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the

date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a

commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of

publication.

This white paper is for informational purposes only. Microsoft makes no warranties, express or implied, in this document.

Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of

this document may be reproduced, stored in, or introduced into a retrieval system, or transmitted in any form or by any means

(electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of

Microsoft Corporation.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject

matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this

document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.

© 2013 Microsoft Corporation. All rights reserved.

The example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted

herein are fictitious. No association with any real company, organization, product, domain name, e-mail address, logo, person,

place, or event is intended or should be inferred.

Microsoft, Microsoft Dynamics, the Microsoft Dynamics logo, .NET Framework, Visual Studio, and Windows Azure are either

registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

The names of actual companies and products mentioned herein may be the trademarks of their respective owners.