msgraph-sdk-javascript
msgraph-sdk-javascript copied to clipboard
Subscription creation to `/communications/onlineMeetings...` fails.
Bug Report
Prerequisites
- [x] Can you reproduce the problem?
- [x] Are you running the latest version?
- [x] Are you reporting to the correct repository?
- [x] Did you perform a cursory search?
For more information, see the CONTRIBUTING
guide.
Description
We are developing a multi-tenant application to monitor online meetings and call records for MS Teams. To this end, we have an Office 365 developer account (E5 license) to play the role of a client, and our own Azure account with a configured client application.
The client application requests the following application scopes (not delegated scopes):
onlineMeetings.Read.All
callRecords.Read.All
The client app is additionally set as a Multi-Tenant app, with implicit and hybrid access token flows checked.
When we attempt to create a subscription to the resource /communicatons/callRecords
, the subscription works correctly for our client-app, and we receive callbacks on our webhook.
However, when we attempt to create a subscription to the the resource /communications/onlineMeetings/?$filter=JoinWebUrl eq '{JoinWebUrl}'
, we get an error message stating: The meeting token does not match the tenant token
.
Console Errors: The following error is shown in the terminal:
GraphError: Operation: Create; Exception: [Status Code: Forbidden;
Reason: The meeting tenant does not match the token tenant.]
Steps to Reproduce
- Sign up for a Microsoft 365 Developer account, login to Azure Portal and note the
tenant Id
down. Let's call thisTenant-A-ID
- Sign up for an Azure account for the client app (TENANT-B)
a. Add an app registration for the client app
b. Add
application
scopes forOnlineMeetings.Read.All
andCallRecords.Read.all
c. Generate a secret key and note it down d. Ensure Implicit and Hybrid OAuth flows are enabled e. Add a redirect URL for OAuth under SPA - Open the following URL as an admin user in a browser (or GET via Postman):
https://login.microsoftonline.com/{TENANT-A-ID}/adminconsent
?client_id=YOUR_APP'S_CLIENT_ID
&state=some-state-string
&redirect_uri=http://your-registered-redirect-url-from-step-2e
- Ensure a TENANT-A admin account logs in and consents to the requested permissions
- Login to the Azure Portal for
TENANT-A
with your admin account - Navigate to Azure AD, click on Enterprise Applications, and your
TENANT-B
client app should be listed - Click on Permissions and ensure Admin consent has been granted for the requested scopes
MSAL initialization and MS Graph calls:
- Initialize the msal-node client as follows (also reference supporting documentation):
const authApp = new ConfidentialClientApplication({
auth: {
clientId: 'app-client-id',
clientSecret: 'app-client-secret',
authority: `https://login.microsoftonline.com/${TENANT-A-ID}`,
},
});
- Request an access token as follows:
const authContext = await authApp.acquireTokenByClientCredential({
authority: `https://login.microsoftonline.com/${TENANT-A-ID}`,
scopes: ['https://graph.microsoft.com/.default'],
});
const accessToken = authContext.accessToken;
- Initial the MS Graph client as follows:
const client = MSClient.init({
debugLogging: true,
authProvider: (done) => {
done(null, accessToken);
},
});
- Attempt to create a subscription to
/communication/callrecords
as follows:
const callRecordsSubscription = await client
.api('/subscriptions')
.version('beta')
.create({
changeType: 'created,updated',
notificationUrl: `https://your-ngrok-url`,
resource: '/communications/callrecords',
clientState: 'some-state',
expirationDateTime: 'date-time',
});
The subscription should get created successfully, and your registered webhook will fire notifications correctly (this is the case with my testing).
- Attempt to create a subscription to
/communications/onlineMeetings/?$filter=JoinWebUrl eq '{JoinWebUrl}'
as follows:
const subscription = await client
.api('/subscriptions')
.version('beta')
.create({
resource: `/communications/onlineMeetings/?$filter=JoinWebUrl eq '{JoinWebUrl}'`,
changeType: 'created,updated',
notificationUrl: `https://your-ngrok-url`,
clientState: 'some-state',
expirationDateTime: 'date-time',
includeResourceData: true,
encryptionCertificate: 'serialized-cert',
encryptionCertificateId: 'cert-id',
});
The request will fail with the console error noted above.
Expected behavior: The subscription should get created.
Actual behavior:
Client throws an error with the message: The meeting tenant does not match the token tenant
.
Additional Context
As a test, I created a client application in TENANT-A (no multi-tenancy involved), and received the exact same error message, whereas the subscription to /communications/callRecords
again did not have any issues.
Usage Information
- Request ID: 226feda8-d956-47f7-87ed-43ca16eafb32
- SDK Version: 3.0.2
- [x] Node
- Node Version - 14.8.1
@mhashmi Can you please provide the request id of the failing request and the subscription id?
@nikithauc Please find below additional details from the error console:
statusCode: 403,
code: 'ExtensionError',
requestId: '226feda8-d956-47f7-87ed-43ca16eafb32',
date: 2022-08-11T09:50:47.000Z,
body: {
code: "ExtensionError",
message: "Operation: Create; Exception: [Status Code: Forbidden; Reason: The meeting tenant does not match the token tenant.]",
innerError: {
date: "2022-08-11T09:50:47",
request-id: "226feda8-d956-47f7-87ed-43ca16eafb32",
client-request-id: "9d772272-b2d6-6d68-8c13-7d2b1ea7ef58"
}
}
Please note that I don't have a subscription id here as subscription creation fails. If there is anything else I can provide please do let me know, and many thanks for looking into this, greatly appreciated!
Can you try the following sugggestion by the service team ?
Can the customer add application permissions 'OnlineMeetings.ReadWrite.All' and try again?
The client application requests the following application scopes (not delegated scopes):
onlineMeetings.Read.All
callRecords.Read.All
Can the customer add application permissions 'OnlineMeetings.ReadWrite.All' and try again?
Just added the additional scope: OnlineMeetings.ReadWrite.All
. The screenshot below shows granted application permissions in Tenant-A (as described in the issue overview):

Unfortunately, the console error still remains the same. Please find request details below for reference:
"statusCode": "403",
"code": "'ExtensionError",
"requestId": "'45dc7cf7-59bd-4bae-ba34-79d1f69a2ed5",
"date": "2022-08-13T14:11:52.000Z",
"body": {
"code": "ExtensionError",
"message": "Operation: Create; Exception: [Status Code: Forbidden; Reason: The meeting tenant does not match the token tenant.]",
"innerError": {
"date": "2022-08-13T14:11:52",
"request-id": "45dc7cf7-59bd-4bae-ba34-79d1f69a2ed5",
"client-request-id": "c610e787-0d35-3802-d292-64aeba3dbfb2"
}
}
If I can help further please do let me know. Thanks.
Root Cause:
Response from the service team: After the POST Request to https://plat.teams.microsoft.com/communications/subscriptions, the code will check for consistency between the tenant ID extracted from the joinWebUrl and the tenant ID from the token principal. In the customer's request, a placeholder value was used for joinWebUrl and as the result there is no tenant ID from the joinWebUrl. That's why the error message says " The meeting tenant does not match the token tenant."
Action:
Please replace the placeholder value for joinWebUrl with an actual meeting url. The join URL for the meeting is included in the joinWebUrl property of the onlineMeeting resource, or in the Teams client for a meeting.
Thanks for the clarification -- my understanding of the purpose of the joinWebUrl was wrong.
Please consider the issue resolved given I am sure the subscription will work if I specify a joinWebUrl.
If possible, can you outline how I would get callbacks to a webhook for any meeting a particular user joins? Is this even possible? I see delegated scopes available for onlineMeetings.Read
, but I am unsure what the correct subscription resource URL should be.