MS Graph put on uploadUrl created from createUploadSession results in a 404 - microsoft-graph-api

When doing a resumable upload to a file that was shared the url returned from createUploadSession can not be used.
Uploading directly with /content works but has a limit of 4MB
Scenario UserA shares a file with edit permissions to UserB
Using the ms graph javascript sdk
const { uploadUrl } = await this.client.api(`/drives/${driveId}/items/${id}/createUploadSession`).post({});
trying to use uploadUrl results in a 404 {"error":{"code":"itemNotFound","message":"The resource could not be found."}}
Interestingly the uploadUrl looks something like this
https://{tenant}-my.sharepoint.com/personal/{UserA}_{tenant}_com/_api/v2.0/drives/${driveId}/items/${id}/uploadSession?guid='5b85df9e-b524-4000-9883-8106a13e592f'...
Not sure if its related to UserA being embedded in the url or not.
If UserA accesses the same file and does a similar upload everything works fine on the file.
All of the following requests work fine for either User:
await this.client.api(`/drives/${driveId}/items/${id}/checkout`).post({});
await this.client.api(`/drives/${driveId}/items/${id}/content`).putStream(fs.createReadStream(filePath));
await this.client.api(`/drives/${driveId}/items/${id}/checkin`).post({});
uploadUrl returned from createUploadSession should be valid for any user that had access to create an upload session.

You cannot upload/replace files shared from another user's OneDrive. Creating an upload session creates a temporary file in the Drive for writing each chunk. Since User B doesn't have read/write access to User A's OneDrive, they cannot create that temporary file (thus the 404 - Not Found).

Related

Video as attachment in email

I use graph api to send emails to users. Is it possible to add video as attachment to email ? I converted .mp4 to binary string, set contentType to video/mp4, id to new Guid.
I created a request to send email, got correct response, but I don't recieve email (emails without videos works fine).
Documentation is not really helpful.
If the file size is between 3MB and 150MB, create an upload session, and iteratively use PUT to upload ranges of bytes of the file until you have uploaded the entire file. A header in the final successful PUT response includes a URL with the attachment ID.
There is a one limitation. An app with delegated permissions returns HTTP 403 Forbidden when attempting to attach large files to an Outlook message that is in a shared or delegated mailbox. With delegated permissions, createUploadSession succeeds only if the message is in the signed-in user's mailbox.
Resources:
Atttach large file

Uploading a large attachment using Microsoft Graph

I am trying to upload a large (> 4mb) attachment to an existing message in Office 365. I am following these instructions: https://learn.microsoft.com/en-us/graph/outlook-large-attachments?tabs=http
I have successfully created the upload session, and obtained a uploadUrl value that looks legitimate, it roughly matches the example in the documentation. Then I start my PUT to this url, for the first byte range that I've selected. I'm sure I'm setting the Content-Type, Content-Length and Contact-Range headers correctly. My problem is that I get http 401 (Unauthorized) in response. The error header returned is "The audience claim value is invalid for current resource..." and it regurgitates my url and it looks intact.
My theory is that I need to add another API permission to my application. I already have mail read.write, and that allows me to create a < 4mb attachment. If I need another permission, which one? Or do I have some other problem?
According to this documentation page on Resumable Uploads, you'll need any of Files.ReadWrite, Files.ReadWrite.All or Sites.ReadWrite.All permissions for a Delegated Work account.
If you're using an Application token, then you need Sites.ReadWrite.All permission.
What were the permissions you were missing that you had to add out of interest? Was the docs clear from our perspective? I can see the Resumable file upload permissions is specific to SharePoint and can use "Files.ReadWrite, Files.ReadWrite.All, Sites.ReadWrite.All".
For mail message you'd need Mail.ReadWrite as per this doc for large file upload https://learn.microsoft.com/en-us/graph/api/message-post-attachments?view=graph-rest-1.0&tabs=http
I've created a feedback item on the doc to get this updated. https://github.com/microsoftgraph/microsoft-graph-docs/issues/6817

Graph API - Unable to Use Valid Access Token to Upload file

I am unable to upload a file using a valid access token (the token allows me to list groups, drive items etc.). The error that appears is:
invalidRequest: One of the provided arguments is not acceptable.
Using the following PUT request:
https://graph.microsoft.com/v1.0/groups/{my group id}/drive/items/{my item(folder) id}:/test.txt:/content
using content type: text/plain
I tested this exact same request using the graph explorer https://developer.microsoft.com/en-us/graph/graph-explorer and my office 365 user account and the upload worked, so I though it might be an app permissions thing, however this did not work even after granting absolutely every permission to the app and regenerating the access tokem.
Please help as I would rather use an access token than my user account to perform the uploads.
Thankyou
Oliver
Just add a worked endpoint on my side:
PUT https://graph.microsoft.com/v1.0/groups/my-group-id/drive/root:/test.txt:/content
Request body: The contents of the file goes here.
The content type of request header does not need to be configured.
You need to check your folder path too.
I managed to resolve by creating a new app definition in Azure AD with the same permissions and it worked! Perhaps there was some corruption in my original Azure application - maybe the manifest was corrupt (due to a bug)?

How to download files from workfront

I have integrated Workfront APIs. I need to download files from my Workfront account using API.
https://api-cl01.attask-ondemand.com/attask/api/v5.0/document/search?fields=downloadURL
Using above URL, I am able to get file download URL, Which seems line as follows :
{ "downloadURL": "/document/download?ID=575a934000474c7938f129f536139952" }
But, I don't know how to download it.
When downloading files, use the API to establish a session key. You can do this by either logging in with a username and password, or by running the login function with no password, but including an API key instead. This will have the effect of logging you in as whatever username you entered (handy if you need to make changes on behalf of some user via API).
Once you have a session established, just use cURL or something similar to get the download link of the document. Link will be something like https://{yoursubdomain}.attask-ondemand.com/document/download?versionID=57c8d8da00b7cb921ff8c9f6b59705c3&ID=57c8d8da00b7cb911bc3aace5d332da9
I just checked and you only need ID in the URL. It appears it will return the latest version if you omit versionID.

Allowing Google Service Account YouTube Upload Access via API v3

I want to automatically upload videos to YouTube without user involvement so I've created a service account, jumped through the hoops, all was looking great, then the upload, chunk one, is attempted and my code bombs with this Google_Exception exception:
"Failed to start the resumable upload (HTTP 401: youtube.header, Unauthorized)"
I then dug and found on the YouTube API v3 error information:
https://developers.google.com/youtube/v3/docs/errors
"This error is commonly seen if you try to use the OAuth 2.0 Service Account flow. YouTube does not support Service Accounts, and if you attempt to authenticate using a Service Account, you will get this error."
Is this correct? I cannot use a service account to upload video to YouTube automatically?
(that was a waste of a couple of days hard work!)
Yes, it is correct.
The way forward is to do a manual authorisation and grab the resultant 'refresh token' and then use that for any automated uploads.
Ensure to add the refresh token to the PHP Google_Client object prior to any other action.
I am now automatically uploading to YouTube.
For anyone attempting to do this today, be aware that any uploads will be set as "Private (Locked)" if they are uploaded using the API unless/until the app is submitted for verification and approved.
https://github.com/porjo/youtubeuploader/issues/86
YouTube requires verification of the OAuth App/credentials used for upload, otherwise the video will be locked as Private.
It's possible to get an app approved, but if you're doing a personal project, it's less likely.
More: https://github.com/porjo/youtubeuploader/issues/86
Yes you can use Service Accounts for Youtube. One way is to add the service account to a CMS where the content owner is part of. When you retrieve an access_token for the Service Account, you can work with the content owners videos.
Looks like this, using Javascript and a npm package:
import { google } from 'googleapis';
const youtube = google.youtube('v3');
const fetchYoutubeData = async (keyfile, scopes) => {
const auth = new google.auth.GoogleAuth({
credentials: keyfile,
scopes,
});
const accessToken = await auth.getAccessToken();
const { data } = await youtube.videos.list({
part: ['snippet'],
id: 'YOUR_VIDEO_ID',
access_token: accessToken
});
return data;
}
Note that the keyfile is the JSON you downloaded from Gcloud when creating the service accounts keys. NOT the path pointing to the file! If you want to use path, use this instead:
const auth = new google.auth.GoogleAuth({
keyFile: 'PATH_TO_KEYFILE_IN_FILE_SYSTEM',
scopes: ['READ_STUFF', 'WRITE_STUFF'],
});
Further reading on server-server authentication using Oauth2

Resources