Microsoft Dynamics 365
Learn how to integrate your Microsoft Dynamics instance with Strivacity Fusion, 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 Fusion)
  • If required, migrate customer information from Microsoft Dynamics to Strivacity Fusion upon account registration
They're two steps to setting up Strivacity Fusion 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 Fusion

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.
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:
9) Next, search for “user_impersonation”, and then click add permissions as shown below:
10) Now click on Manifest, and set allowPublicClient to true, as shown highlighted below:
This completes the initial configuration within Microsoft Dynamics 365 for use with Strivacity Fusion.

2) Setup a pre-registration hook within Strivacity Fusion

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, and DYNAMICS_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!
1
var dynamics = require('dynamics-web-api');
2
var AuthenticationContext = require('adal-node').AuthenticationContext;
3
4
// dynamics config
5
var DYNAMICS_AUTHORITY_URL = 'https://login.microsoftonline.com/<YOUR TENANT>/oauth2/token';
6
var DYNAMICS_RESOURCE = 'https://<YOUR DYNAMICS INSTANCE>.crm.dynamics.com/';
7
var DYNAMICS_CLIENT_ID = '<CLIENT ID>';
8
var DYNAMICS_CLIENT_SECRET = '<CLIENT SECRET>'
9
10
// get an adal context for use in auth
11
var adalContext = new AuthenticationContext(DYNAMICS_AUTHORITY_URL);
12
13
/** This function will be called from the Pre registration hook in a blocking manner.
14
*
15
* @param {Object} args Input arguments
16
* @param {Object} args.application Application related information
17
* @param {string} args.application.name Name
18
* @param {string} args.application.client_id OAuth client ID
19
*
20
* @param {Object} args.oidc_context Information about the originating OpenID Connect request
21
* @param {string[]} args.oidc_context.acr_values ACR values
22
* @param {string[]} args.oidc_context.ui_locales UI locales
23
*
24
* @param {Object} args.customer Customer related information
25
* @param {string} args.customer.ip_address HTTP client IP coming from the X-Forwarded-For header
26
* @param {string} args.customer.store Userstore
27
* @param {Object} args.customer.attributes User attributes provided during the registration
28
* @param {Object} args.customer.identifiers User identifiers provided during the registration
29
* @param {Object[]} args.customer.consents User consents accepted during the registration
30
* @param {string} args.customer.location.city City of the customer
31
* @param {string} args.customer.location.state State of the customer
32
* @param {string} args.customer.location.country Country of the customer
33
* @param {string} args.customer.location.country_code Country code of the customer
34
* @param {string} args.customer.location.coordinates.latitude Latitude coordinate of the customer
35
* @param {string} args.customer.location.coordinates.longitude Longitude coordinate of the customer
36
*
37
* @param {Object} args.session Session store
38
* @param {Object} args.continue_context Continue context
39
*
40
* @param {Object} args.continue_request_parameters Continue request parameters
41
* @param {string} args.continue_request_parameters.callback_url Callback url to use after a continue call
42
* @param {string} args.continue_request_parameters.state State parameter to use after a continue call
43
* @param {preRegistrationCallback} callback
44
* @param {denyRequestCallback} error
45
*/
46
module.exports = async function ({ application, oidc_context, customer, session, continue_context, continue_request_parameters }, callback, error) {
47
console.log(customer)
48
49
var client = new dynamics({
50
webApiUrl: DYNAMICS_RESOURCE + 'api/data/v9.1/',
51
onTokenRefresh: acquireToken
52
});
53
54
var records = await client.retrieveMultiple("contacts", ["fullname"], `emailaddress1 eq '${customer.attributes.emails.primaryEmail}'`)
55
console.log(records)
56
57
// the following function call does not modify the registering user
58
callback(new RegistrationData(customer.attributes, [], session));
59
};
60
61
/**
62
* Callback for acquiring a token via ADAL
63
*/
64
function acquireToken(callback) {
65
function adalcb(error, token) {
66
if (!error) {
67
callback(token);
68
} else {
69
throw new Error(error)
70
}
71
}
72
73
// get the token
74
adalContext.acquireTokenWithClientCredentials(DYNAMICS_RESOURCE, DYNAMICS_CLIENT_ID, DYNAMICS_CLIENT_SECRET, adalcb);
75
}
76
77
/** Allow registration
78
*
79
* @callback preRegistrationCallback
80
* @param {RegistrationData|RedirectRequest|ShowErrorMessage} token
81
*/
82
83
/** Deny registration
84
*
85
* @callback denyRequestCallback
86
* @param {ErrorDenyRequest} error
87
*/
88
89
/** RegistrationData */
90
class RegistrationData {
91
attributes = {}
92
additionalAuthenticators = []
93
session = {}
94
95
/**
96
* @constructor
97
* @param {Object} attributes
98
* @param {AdditionalAuthenticator[]} additionalAuthenticators
99
* @param {Object} session
100
*/
101
constructor(attributes, additionalAuthenticators, session) {
102
this.attributes = attributes;
103
this.additionalAuthenticators = additionalAuthenticators;
104
this.session = session;
105
}
106
}
107
108
/** AdditionalAuthenticator */
109
class AdditionalAuthenticator {
110
type = null;
111
target = null;
112
113
/**
114
* @constructor
115
* @param {"email"|"phone"} type
116
* @param {string} target
117
*/
118
constructor(type, target) {
119
this.type = type;
120
this.target = target;
121
}
122
}
123
124
/** RedirectRequest is a global object
125
* @constructor
126
* @param {string} redirect_url
127
* @param {Object} session
128
*/
129
130
/** ShowErrorMessage is a global object
131
* @constructor
132
* @param {string} error_message
133
* @param {Object} session
134
*/
135
136
/** ErrorDenyRequest is a global object
137
* @constructor
138
* @param {string} description
139
* @param {string} hint
140
*/
Copied!