@primno/dataverse-auth
v0.7.0
Published
Authenticate to Dataverse and Dynamics 365 with a connection string or OAuth 2.0. Provides a token persistence cache.
Downloads
32
Maintainers
Readme
Dataverse Authentication for Node.JS
@primno/dataverse-auth
is a library for Node.JS to authenticate to Dataverse / Dynamics 365.
@primno/dataverse-auth
provides:
- Authentication from:
- Connection string.
- OAuth2 flow:
- Device code flow.
- Client credentials flow.
- Username/password flow.
- Persistent token cache to avoid re-authenticating.
- Authority discovery
Works with @primno/dataverse-client
to make requests to Dataverse / Dynamics 365 CE, but can be used as a standalone library.
This package is part of the Primno framework.
Compatibility
@primno/dataverse-auth
works with Dataverse / Dynamics 365.
Dynamics 365 CE (on-premises) is supported since version 9.0 with CBA/IFD deployment (ADFS 2019+ with OAuth enabled in deployment settings).
Tip If you are using Dynamics 365 App for Outlook on your on-premises environment, the prerequisite are met.
Quick start
Installation
npm install @primno/dataverse-auth
Usage
With connection string authentication:
import { ConnStringTokenProvider } from '@primno/dataverse-auth';
const tokenProvider = new ConnStringTokenProvider(
"AuthType=OAuth;Url=https://<Environnement>.crm.dynamics.com;UserName=<UserName>;TokenCacheStorePath=./.cache/token.json",
{
oAuth: {
// For persistent token cache on Linux/Mac to store the token in the keychain.
// Only used when TokenCacheStorePath is set.
persistence: {
serviceName: "<serviceName>", // Optional, default to "Primno.DataverseClient"
accountName: "<accountName>" // Optional, default to "MSALCache"
},
// For device code flow
deviceCodeCallback: (deviceCode) => {
console.log(deviceCode.message);
}
}
}
);
const token = await tokenProvider.getToken();
With OAuth:
import { OAuthTokenProvider } from '@primno/dataverse-auth';
const tokenProvider = new OAuthTokenProvider({
url: "https://<Environment>.crm.dynamics.com",
credentials: {
clientId: "51f81489-12ee-4a9e-aaae-a2591f45987d", // Sample client id
redirectUri: "app://58145B91-0C36-4500-8554-080854F2AC97", // Sample redirect uri
authorityUrl: "https://login.microsoftonline.com/common",
scope: "https://<Environment>.crm.dynamics.com/.default",
grantType: "device_code",
userName: "<Username>"
},
persistence: {
enabled: false
},
deviceCodeCallback: (deviceCode) => {
console.log(deviceCode.message);
}
});
const token = await tokenProvider.getToken();
Authentication
dataverse-auth is provided with 2 authentication providers :
- Connection string
- OAuth2
Connection string
ConnStringTokenProvider
provides a token by using a connection string (see Dataverse doc and D365 CE on-premises doc).
Only OAuth
authentication type is supported.
The token can be persisted using the TokenCacheStorePath
connection string parameter. To learn more about the token cache, see Token cache.
const tokenProvider = new ConnStringTokenProvider(
"AuthType=OAuth;Url=https://<Environnement>.crm.dynamics.com;UserName=<UserName>;TokenCacheStorePath=./.cache/token.json",
{
oAuth: {
// For persistent token cache on Linux/Mac to store the token in the keychain.
// Only used when TokenCacheStorePath is set.
persistence: {
serviceName: "<serviceName>", // Optional, default to "Primno.DataverseClient"
accountName: "<accountName>" // Optional, default to "MSALCache"
},
// For device code flow. Show the url and code to the user.
deviceCodeCallback: (deviceCode) => {
console.log(deviceCode.message);
}
}
}
);
OAuth flows
ConnStringTokenProvider
determines which OAuth flow to use based on the parameters in the connection string.
| Parameters | Flow |
|-----------|------|
| UserName
and Password
| User password |
| ClientId
and ClientSecret
| Client credential |
| UserName
only | Device code |
Note Device code flow allows to authenticate with MFA enabled.
Examples:
| Environment | AuthType | OAuth flow | Connection string |
|-------------|----------|------------|-------------------|
| Dataverse | OAuth | Device code | AuthType=OAuth;Url=https://<Environnement>.crm.dynamics.com;UserName=<UserName>
|
| Dataverse | OAuth | User password | AuthType=OAuth;Url=https://<Environnement>.crm.dynamics.com;UserName=<UserName>;Password=<Password>
|
| Dataverse | OAuth | Client credential | AuthType=OAuth;Url=https://<Environnement>.crm.dynamics.com;ClientId=<ClientId>;ClientSecret=<ClientSecret>;RedirectUri=<RedirectUri>
|
| On-premises | OAuth | User password | AuthType=OAuth;RedirectUri=<RedirectUri>;Url=https://<D365Url>;UserName=<Domain>\<UserName>;Password=<Password>
|
OAuth2
OAuthTokenProvider
provides OAuth2 authentication.
const tokenProvider = new OAuthTokenProvider(options);
Options definition:
interface OAuthConfig {
/**
* OAuth2 credentials
*/
credentials: {
/**
* OAuth flow
*/
grantType: "client_credential" | "password" | "device_code";
/**
* Client ID.
* @default "51f81489-12ee-4a9e-aaae-a2591f45987d" (Sample client id)
*/
clientId?: string;
/**
* Client secret for ConfidentialClientApplication.
* If set, clientCertificate is not required.
*/
clientSecret?: string;
/**
* Client certificate for ConfidentialClientApplication.
* If set, clientSecret is not required.
*/
clientCertificate?: {
thumbprint: string;
privateKey: string;
},
/**
* Authority URL (eg: https://login.microsoftonline.com/common/)
*/
authorityUrl: string;
/**
* Username for password and device_code flow.
*/
userName?: string;
/**
* Password for password flow.
*/
password?: string;
/**
* Redirect URI.
*/
redirectUri?: string;
/**
* Scope. Dataverse url suffixed with .default.
*/
scope?: string;
};
/**
* Persistence options
*/
persistence: {
/**
* Enable persistence. Default: false.
*/
enabled: true;
/**
* Cache path.
*/
cachePath: string;
/**
* Service name. Only used on Linux/MacOS to store the token in the keychain. Default: "Primno.DataverseClient"
*/
serviceName: string;
/**
* Account name. Only used on Linux/MacOS to store the token in the keychain. Default: "MSALCache"
*/
accountName: string;
};
/**
* Device code callback. Only used when grant_type is device_code.
* @param response The device code response
* @returns
*/
deviceCodeCallback?: (response: DeviceCodeResponse) => void;
/**
* Dataverse / D365 url. Eg: https://org.crm.dynamics.com
*/
url: string;
}
Discover authority
To discover the authority url, you can use the discoverAuthority
method.
interface Authority {
authUrl: string;
resource?: string;
}
const authority: Authority = await discoverAuthority("<DataverseOrOnPremisesUrl>");
Token cache persistence
The token can be persisted using the persistence
option.
It is encrypted using DPAPI
on Windows, libsecret
on Linux and the Keychain
on MacOS.
Queries
If you want to query the Dataverse API, you can use @primno/dataverse-client
package.
Troubleshooting
Unable to verify the first certificate
On on-premises
environments, you may have this error :
Error: unable to verify the first certificate
To fix this issue, you can add your enterprise CA certificate to the trusted root certificate authorities by setting the NODE_EXTRA_CA_CERTS
environment variable. See Node.js documentation for more information.
Credits
Thanks to Microsoft for persistence cache (msal-node-extensions).