Search code examples
microsoft-graph-apimicrosoft-teams

how to get ms graph api access token with channel message send permission


I am trying to send an adaptive card from a React app to an MS teams channel. I've granted the "ChannelMessage.Send" permission to the app created in the App registrations. Below is the code copied from Postman:

var axios = require('axios');
var qs = require('qs');
var data = qs.stringify({
  'client_id': 'xxx',
  'scope': 'https://graph.microsoft.com/.default',
  'client_secret': 'xxx',
  'grant_type': 'client_credentials' 
});
var config = {
  method: 'post',
  url: 'https://login.microsoftonline.com/xxx/oauth2/v2.0/token',
  headers: { 
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  data : data
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});

However, the access token returned only has following roles:

"roles": [
    "User.Read.All"
  ],

If I use this token to send message, I receive a "forbidden" error. How can I obtain the right access token to send message to a team channel? I tried following scopes, neither are valid.

https://graph.microsoft.com/.default+ChannelMessage.Send https://graph.microsoft.com/.default ChannelMessage.Send


Solution

  • Your provided code is for obtaining an access token using the client credentials flow, which is suitable for server-to-server communication. However, for sending messages to a Teams channel, you need to use the user token of the user who is sending the message.

    To obtain the user token, you can use the Microsoft Authentication Library (MSAL) for JavaScript in your React app. Here's an example of how you can obtain the user token:

    import { PublicClientApplication } from '@azure/msal-browser';
    
    const msalConfig = {
      auth: {
        clientId: 'YOUR_CLIENT_ID',
        redirectUri: 'http://localhost:3000', // Replace with your app's redirect URI
      },
    };
    
    const msalInstance = new PublicClientApplication(msalConfig);
    
    // Request the necessary scopes
    const loginRequest = {
      scopes: ['ChannelMessage.Send'],
    };
    
    // Sign in the user and obtain the token
    msalInstance.loginPopup(loginRequest)
      .then((response) => {
        // Access token is available in response.accessToken
        console.log(response.accessToken);
      })
      .catch((error) => {
        console.log(error);
      });
    

    Once you have obtained the user token, you can use it to send a message to a Teams channel using the Microsoft Graph API. Here's an example of how you can send a message using the axios library:

    const accessToken = 'USER_ACCESS_TOKEN'; // Replace with the user access token
    
    const message = {
      body: {
        content: 'Hello from my app!',
      },
    };
    
    axios.post('https://graph.microsoft.com/v1.0/teams/{team-id}/channels/{channel-id}/messages', message, {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        'Content-Type': 'application/json',
      },
    })
      .then((response) => {
        console.log(response.data);
      })
      .catch((error) => {
        console.log(error);
      });