Back

Step by Step Guide to Building a Microsoft Entra ID API Integration in JS

Aug 9, 20248 minute read

Hey there, fellow developer! Ready to dive into the world of Microsoft Entra ID API integration? Buckle up, because we're about to embark on a journey that'll level up your authentication game. Let's get started!

Introduction

Microsoft Entra ID (formerly Azure AD) is a powerhouse when it comes to identity and access management. By integrating it into your JavaScript app, you're opening doors to secure, seamless authentication and authorization. Trust me, your future self will thank you for this.

Prerequisites

Before we jump in, make sure you've got:

  • Node.js and npm (you're a JS dev, so I'm betting you've got this covered)
  • A Microsoft Azure account (if you don't have one, now's the perfect time to get one)
  • An application registered in the Azure portal (don't worry, we'll touch on this)

Setting up the project

Let's lay the groundwork:

mkdir entra-id-integration cd entra-id-integration npm init -y npm install @azure/msal-node axios dotenv

Create a .env file in your project root. We'll use this to store our secrets safely.

Configuring Azure AD application

Head over to the Azure portal and:

  1. Register a new application
  2. Grab your client ID, tenant ID, and generate a client secret
  3. Set up a redirect URI (use http://localhost:3000/redirect for now)
  4. Add the Microsoft Graph API permissions you need

Pop these details into your .env file:

CLIENT_ID=your_client_id
TENANT_ID=your_tenant_id
CLIENT_SECRET=your_client_secret
REDIRECT_URI=http://localhost:3000/redirect

Implementing authentication

Time to bring in the big guns - MSAL.js:

const msal = require('@azure/msal-node'); const config = { auth: { clientId: process.env.CLIENT_ID, authority: `https://login.microsoftonline.com/${process.env.TENANT_ID}`, clientSecret: process.env.CLIENT_SECRET } }; const cca = new msal.ConfidentialClientApplication(config);

Now, let's set up login and token acquisition:

async function getToken() { const authCodeUrlParameters = { scopes: ["user.read"], redirectUri: process.env.REDIRECT_URI, }; // Get URL to sign user in and consent to scopes needed for application const authUrl = await cca.getAuthCodeUrl(authCodeUrlParameters); console.log("Authorize here:", authUrl); // Handle the response from Azure AD (you'd typically do this in a route handler) const tokenRequest = { code: authorizationCode, // You'll get this from the redirect scopes: ["user.read"], redirectUri: process.env.REDIRECT_URI, }; const response = await cca.acquireTokenByCode(tokenRequest); return response.accessToken; }

Making API calls

With our token in hand, let's make some API magic happen:

const axios = require('axios'); async function callMsGraph(accessToken) { const options = { headers: { Authorization: `Bearer ${accessToken}` } }; const response = await axios.get('https://graph.microsoft.com/v1.0/me', options); return response.data; }

Implementing token caching and refresh

MSAL.js handles token caching for us (thanks, Microsoft!), but let's set up silent token refresh:

async function getTokenSilently() { const account = await cca.getTokenCache().getAllAccounts()[0]; const silentRequest = { account: account, scopes: ["user.read"], }; try { const response = await cca.acquireTokenSilent(silentRequest); return response.accessToken; } catch (error) { if (error instanceof msal.InteractionRequiredAuthError) { return getToken(); // Fall back to interactive method } throw error; } }

Error handling and logging

Always be prepared:

function handleError(error) { console.error('An error occurred:', error); if (error.response) { console.error('Response data:', error.response.data); console.error('Response status:', error.response.status); } } // Use it like this: try { const token = await getTokenSilently(); const userData = await callMsGraph(token); } catch (error) { handleError(error); }

Testing the integration

I know you're itching to see this in action. Here's a quick test script:

async function testIntegration() { try { const token = await getToken(); console.log('Token acquired successfully'); const userData = await callMsGraph(token); console.log('User data:', userData); } catch (error) { handleError(error); } } testIntegration();

Best practices and security considerations

Remember, with great power comes great responsibility:

  • Never, ever commit your .env file to version control
  • Use the principle of least privilege when requesting scopes
  • Regularly rotate your client secrets
  • Keep your dependencies updated

Conclusion

And there you have it! You've just built a robust Microsoft Entra ID API integration. Pat yourself on the back – you've taken a big step towards more secure and efficient authentication in your apps.

Remember, this is just the beginning. The Microsoft Graph API has a ton of endpoints to explore, so don't be afraid to experiment and expand on what you've learned here.

Keep coding, keep learning, and most importantly, keep having fun with it!