Graph Javascript SDK with Azure Identity

A while back I wrote about how using a custom authentication provider with the Graph SDK would allow for the use of a client credential flow. Since then, I began using the @azure/identity package to obtain the access token instead.

However, with the release of the Graph Javascript SDK 3.0, this is no longer needed. With the use of TokenCredentialAuthenticationProvider you can now pass the generated Credential from @azure/identity directly in to TokenCredentialAuthenticationProvider and use the SDK without having to manage the retrival of the token.

This will work with all different @azure/identity credential types such as ClientSecretCredential, ClientCertificateCredential and DefaultAzureCredential.

In this example I am using DefaultAzureCredential as this allows the same code to use environmental variables (client credentials) during development locally, but then when deployed in Azure, Managed Identity - neat!

image (Source: https://docs.microsoft.com/en-us/javascript/api/overview/azure/identity-readme?view=azure-node-latest#defaultazurecredential)

For this to work locally, you will need some environmental variables configured:

AZURE_CLIENT_ID = <Azure AD Application (client) ID>
AZURE_TENANT_ID = <Azure AD Directory (tenant) ID>
AZURE_CLIENT_SECRET = <Azure AD Client Secret>

And here is the code with the basic logic:

  1. DefaultAzureCredential generated from environmental variables (client credential)
  2. DefaultAzureCredential passed to TokenCredentialAuthenticationProvider with the default Graph scope
  3. authProvider configured in Graph clientOptions
import * as dotenv from "dotenv";
import "isomorphic-fetch";
import { Client, ClientOptions } from "@microsoft/microsoft-graph-client";
import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials";
import { DefaultAzureCredential } from "@azure/identity";
import { User } from "@microsoft/microsoft-graph-types";

dotenv.config()

export class Graph {

    client: Client;

    constructor() {
        const credential = new DefaultAzureCredential();
        const authProvider = new TokenCredentialAuthenticationProvider(credential, { scopes: ["https://graph.microsoft.com/.default"] });
        const clientOptions: ClientOptions = {
            defaultVersion: "v1.0",
            debugLogging: false,
            authProvider
        };
        this.client = Client.initWithMiddleware(clientOptions);
    }

    async getUsersAll(): Promise<User[]> {
        const request = await this.client.api("/users/")
            .top(5)
            .get();
        return request.value;
    }

}

const graph = new Graph();
graph.getUsersAll()
    .then((users) => {
        console.log(users);
    }).catch((error) => {
        console.error(error);
    });

Running the script should result in the following:

image

If you would like to try this for yourself I have put some sample code here