Following the microsoft documentation, we are tried to calling the Graph API for getting transcript content.
Useful information:
MicrosoftAppType=MultiTenant
MicrosoftAppId=2dacff5b-9494-45b4-90f1-df6953d401aa
MicrosoftAppTenantId=91e213e9-498d-46b9-bc35-cd0aa9390b45
SubscriptionId=1106df7f-3a2b-4b98-80ff-7ab8738177d
MeetingID=MSpiYTc2OWFjOC0wOTc1LTRiOTctYTlmOS03NWFlYzZiNjEwMDQqMCoqMTk6bWVldGluZ19OV1ZsTmpoaU9Ua3RNV000WWkwME1HSmhMV0ZoT1RZdE0yUmlObVk0WmpnMk9HUTVAdGhyZWFkLnYy
TranscriptID=VjIjIzFiYTc2OWFjOC0wOTc1LTRiOTctYTlmOS03NWFlYzZiNjEwMDQ5MWUyMTNlOS00OThkLTQ2YjktYmMzNS1jZDBhYTkzOTBiNDUwNDAwMDAwMDgyMDBFMDAwNzRDNUI3MTAxQTgyRTAwODAwMDAwMDAwNDQ4MzI0ZjY2ZGQyZGEwMTAwMDAwMDAwMDAwMDAwMDAxMDAwMDAwMGEzMWUzOWY1MDhhZWM5NGVhZWM2ZDlkYzEwMjIzNWQ3IyMwZjM1MWUxNy1mMjRjLTRiZmUtYTM4NC0zZDdmN2ZmODliMzE=
Application/RSC permission (we have added required permission in manifest)
Firstly we have created a GraphClient with our application credentials as follows:
// @azure/identityconst
credential = new ClientSecretCredential(
process.env.MicrosoftAppTenantId,
process.env.MicrosoftAppId,
process.env.MicrosoftAppPassword
);
// @microsoft/microsoft-graph-client/authProviders/azureTokenCredentials
const authProvider = new TokenCredentialAuthenticationProvider(credential, {
['https://graph.microsoft.com/.default']
});
const graphClient = Client.initWithMiddleware({ authProvider: authProvider });
We successfully created the subscription as follows:
const transcriptSubscription = {
changeType: 'created',
notificationUrl: 'https://6ebd-2405-201-1021-7808-298c-d664-4dae-fff3.ngrok-free.app/notificationClient',
lifecycleNotificationUrl: 'https://6ebd-2405-201-1021-7808-298c-d664-4dae-fff3.ngrok-free.app/api/lifecycleNotifications',
resource: 'communications/onlineMeetings/getAllTranscripts?useResourceSpecificConsentBasedAuthorization=true',
includeResourceData: true,
encryptionCertificate: '{valid certificate}',
encryptionCertificateId:'{validId}',
expirationDateTime: '2024-07-11T11:00:00.0000000Z',
clientState: '{secretClientState}'
};
await graphClient.api('/subscriptions')
.post(transcriptSubscription).then((res) =>
{
console.log('Subscription:', res);
}).catch((err) => {
console.log('Error:', err);
});
This code results creates a valid subscription
res: {
'@odata.context': 'https://graph.microsoft.com/v1.0/$metadata#subscriptions/$entity',
id: '1106df7f-3a2b-4b98-80ff-7ab8738177d9',
resource: 'communications/onlineMeetings/getAllTranscripts?useResourceSpecificConsentBasedAuthorization=true',
applicationId: '2dacff5b-9494-45b4-90f1-df6953d401aa',
changeType: 'created',
clientState: '{secretClientState}',
notificationUrl: 'https://6ebd-2405-201-1021-7808-298c-d664-4dae-fff3.ngrok-free.app/notificationClient',
notificationQueryOptions: null,
lifecycleNotificationUrl: 'https://6ebd-2405-201-1021-7808-298c-d664-4dae-fff3.ngrok-free.app/api/lifecycleNotifications',
expirationDateTime: '2024-07-11T11:00:00Z',
creatorId: 'b3d2c52d-3d02-43bf-bd27-6408d62af8a1',
includeResourceData: true,
latestSupportedTlsVersion: 'v1_2', // Other data}
We are listening on the tenant, such that the events are getting received as expected:
subscriptionId: '1106df7f-3a2b-4b98-80ff-7ab8738177d9',
changeType: 'created',
clientState: '{secretClientState}',
subscriptionExpirationDateTime: '2024-07-11T11:00:00+00:00',
resource: "communications/onlineMeetings('MSpiYTc2OWFjOC0wOTc1LTRiOTctYTlmOS03NWFlYzZiNjEwMDQqMCoqMTk6bWVldGluZ19OV1ZsTmpoaU9Ua3RNV000WWkwME1HSmhMV0ZoT1RZdE0yUmlObVk0WmpnMk9HUTVAdGhyZWFkLnYy')/transcripts('VjIjIzFiYTc2OWFjOC0wOTc1LTRiOTctYTlmOS03NWFlYzZiNjEwMDQ5MWUyMTNlOS00OThkLTQ2YjktYmMzNS1jZDBhYTkzOTBiNDUwNDAwMDAwMDgyMDBFMDAwNzRDNUI3MTAxQTgyRTAwODAwMDAwMDAwNDQ4MzI0ZjY2ZGQyZGEwMTAwMDAwMDAwMDAwMDAwMDAxMDAwMDAwMGEzMWUzOWY1MDhhZWM5NGVhZWM2ZDlkYzEwMjIzNWQ3IyMwZjM1MWUxNy1mMjRjLTRiZmUtYTM4NC0zZDdmN2ZmODliMzE=')",// Other data
When we are trying to call content API:
await graphClient
.api(`users/${ process.env.MicrosoftAppId }/onlineMeetings/${ meetingId }/transcripts/${ transcriptId }`)
.get()
.then((dataFromResponse) => {
console.log('### dataFromResponse:', dataFromResponse);
})
.catch((error) => {
console.log('### error:', error);
});
We receive an error response as follows:
body: `{
"code":"Forbidden","message":"Application is not allowed to perform operations on the user '2dacff5b-9494-45b4-90f1-df6953d401aa', neither is allowed access through RSC permission evaluation.",
"innerError":{"date":"2024-07-10T02:45:09","request-id":"81fbbe48-d368-41d0-b5ab-f1a3e59f237a",
"client-request-id":"34e6cbfd-a622-0969-e57e-cc9c3c4e04c0"
}}`
My application is contributor to Subscription and we also tried with "beta" version but result is same.
How can I obtain the transcript through the Graph API?
First Thing:
Make sure to add the following permissions of Microsoft Graph API in your app registration.
OnlineMeetings.Read.All
OnlineMeetingTranscript.Read.All
Give Admin consent to the API permissions.
Second Thing:
You have to create an application access policy to allow application to access online meetings on behalf of a user.
Here are the commands to configure Application Access Policy:
--> Import-Module MicrosoftTeams
--> Connect-MicrosoftTeams
--> New-CsApplicationAccessPolicy -Identity "PolicyName" -AppIds "App-regID" -Description "Some description"
--> Grant-CsApplicationAccessPolicy -PolicyName "PolicyName" -Identity "UserID"
Grant this Policy using your Azure UserID.
After creating and granting this access policy you should be able to use Graph API to access transcripts content using auth token of your app registration.
For Reference : https://learn.microsoft.com/en-us/graph/cloud-communication-online-meeting-application-access-policy
Note : Do not grant policy as -Global. Because then anyone in the tenant can access transcriptions of any of the meetings.