Calling graph API to access oneDrive (office365) via another REST service - microsoft-graph-api

We want to upload files via a REST service to our oneDrive. In the REST service we are calling Microsoft Graph API but I am getting the 401 error, which I guess because of authorisation issue, I am wondering what is the best approach here?
The whole process works nicely if on our web-application.
I granted App permission in the Azure Active Directory portal and confirmed the consent at
https://login.microsoftonline.com/<tenant>/adminconsent?client_id=<client-id>
Then tried to get token
url = "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token"
"client_id": credential.clientid
"client_secret", credential.clientsecret
"scope", "https%3A%2F%2Fgraph.microsoft.com%2F.default"
"grant_type", "client_credentials"
I was still getting 401 error.
Then I fixed the permissions, now I get the access_token, now I first checked if a file exists in specific folder in oneDrive, if not then upload the file.
But now I get the following error:
{
"statuscode": 403,
"body": "{\r\n \"error\": {\r\n \"code\": \"AccessDenied\",\r\n \"message\": \"Either scp or roles claim need to be present in the token.\",\r\n \"innerError\": {\r\n \"date\": \"2020-08-13T10:12:33\",\r\n \"request-id\": \"338a2758-m7e0-4289-bnna-45pb14c79efa\"\r\n }\r\n }\r\n}"
}
I used the following API for checking if a file exists:
"https://graph.microsoft.com/v1.0/sites/<siteid>/drive/root:/<filePath>:/children"
I am not sure what roles/permission I need to set.

Related

Graph API: Upload contents of driveItem throws 501 not_implemented error for AzureChina

I want to update the content of the file on OneDrive item. For that I used this API.
PUT /drives/{drive-id}/items/{parent-id}:/{filename}:/content
This works perfectly fine for non China azure with Microsoft graph endpoint.
https://graph.microsoft.com
However, when I am trying this on AzureChina it is throwing me 501 error.
https://microsoftgraph.chinacloudapi.cn
Error:
This is the error response I am getting event though I am uploading data to file.
{
"error": {
"code": "notSupported",
"message": "Cannot upload content to an item representing a folder.",
"innerError": {
"date": "2021-05-10T09:01:12",
"request-id": "98a8b075-bb90-42fe-8620-7303e669f4ec",
"client-request-id": "98a8b075-bb90-42fe-8620-7303e669f4ec"
}
}
}
Is this not implemented in AzureChina?
Another thing is graph explorer does not work with AzureChina. Is there separate graph explorer available for AzureChina?
For Azure China, Work around for Graph API is to use SharePoint REST API v1.
To upload the file contents of drive items
URL: https://{site_url}/_api/web/GetFolderByServerRelativeUrl('/Folder Name')/Files/add(url='newFile.txt',overwrite=true)
Headers:
"Accept": "application/json; odata=verbose",
"Authorization": "Bearer " + accessToken
Method: "POST",
Body:
<File_contents>
Auth URL: https://login.partner.microsoftonline.cn/{{TenantID}}/oauth2/v2.0/authorize
Access Token URL: https://login.partner.microsoftonline.cn/{{TenantID}}/oauth2/v2.0/token
Scope : https://{tenantId}-my.sharepoint.cn/.default
Make sure you have added appropriate API Permissions for SharePoint & granted Admin consent in Azure AD portal within corresponding Application.
According to this page OneDrive and Excel features of Graph API are limited by Microsoft Cloud China but without more details what exactly is not supported.

unable to get given_name and family_name from azure v2 token endpoint

In the manifest of my application registration I've configured to retrieve the given_name and family_name claims (through the UI, the resulting manifest looks like this):
"idToken": [
{
"name": "family_name",
"source": "user",
"essential": false,
"additionalProperties": []
},
{
"name": "given_name",
"source": "user",
"essential": false,
"additionalProperties": []
}
],
During the redirect I add the profile scope along with the given_name and family_name scopes, which results in the following error.
Message contains error: 'invalid_client', error_description: 'AADSTS650053: The application 'REDACTED' asked for scope 'given_name' that doesn't exist on the resource '00000003-0000-0000-c000-000000000000'. Contact the app vendor.
Any ideas? As I understand that is what is required to configure these optional claims on the v2.0 endpoint as described here: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-optional-claims#v20-specific-optional-claims-set
You should only use the profile 'scope', which should result in you receiving the given_name and family_name 'claims'. That's standard behaviour for an Authorization Server, which will then either:
Return the name details directly in the id token
Or allow you to send an access token to the user info endpoint to get the name details
However, Azure v2 is very Microsoft specific, and user info lookup can be painful and involve sending a separate type of token to the Graph user info endpoint. Hopefully you won't have to deal with that and you will get the name details directly in the id token.
I had a scenario where my API (which only received an access token) needed to get user info, and I solved it via steps 14 - 18 of this write up, but it's a convoluted solution.
Once you configure optional claims for your application through the UI or application manifest. you need to provide profile Delegated permissions for the application.

How to get list of all subscribed channels of user using youtube api?

I am using Laravel-php, I have following code :
$client = new Google_Client();
$client->setClientId(env('GOOGLE_ID'));
$client->setClientSecret(env('GOOGLE_SECRET'));
//$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/youtube.force-ssl");
$client->addScope("https://www.googleapis.com/auth/youtube");
$client->addScope("https://www.googleapis.com/auth/youtube.readonly");
$client->addScope("https://www.googleapis.com/auth/youtubepartner");
$youtube = new \Google_Service_YouTube($client);
$searchResponse = $youtube->channels->listChannels('snippet', array('mine' => true));
//$subscriptions = Curl::to('https://www.googleapis.com/youtube/v3/subscriptions')->withData(['part' => 'snippet', 'mine' => 'true'])->get();
echo "<pre>";
print_r($searchResponse);
Above code gives me following error :
Google_Service_Exception in REST.php line 118:
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
}],
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
}
}
I have tried to use CURL call also but that also gives me same error, any suggestions will save my day
What am I missing in code ?
Your error means that you haven't set up a Google APIs console project. The resource you are accessing requires OAuth authorization. You need to obtain authorization credentials in the Google Developers Console to be able to use OAuth 2.0 authorization.
Open the Credentials page.
The API supports API keys and OAuth 2.0 credentials. In your case, use OAuth 2.0 for your project:
OAuth 2.0: Your application must send an OAuth 2.0 token with any request that accesses private user data. Your application sends a client ID and, possibly, a client secret to obtain a token. You can generate OAuth 2.0 credentials for web applications, service accounts, or installed applications.
See the Creating OAuth 2.0 credentials section for more information.
You may also check this related thread: list user subscriptions to all youtube channels after getting access token
First thing is that it needs to be an authenticated call.
So you need to get the person to "Authenticate" through the Oauth2 and collect the token.
Then with the token send this call
https://www.googleapis.com/youtube/v3/subscriptions?part=id,snippet,contentDetails&maxResults=50&channelId='.$channelId.'&access_token='.$access_token
Then you can access the JSON response and collect them.

Error when createUploadSession on OneDrive graph api for the special AppFolder

I am attempting to create an upload session in the special app folder for my OneDrive app using the Graph API. My app have the following permissions:
Files.ReadWrite
Files.ReadWrite.AppFolder
offline_access
The request looks like this
https://graph.microsoft.com/v1.0/users/xxxxxx96-2e02-4300-8ab0-a05d73xxxxxx/drive/special/approot:/documentname.docx:/createUploadSession
gives the following error:
{
"error": {
"code": "itemNotFound",
"message": "The resource could not be found.",
"innerError": {
"request-id": "7447aa01-6685-4af0-998a-64abc9b14825",
"date": "2017-04-06T10:07:46"
}
}
}
I can create an upload session on the normal root folder without any errors:
graph.microsoft.com/v1.0/users/xxxxxx96-2e02-4300-8ab0-a05d73xxxxxx/drive/root:/documentname.docx:/createUploadSession
result:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.uploadSession",
"expirationDateTime": "2017-04-06T10:32:48.5252565Z",
"nextExpectedRanges": [
"0-"
],
"uploadUrl": "......."
}
The createuploadsession method does not support special/approot. As mentioned in the documentation, these are the only paths to use:
POST /drive/root:/{path_to_item}:/createUploadSession
POST /drive/items/{parent_item_id}:/{filename}:/createUploadSession
Just wanted to clarify, since people are sometimes referring to this thread still: This syntax actually is supported. Due to the flexibility of OData syntax/support, the docs are not always 100% comprehensive about every request path that works.
I believe the actual issue is that Files.ReadWrite.AppFolder is not supported on ODB/SPO/business accounts yet (as of 2022) - it is only for personal/MSA accounts. However, there is work in progress to bring this support to SPO in the future.
The two scopes that are mentioned above are:
Files.ReadWrite - grants access to content on the caller's mysite only
Files.ReadWrite.AppFolder - has no effect on SPO/business
Files.ReadWrite.All should work in the short term, until Files.ReadWrite.AppFolder is implemented on SPO/ODB.

"Insufficient Permission" to retrieve user youtube subscriptipns after getting access token

I'm working on a scripts that checks if the user is already subscribed to my channel. The idea is to get all the channels the user had subscribed into then check if my channel id is one of them. First I get the access token correctly using POST and it works fine than send these as GET but the result is "failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden false". Doc page: https://developers.google.com/youtube/v3/docs/subscriptions/list#request_url
$data =file_get_contents('https://www.googleapis.com/youtube/v3/subscriptions?part=snippet
&maxResults=50&access_token='.$token.'&mine=true&key=My API Key');
var_export($data);
and pasting the full url
https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&access_token={Access_Token}
I get this
{
"error": {
"errors": [
{
"domain": "global",
"reason": "insufficientPermissions",
"message": "Insufficient Permission"
}
],
"code": 403,
"message": "Insufficient Permission"
}
}
Add a heaer:
Authorization: Bearer ya29.DwG_A_V6cybZ2KGqRwPMBF02w0sYw9msqSKoCBI53So0zzIHFRKlwEv68C4aI_NdadQ4wKHUrV2pBA
key is your client id
Google restricts access with API keys. If you go over the free limits, they charge you. You need to get a Google API key and add it to the URL like this: &key=YOUR_API_KEY
Create the API key from Google's console (you'll need to sign up and create a project): https://console.cloud.google.com/apis/credentials
Your new URL for the request would be:
https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&access_token={Access_Token}&key=YOUR_API_KEY
I was having this error, and I solved it when I found out I needed to add the Youtube scope to my OAuth sign-in request: "https://www.googleapis.com/auth/youtube"

Resources