npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mohsinonxrm/dataverse-sdk-auth-azure-identity

v1.0.0

Published

Azure Identity authentication provider for Dataverse SDK

Downloads

8

Readme

@mohsinonxrm/dataverse-sdk-auth-azure-identity

Azure Identity authentication provider for Dataverse SDK. Supports authentication using any credential from @azure/identity, making it ideal for Azure-hosted applications, local development, and service principal scenarios.

Installation

npm install @mohsinonxrm/dataverse-sdk-auth-azure-identity @mohsinonxrm/dataverse-sdk-core @azure/identity

Features

  • Managed Identity: Seamless authentication for Azure-hosted resources
  • DefaultAzureCredential: Automatic credential chain for development and production
  • Service Principal: Client secret or certificate-based authentication
  • Azure CLI: Local development using az login
  • Environment Variables: Credential configuration via environment
  • Workload Identity: Kubernetes workload identity support
  • TypeScript first: Fully typed with comprehensive IntelliSense

Supported Credentials

Works with any TokenCredential from @azure/identity:

| Credential | Best For | Authentication Method | | ------------------------------ | ------------------------------------------------- | ---------------------------------------- | | ManagedIdentityCredential | Azure VMs, App Service, Functions, Container Apps | System/user-assigned managed identity | | DefaultAzureCredential | Development & Production | Tries multiple credential types in order | | ClientSecretCredential | Service principals | Client ID + secret | | ClientCertificateCredential | Service principals | Client ID + certificate | | EnvironmentCredential | CI/CD pipelines | Environment variables | | AzureCliCredential | Local development | az login | | AzurePowerShellCredential | Local development | Connect-AzAccount | | DeviceCodeCredential | CLI tools | Device code flow | | InteractiveBrowserCredential | Desktop apps | Browser popup | | UsernamePasswordCredential | Legacy scenarios | Username + password | | WorkloadIdentityCredential | Kubernetes | Workload identity federation |

Usage

Managed Identity (Recommended for Azure)

Best for: Azure VMs, App Service, Functions, Container Apps, AKS

import { ManagedIdentityCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";
import { DataverseClient } from "@mohsinonxrm/dataverse-sdk-core";

// System-assigned managed identity
const credential = new ManagedIdentityCredential();

// Or user-assigned managed identity
// const credential = new ManagedIdentityCredential('client-id-of-user-assigned-identity');

const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: ["https://your-org.crm.dynamics.com/.default"],
});

const client = new DataverseClient({
  baseUrl: "https://your-org.crm.dynamics.com",
  tokenProvider,
});

// Use the client
const accounts = await client.api("/accounts").top(10).get();

DefaultAzureCredential (Development & Production)

Best for: Applications that run both locally and in Azure

import { DefaultAzureCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";

// Tries credentials in this order:
// 1. Environment variables
// 2. Workload Identity (Kubernetes)
// 3. Managed Identity
// 4. Azure CLI
// 5. Azure PowerShell
const credential = new DefaultAzureCredential();

const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: ["https://your-org.crm.dynamics.com/.default"],
});

Service Principal with Client Secret

Best for: CI/CD pipelines, daemon apps, server-to-server

import { ClientSecretCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";

const credential = new ClientSecretCredential("tenant-id", "client-id", "client-secret");

const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: ["https://your-org.crm.dynamics.com/.default"],
});

Service Principal with Certificate

Best for: Production daemons, enhanced security requirements

import { ClientCertificateCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";
import { readFileSync } from "fs";

const certificatePath = "/path/to/certificate.pem";
const certificate = readFileSync(certificatePath, "utf-8");

const credential = new ClientCertificateCredential("tenant-id", "client-id", certificate);

const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: ["https://your-org.crm.dynamics.com/.default"],
});

Azure CLI Credential (Local Development)

Best for: Local development, quick prototyping

import { AzureCliCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";

// Requires: az login
const credential = new AzureCliCredential();

const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: ["https://your-org.crm.dynamics.com/.default"],
});

Environment Variables

Best for: CI/CD, containerized apps

# Set environment variables for service principal
export AZURE_TENANT_ID="your-tenant-id"
export AZURE_CLIENT_ID="your-client-id"
export AZURE_CLIENT_SECRET="your-client-secret"
import { EnvironmentCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";

const credential = new EnvironmentCredential();

const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: ["https://your-org.crm.dynamics.com/.default"],
});

Workload Identity (Kubernetes)

Best for: AKS workloads with federated identity

import { WorkloadIdentityCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";

const credential = new WorkloadIdentityCredential({
  tenantId: "tenant-id",
  clientId: "client-id",
});

const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: ["https://your-org.crm.dynamics.com/.default"],
});

Complete Examples

Azure Function with Managed Identity

import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
import { ManagedIdentityCredential } from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";
import { DataverseClient } from "@mohsinonxrm/dataverse-sdk-core";

// Initialize once (cold start)
const credential = new ManagedIdentityCredential();
const tokenProvider = new AzureIdentityTokenProvider(credential, {
  scopes: [process.env.DATAVERSE_URL + "/.default"],
});

const client = new DataverseClient({
  baseUrl: process.env.DATAVERSE_URL!,
  tokenProvider,
});

export async function getAccounts(
  request: HttpRequest,
  context: InvocationContext
): Promise<HttpResponseInit> {
  context.log("HTTP trigger function processing request");

  try {
    const result = await client.api("/accounts").select("name", "accountnumber").top(100).get();

    return {
      status: 200,
      jsonBody: result.value,
    };
  } catch (error) {
    context.error("Error fetching accounts:", error);
    return {
      status: 500,
      body: "Internal server error",
    };
  }
}

app.http("getAccounts", {
  methods: ["GET"],
  authLevel: "function",
  handler: getAccounts,
});

Multi-Environment Configuration

import {
  DefaultAzureCredential,
  AzureCliCredential,
  ManagedIdentityCredential,
} from "@azure/identity";
import { AzureIdentityTokenProvider } from "@mohsinonxrm/dataverse-sdk-auth-azure-identity";
import { DataverseClient } from "@mohsinonxrm/dataverse-sdk-core";

function createTokenProvider() {
  const scopes = [process.env.DATAVERSE_URL + "/.default"];

  let credential;

  if (process.env.NODE_ENV === "development") {
    // Local development: use Azure CLI
    credential = new AzureCliCredential();
    console.log("Using Azure CLI credential for local development");
  } else if (process.env.USE_MANAGED_IDENTITY === "true") {
    // Production: use managed identity
    credential = new ManagedIdentityCredential();
    console.log("Using Managed Identity credential for production");
  } else {
    // Fallback: try DefaultAzureCredential
    credential = new DefaultAzureCredential();
    console.log("Using DefaultAzureCredential");
  }

  return new AzureIdentityTokenProvider(credential, { scopes });
}

const tokenProvider = createTokenProvider();
const client = new DataverseClient({
  baseUrl: process.env.DATAVERSE_URL!,
  tokenProvider,
});

API Reference

Constructor

constructor(
  credential: TokenCredential,
  options: AzureIdentityTokenProviderOptions
)

Parameters:

  • credential (required): Any TokenCredential from @azure/identity
  • options (required): Configuration options

Options:

  • scopes (required): Default scopes (e.g., ['https://org.crm.dynamics.com/.default'])
  • tenantId (optional): Tenant ID for multi-tenant scenarios
  • getTokenOptions (optional): Additional GetTokenOptions for Azure Identity

Methods

getToken(scopes?, options?): Promise<string>

Acquires an access token using the configured credential.

Parameters:

  • scopes (optional): String or array of scopes to override default scopes
  • options (optional): Token options
    • tenantId: Override tenant ID for multi-tenant scenarios
    • claims: Claims challenge from server (Conditional Access)
    • correlationId: Correlation ID for telemetry (not passed to Azure Identity)

Returns: Promise<string> - Access token

Throws:

  • DataverseAuthenticationError - Token acquisition failed
  • DataverseInvalidRequestError - Invalid scopes or configuration
// Use default scopes
const token = await tokenProvider.getToken();

// Override with different scopes
const token = await tokenProvider.getToken(["https://other-org.crm.dynamics.com/.default"]);

// Pass additional options
const token = await tokenProvider.getToken(undefined, {
  tenantId: "specific-tenant-id",
  claims: '{"access_token":{"email":{"essential":true}}}',
  correlationId: "correlation-123", // Stored but not passed to Azure Identity
});

getCredential(): TokenCredential

Gets the underlying TokenCredential instance for advanced scenarios.

Returns: TokenCredential - The Azure Identity credential

const credential = tokenProvider.getCredential();
// Use credential directly if needed

getOptions(): Readonly<AzureIdentityTokenProviderOptions>

Gets the current configuration options (frozen copy).

Returns: Readonly<AzureIdentityTokenProviderOptions> - Immutable options object

const options = tokenProvider.getOptions();
console.log("Default scopes:", options.scopes);
console.log("Tenant ID:", options.tenantId);

Error Handling

import {
  DataverseAuthenticationError,
  DataverseInvalidRequestError,
} from "@mohsinonxrm/dataverse-sdk-core";

try {
  const token = await tokenProvider.getToken();
} catch (error) {
  if (error instanceof DataverseAuthenticationError) {
    console.error("Authentication failed:", error.message);
    // Original Azure Identity error available in error.cause
    if (error.cause) {
      console.error("Azure Identity error:", error.cause);
    }
  } else if (error instanceof DataverseInvalidRequestError) {
    console.error("Invalid configuration:", error.message);
  }
}

Azure Setup

1. Create Managed Identity

# System-assigned (VM, App Service, Function)
az vm identity assign --name myVM --resource-group myResourceGroup

# User-assigned
az identity create --name myIdentity --resource-group myResourceGroup

2. Grant Dataverse Permissions

  1. Go to Power Platform Admin Center
  2. Select your environment
  3. Settings → Users + permissions → Application users
  4. Click "+ New app user"
  5. Add the managed identity or service principal
  6. Assign security roles (e.g., System Administrator, System Customizer)

3. Configure App Registration (Service Principal)

# Create app registration
az ad app create --display-name "Dataverse SDK App"

# Create service principal
az ad sp create --id <app-id>

# Create client secret
az ad app credential reset --id <app-id>

Comparison with MSAL

| Feature | Azure Identity | MSAL Node | MSAL Browser | | ---------------------- | ----------------- | -------------------- | ------------ | | Managed Identity | ✅ Yes | ❌ No | ❌ No | | Azure CLI | ✅ Yes | ❌ No | ❌ No | | DefaultAzureCredential | ✅ Yes | ❌ No | ❌ No | | Service Principal | ✅ Yes | ✅ Yes | ❌ No | | Device Code | ✅ Yes | ✅ Yes | ❌ No | | Interactive Browser | ✅ Yes (desktop) | ❌ No | ✅ Yes (SPA) | | Best For | Azure-hosted apps | Multi-flow Node apps | Browser SPAs |

Recommendation: Use Azure Identity for server-side Azure apps, MSAL for client apps or multi-flow requirements.

Troubleshooting

Managed Identity 403 Forbidden

Ensure:

  1. Managed identity is enabled on Azure resource
  2. Application user created in Dataverse with managed identity's client ID
  3. Security roles assigned to application user

DefaultAzureCredential Fails Locally

# Sign in with Azure CLI
az login

# Or sign in with Azure PowerShell
Connect-AzAccount

Environment Variables Not Working

Verify all three are set:

echo $AZURE_TENANT_ID
echo $AZURE_CLIENT_ID
echo $AZURE_CLIENT_SECRET

Certificate Authentication Issues

Ensure certificate is in PEM format:

# Convert PFX to PEM
openssl pkcs12 -in cert.pfx -out cert.pem -nodes

License

AGPL-3.0