node.jsazuremicrosoft-graph-apimicrosoft-teamstranscription

Not able to get Transcript content through Graph API


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?


Solution

  • 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.