node.jsazureazure-ad-msalazure-authenticationazure-service-principal

How to avoid explicitly acquiring access tokens when calling Microsoft Graph API in Node.js?


I’m building a Node.js app that uses the Microsoft Graph API, and I recently switched from using a client secret to a client certificate for authentication (better security and all that good stuff). Right now, I’m using @azure/msal-node to manually grab an access token and make API calls. It works, but honestly, managing tokens like this feels a bit clunky.

Here’s a simplified version of what I’m doing:

const msal = require('@azure/msal-node');
const fs = require('fs');

const config = {
    auth: {
        clientId: 'appId',
        authority: `https://login.microsoftonline.com/tenantId`,
        clientCertificate: {
            thumbprint: 'certificateThumbprint',
            privateKey: fs.readFileSync('./certificate.pem', 'utf8'),
        },
    },
};

const cca = new msal.ConfidentialClientApplication(config);

async function getAccessToken() {
    const request = { scopes: ['https://graph.microsoft.com/.default'] };
    const response = await cca.acquireTokenByClientCredential(request);
    return response.accessToken;
}

async function listUsers() {
    const token = await getAccessToken();
    const options = {
        headers: { Authorization: `Bearer ${token}` },
    };
    const axios = require('axios');
    const response = await axios.get('https://graph.microsoft.com/v1.0/users', options);
    console.log(response.data);
}

listUsers();

What I’m hoping to do now is simplify this whole process by using Microsoft Graph SDK. I’ve read that it can handle authentication and API calls more seamlessly, which sounds amazing, but I’m not quite sure how to set it up to work with my client certificate.


Solution

  • You can refer this MS Document for using client certificate as auth provider with Microsoft Graph SDK.

    Initially, I registered one application and uploaded client certificate to it as below:

    enter image description here

    Now, I used below modified code by installing libraries like @azure/identity, @microsoft/microsoft-graph-client and @isomorphic-fetch to call MS Graph:

    const { ClientCertificateCredential } = require('@azure/identity');
    const { Client } = require('@microsoft/microsoft-graph-client');
    const { TokenCredentialAuthenticationProvider } = require('@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials');
    require('isomorphic-fetch');
    
    const tenantId = 'tenantId';
    const clientId = 'appId';
    const certificatePath = './certificate.pem';
    
    const credential = new ClientCertificateCredential(tenantId, clientId, certificatePath);
    
    const authProvider = new TokenCredentialAuthenticationProvider(credential, {
        scopes: ['https://graph.microsoft.com/.default'],
    });
    
    const graphClient = Client.initWithMiddleware({ authProvider });
    
    async function listUsers() {
        try {
            const users = await graphClient.api('/users').get();
            console.log(users);
        } catch (error) {
            console.error(`Error fetching users: ${error}`);
        }
    }
    
    listUsers();
    

    Response:

    enter image description here