Microsoft Dynamics 365
Learn how to integrate your Microsoft Dynamics instance with Strivacity, allowing Strivacity to add, update and maintain customer information and use it as a source of entitlement.
Integrating Strivacity with Microsoft Dynamics provides the following benefits:
- Use Microsoft Dynamics customer information as a source of entitlement during customer registration, login, or any step within the customer account lifecycle
- Create new customer records, and synchronize/update those customer records with the latest customer account information (from Strivacity)
- If required, migrate customer information from Microsoft Dynamics to Strivacity upon account registration
They're two steps to setting up Strivacity with Microsoft Dynamics 365:
1) Setup Microsoft Power Platform to register Strivacity as an Application and define API permissions for the application, and enable public client access
2) Setup a pre-registration hook within Strivacity
1) Setup Microsoft Power Platform to register Strivacity as an Application
1) From within the Azure Active Directory Dashboard, click on App registrations, and click + New registration
2) Define a name for your new application
3) Choose Accounts in any organizational directory (Any Azure AD directory - Multitenant)
4) Click the Register button. Your newly created application should be registered as shown in the screenshot below.
Make a record of the ClientID so that you can use it at a later stage of the integration.
.png)
5) Next, click on Certificates and Secrets
6) Click on New client secret and copy it to a safe location for use later in this integration. Note you will not be able to copy the secret again later
7) Next, click on API permissions, and then Add a permission
8) Select Dynamics CRM as shown below:
.png)
9) Next, search for “user_impersonation”, and then click add permissions as shown below:
.png)
10) Now click on Manifest, and set allowPublicClient to true, as shown highlighted below:
.png)
This completes the initial configuration within Microsoft Dynamics 365 for use with Strivacity.
2) Setup a pre-registration hook within Strivacity
1) Log into the Strivacity Admin Console using an Admin role, or a role that has delegated access to create a Lifecycle Event Hook.
Using the pre-registration hook code below, do the following:
- Define
DYNAMICS_AUTHORITY_URL
,DYNAMICS_RESOURCE
,DYNAMICS_CLIENT_ID
, andDYNAMICS_CLIENT_SECRET
you noted from step 1 above.
This will search Microsoft Dynamics 365 for a contact matching the primary email address
Now add any additional logic as you see fit!
var dynamics = require('dynamics-web-api');
var AuthenticationContext = require('adal-node').AuthenticationContext;
// dynamics config
var DYNAMICS_AUTHORITY_URL = 'https://login.microsoftonline.com/<YOUR TENANT>/oauth2/token';
var DYNAMICS_RESOURCE = 'https://<YOUR DYNAMICS INSTANCE>.crm.dynamics.com/';
var DYNAMICS_CLIENT_ID = '<CLIENT ID>';
var DYNAMICS_CLIENT_SECRET = '<CLIENT SECRET>'
// get an adal context for use in auth
var adalContext = new AuthenticationContext(DYNAMICS_AUTHORITY_URL);
/** This function will be called from the Pre registration hook in a blocking manner.
*
* @param {Object} args Input arguments
* @param {Object} args.application Application related information
* @param {string} args.application.name Name
* @param {string} args.application.client_id OAuth client ID
*
* @param {Object} args.oidc_context Information about the originating OpenID Connect request
* @param {string[]} args.oidc_context.acr_values ACR values
* @param {string[]} args.oidc_context.ui_locales UI locales
*
* @param {Object} args.customer Customer related information
* @param {string} args.customer.ip_address HTTP client IP coming from the X-Forwarded-For header
* @param {string} args.customer.store Userstore
* @param {Object} args.customer.attributes User attributes provided during the registration
* @param {Object} args.customer.identifiers User identifiers provided during the registration
* @param {Object[]} args.customer.consents User consents accepted during the registration
* @param {string} args.customer.location.city City of the customer
* @param {string} args.customer.location.state State of the customer
* @param {string} args.customer.location.country Country of the customer
* @param {string} args.customer.location.country_code Country code of the customer
* @param {string} args.customer.location.coordinates.latitude Latitude coordinate of the customer
* @param {string} args.customer.location.coordinates.longitude Longitude coordinate of the customer
*
* @param {Object} args.session Session store
* @param {Object} args.continue_context Continue context
*
* @param {Object} args.continue_request_parameters Continue request parameters
* @param {string} args.continue_request_parameters.callback_url Callback url to use after a continue call
* @param {string} args.continue_request_parameters.state State parameter to use after a continue call
* @param {preRegistrationCallback} callback
* @param {denyRequestCallback} error
*/
module.exports = async function ({ application, oidc_context, customer, session, continue_context, continue_request_parameters }, callback, error) {
console.log(customer)
var client = new dynamics({
webApiUrl: DYNAMICS_RESOURCE + 'api/data/v9.1/',
onTokenRefresh: acquireToken
});
var records = await client.retrieveMultiple("contacts", ["fullname"], `emailaddress1 eq '${customer.attributes.emails.primaryEmail}'`)
console.log(records)
// the following function call does not modify the registering user
callback(new RegistrationData(customer.attributes, [], session));
};
/**
* Callback for acquiring a token via ADAL
*/
function acquireToken(callback) {
function adalcb(error, token) {
if (!error) {
callback(token);
} else {
throw new Error(error)
}
}
// get the token
adalContext.acquireTokenWithClientCredentials(DYNAMICS_RESOURCE, DYNAMICS_CLIENT_ID, DYNAMICS_CLIENT_SECRET, adalcb);
}
/** Allow registration
*
* @callback preRegistrationCallback
* @param {RegistrationData|RedirectRequest|ShowErrorMessage} token
*/
/** Deny registration
*
* @callback denyRequestCallback
* @param {ErrorDenyRequest} error
*/
/** RegistrationData */
class RegistrationData {
attributes = {}
additionalAuthenticators = []
session = {}
/**
* @constructor
* @param {Object} attributes
* @param {AdditionalAuthenticator[]} additionalAuthenticators
* @param {Object} session
*/
constructor(attributes, additionalAuthenticators, session) {
this.attributes = attributes;
this.additionalAuthenticators = additionalAuthenticators;
this.session = session;
}
}
/** AdditionalAuthenticator */
class AdditionalAuthenticator {
type = null;
target = null;
/**
* @constructor
* @param {"email"|"phone"} type
* @param {string} target
*/
constructor(type, target) {
this.type = type;
this.target = target;
}
}
/** RedirectRequest is a global object
* @constructor
* @param {string} redirect_url
* @param {Object} session
*/
/** ShowErrorMessage is a global object
* @constructor
* @param {string} error_message
* @param {Object} session
*/
/** ErrorDenyRequest is a global object
* @constructor
* @param {string} description
* @param {string} hint
*/
Updated 5 months ago