title: Microsoft Graph API calls through Express app
body: <p>I am trying to follow this tutorial here: <a href="https://github.com/Azure-Samples/ms-identity-javascript-nodejs-tutorial/tree/main/2-Authorization/1-call-graph" rel="nofollow noreferrer">https://github.com/Azure-Samples/ms-identity-javascript-nodejs-tutorial/tree/main/2-Authorization/1-call-graph</a>. It uses the microsoft-identity-express wrapper for msal-node, but I am having trouble with some Graph routes.</p>
  <p>I have set up my Azure AD app permissions exactly as described in the tutorial.</p>
  <p>I have successfully got the /profile route working, like this:</p>
  <pre><code>router.get('/profile',
      msid.isAuthenticated(), 
      msid.getToken({
          resource: appSettings.protectedResources.graphAPI
      }), 
      async (req,res,next) =&gt; {
          let output;
          
          try {
              const graphClient = graphManager.getAuthenticatedClient(req.session.protectedResources[&quot;graphAPI&quot;].accessToken);
  
              output = await graphClient
                      .api('/me')
                      .get();
  
          } catch (error) {
              console.log(error);
              next(error);
          }
          res.send(output);
      }
  );
  </code></pre>
  <p>My appSettings look like this:</p>
  <pre><code>    const appSettings = {
      appCredentials: {
          clientId: &quot;zzz&quot;,
          tenantId: &quot;yyy&quot;,
          clientSecret: &quot;xxx&quot;
      },
      authRoutes: {
          redirect: &quot;/redirect&quot;,
          error: &quot;/error&quot;, // the wrapper will redirect to this route in case of any error
          unauthorized: &quot;/unauthorized&quot; // the wrapper will redirect to this route in case of unauthorized access attempt
      },
      protectedResources: {
          graphAPI: {
              endpoint: &quot;https://graph.microsoft.com/v1.0/me&quot;,
              scopes: [&quot;user.read&quot;]
          },
          armAPI: {
              endpoint: &quot;https://management.azure.com/tenants?api-version=2020-01-01&quot;,
              scopes: [&quot;https://management.azure.com/user_impersonation&quot;]
          },
          joinedTeams: {
              endpoint: &quot;https://graph.microsoft.com/v1.0/me/joinedTeams&quot;,
              scopes: [&quot;user.read&quot;, &quot;teamsettings.readwrite.all&quot;]
          },
          myEvents: {
              endpoint: &quot;https://graph.microsoft.com/v1.0/me/events&quot;,
              scopes: [&quot;user.read&quot;, &quot;calendars.readwrite&quot;]
          },
          messages: {
              endpoint: &quot;https://graph.microsoft.com/v1.0/me/messages&quot;,
              scopes: [&quot;Mail.ReadWrite&quot;]
          }
      }
  };
  </code></pre>
  <p>And finally, my getAuthenticatedClient function from graphManager is:</p>
  <pre><code>const getAuthenticatedClient = (accessToken) =&gt; {
      // Initialize Graph client
      const client = graph.Client.init({
          // Use the provided access token to authenticate requests
          authProvider: (done) =&gt; {
              done(null, accessToken);
          }
      });
  
      return client;
  };
  </code></pre>
  <p>graphManager and appSettings are set up exactly how the tutorial does it. I added more API endpoints to the protectedResources object as the tutorial says. I followed the same logic process as the /profile route for the extra Graph API routes. But I still get 401 errors whenever running this:</p>
  <pre><code>router.get('/me/events',
      msid.isAuthenticated(),
      msid.getToken({
          resource: appSettings.protectedResources.myEvents
      }),
      async (req,res,next) =&gt; {
          let output;
          
          try {
              const graphClient = graphManager.getAuthenticatedClient(req.session.protectedResources[&quot;myEvents&quot;].accessToken);
  
              output = await graphClient
                      .api('/me/events')
                      .get();
  
          } catch (error) {
              console.log(error);
              next(error);
          }
          res.send(output);
      }
  );
  </code></pre>
  <p>I can't understand why /me calls to the Graph API work but /me/events does not. The correct permissions are being passed to msid.getToken() and getAuthenticatedClient(), so why do the API calls fail?</p>