MS Teams bot - how to download file that was uploaded in teams

Copper Contributor

I'm using teams bot api.
We want to support images - a user will upload images in teams bot conversation, and the image will be sent to our server and converted to base64.

The request that my server gets:

 

 

{"text":"send file","textFormat":"plain","attachments":[{"contentType":"application/vnd.microsoft.teams.file.download.info","content":{"downloadUrl":"https://*-my.sharepoint.com/personal/*/_layouts/15/download.aspx?UniqueId=2f***b&Translate=false&tempauth=*&ApiVersion=2.0","uniqueId":"*","fileType":"pdf"},"contentUrl":"https://*-my.sharepoint.com/personal/*/Documents/Microsoft Teams Chat Files/myFile.pdf","name":"myFile.pdf"},{"contentType":"text/html","content":"<p>send file</p>"}],"type":"message","timestamp":"2022-07-25T11:13:17.7731472Z"........}

 

 

This is my code:

 

 

if (message.attachments) {
       const file = message.attachments.find(a => a.contentType === "application/vnd.microsoft.teams.file.download.info");
       if (file) {
             require('request').get({uri: file.content.downloadUrl, encoding: null}, function (err, res, body) {
                if (!err && res.statusCode === 200) {
                    const base64Data = "data:" + res.headers["content-type"] + ";base64," + new Buffer(body).toString('base64'); 
                } else console.log(err ? err : "statusCode: " + res.statusCode);
            });          
       }
}

 

 

I'm getting "statusCode: 403".

From the docs it seems like the URL should be public (pre-auth) for a few minutes:

content.downloadUrl is a pre-authenticated link to download the file.
To fetch the contents of the file, send a GET request to the URL in content.downloadUrl. The URL is only valid for a few minutes, so you must fetch the file immediately.

 

Thanks in advance

14 Replies
@chisr- We are looking into this we will get back to you soon.

@chisr -Your bot can directly send and receive files with users in the personal context, also known as personal chats, using Teams APIs. In order to send and receive files in your bot, you have to set the supportsFiles property in the manifest to true. This property is described in the bots section of the Manifest reference. The definition will look like this: "supportsFiles": true. If your bot doesn't enable supportsFiles, this features won't work.

Reference Document- Send and receive files from a bot - Teams | Microsoft Docs

Sample Link-BotBuilder-Samples/samples/javascript_nodejs/56.teams-file-upload at 397672668ddc14a1adab7fc81068c61...

Thanks!

This is not a published application, the users talk to the bot through the link from the registered bot Portal. So I will have to add my app as described here ? -  https://docs.microsoft.com/en-us/microsoftteams/platform/sbs-file-handling-in-bot?tabs=visualstudio&...

Thanks.
It talks about sending an attachment (this works fine for me with HERO card).. My problem is - receiving an attachment (the url is private instead of pre-authenticated for a few minutes).
I added the bot as Teams App with manifest ("supportsFiles": true), but still I get "403" error when trying to access the downloadUrl. Can you please help?
Can you please check if you have configured proper permissions to access the downloadURL because it needs authentication?

@chisr - We tried with the below sample, It's working fine from our end. Could you please try it once?
Reference Sample-BotBuilder-Samples/samples/csharp_dotnetcore/56.teams-file-upload at main · microsoft/BotBuilder-Sam...

What permissions do I need? (From Docs it looks like the link should be pre-auth), I use REST API and not the BotBuilder. I also tried with Bearer authorization header - with the token generated by bot credentials:
const params = {
"grant_type": "client_credentials",
"client_id": botId,
"client_secret": secret,
"scope": 'what should be here?'
}

@chisr -Prerequisites for uploading file-
Upload file in Teams using bot - Teams | Microsoft Docs

For Bearer Token Call:

 

 

POST https://login.microsoftonline.com/your_tenant.onmicrosoft.com/oauth2/v2.0/token

 

 

Body: (in form-data or x-www-form-urlencoded format):

  1. client_id: Application ID copied earlier
  2. scope: profile-search (May vary based on the scopes exposed in the resource API)
  3. client_assertion_type: urn:ietf:params:oauth:client-assertion-type:jwt-bearer (Must be same)
  4. client_assertion: Read about certificate credentials to learn how to register your certificate and Signed assertions for encoded assertion to be used here.
  5. grant_type: client_credentials (to acquire token in application context where no human interaction is needed)

Notice that there are no user credentials specified in the request. The token will be acquired in the Application/servicePrincipal context.
OAuth 2.0 client credentials flow on the Microsoft identity platform - Microsoft Entra | Microsoft D...

.

So it is not as written in the Docs. The downloadUrl should be public - pre-authenticated and valid for a few minutes. Else, what is the tempAuth parameter (and it's value..) that exists in the downloadUrl? (maybe only the contentUrl requires an access token)

 

In another doc there is an explaination about the 'pre-authenticated downloadUrl' :

"Pre-authenticated download URLs are only valid for a short period of time (a few minutes) and do not require an Authorization header to download"

 

Maybe I missed some steps to make it public for a few minutes ? (we created the bot here: https://dev.botframework.com/bots/new)

The bot has to access the files that users upload in the conversation (users can be from many tenants, not from the tenant where the bot was created), without the need to ask and save the user's credentials to sharepoint (maybe bot credentials can also be good, but not user's ones)...

 

Thanks in advance!

I found the problem!!!

The DownloadUrl really has to be public, the problem is that our nodejs code use sanitazion on each input for security -

expressSanitized.middleware({encoder: 'XSSEncode'})

The sanitazion added "&amd;" to the downloadUrl - 

https://***.sharepoint.com/personal/****/_layouts/15/download.aspx?UniqueId=5c****c344&Translate=false&tempauth=eyJ0e........AwMDAwMDAv

 

That's why I got 403....

I added unescape function to remove the & and now it works.

Thanks!

@chisr-Glad to hear that your issue is resolved.