Trying to use Microsoft's Graph API to iterate through Sharepoint sites, in order to find and remove a user's access to sites when they go out of the country.
Graph / Sharepoint API documentation: https://learn.microsoft.com/en-us/graph/api/resources/site?view=graph-rest-1.0
I get a list of all sites using the Get Sites endpoint:
https://graph.microsoft.com/v1.0/sites
I then filter out personal / OneDrive sites, and try to use the List Site Permissions endpoint to try to get admins/members: https://learn.microsoft.com/en-us/graph/api/site-list-permissions?view=graph-rest-beta&tabs=http
Unfortunately, I get an empty value array in response for all sites:
{'#odata.context': "https://graph.microsoft.com/v1.0/$metadata#sites('<domain>.sharepoint.com%asdfasdgsdf-ca8f-4ec1-bb3e-sdfsdfsdgsdf%2Cbed949c3-3f83-47c2-a263-sdfsdfsdgasdf')/permissions", 'value': []}
I know that the query is fine, because if I change it to instead hit the Site Lists endpoint, I get a response which includes various values:
{'#odata.context': "https://graph.microsoft.com/v1.0/$metadata#sites('<domain>.sharepoint.com%sdfsdfsdgsd-7dce-4564-9de8-eb2dfc02eb86%sdfsdgsdfsdf-ab8c-464f-a77d-sdfsdfsdgsdg')/lists", 'value': [{'#odata.etag': '"sfwsdgsdg-aff1-4295-8443-sdfsdgasdf,7"', 'createdDateTime': '2020-08-26T16:17:41Z', 'description': 'This library contains items that have been modified or deleted but must remain available due to eDiscovery holds. Items cannot be modified...
...
So, the Site ID I am passing to the permissions request must be correct. Is this the wrong endpoint then? Or, is this functionality missing from the Graph API, and my only solution is via the SP Powershell module?
I have tried with both the v1.0 and beta vesions of the API.
Thanks!
According this it looks like a bug in Graph API.
Related
I am facing a weird issue with microsoft's graph api.
I am trying to retrieve files stored on Sharepoint. I don't know what the issue is and I have tried a lot of different things:
Call to get all drives for the site works and returns a list of all available drives:
GET https://graph.microsoft.com/v1.0/sites/site.sharepoint.com,<id>,<id>:/teams/myTeam:/drives
Via the previous endpoint I can extract the id for that drive with which I would then like to retrieve drive details (and in consequence all children of that drive):
GET https://graph.microsoft.com/v1.0/sites/site.sharepoint.com,<id>,<id>:/teams/myTeam:/drives/<driveId>
GET https://graph.microsoft.com/v1.0/sites/site.sharepoint.com,<id>,<id>:/teams/myTeam:/drives/<driveId>/root
GET https://graph.microsoft.com/v1.0/sites/site.sharepoint.com,<id>,<id>:/teams/myTeam:/drives/<driveId>/root/children
But all 3 above endpoints throw a 400 Bad Request Error with message: Url specified is invalid.
Additional information:
My access token has the following scopes: Sites.FullControl.All User.Read profile openid email
I am able to retrieve an individual drive item through the list endpoints (but the folder structure is quite complex and I need to list several layers of folders/files - this is why I believe the syntax with drive would be a lot more convenient):
GET https://graph.microsoft.com/v1.0/sites/site.sharepoint.com,<id>,<id>:/teams/myTeam:/lists/<list-id>/items/<item-id>/driveItem
via the field parentReference I am also able to fetch the driveId and even the relative path (/drives/<drive-id>/root:) but I also have no idea how I would get the content from that.
Help is greatly appreciated as I have been stuck for a long time now - thank you!
Try with the below HTTP call.
https://graph.microsoft.com/v1.0/sites/site.sharepoint.com,<id>,<id>/drives/driveid/root/children
It worked for me.
I've been trying this scenario on a couple of different tenants so far:
use an existing team or create a new one through the UI
add a tab (let's say OneNote) to a channel
query the list tabs endpoint (through graph explorer)
I always get a 404 response. If I replace in my query tabs by messages I get the messages.
In terms of permissions I have the default graph explorer one + Group.Read.All.
Here is the latest request Id I got 2a180611-b637-4aa4-be27-9e42cbb27ab9 on tenant dev2tolead12. (GET https://graph.microsoft.com/beta/teams/7471ee8d-0ed3-4f22-80ee-3b513e42e6ac/channels/19:9a0544b274654ef8ac97761ebd91b471#thread.skype/tabs)
My question: what am I missing for this request to work?
Sorry, we thought we had deployed the tabs API to all tenants, but had actually deployed it to only some of them – this has been fixed.
The endpoint started working in my tenants today. My guess is Microsoft fixed something recently
I am trying to use the graph API (v1.0) to search for files and folders within our team's sharepoint/onedrive folders but when using an app-only token I consistently get no results for any /search(...) request I try.
I have an registered and application with https://apps.dev.microsoft.com and have requested and granted consent for the permissions stated in the API Documentation;
User.ReadWrite.All, Group.Read.All, Sites.Read.All, Sites.ReadWrite.All, Group.ReadWrite.All, Sites.Manage.All, Files.ReadWrite.All, User.Read.All, Files.Read.All, Sites.FullControl.All
When I request a token from https://login.microsoftonline.com/ I can see the granted permissions in the payload.
Using this token I can successfully access the drive and retrieve information about its contents using drive/root
I have a small test folder structure that contains a few simple text files.
I can confirm that this token gives me access to my files and folders by calling drives/{driveid}/items/{folderid}/children recursively to build a complete tree structure.
However, when I try to search the drive for filenames or text phrases that I know exist I get no results at all, no matter what combination of paths or search terms I use. I've never seen a search result from an app-only token.
Examples that I've tried;
sites/root/drive/search(q='test')
drive/root/search(q='test')
drives/{driveid}/search(q='test')
drives/{driveid}/root/search(q='test')
The phrase "test" exists both as a filename and also within the text content of some of the files.
I get an HTTP:200 response but the value collection https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem) is always empty.
I'm building http requests in my application (Coldfusion), not using a SDK.
I wondered if I was having encoding problems so have tried various approaches of url-encoding the search part of the url (q='test') etc.
I've also tried running the same requests with Postman and cUrl but the results are the same. Empty.
The only thing that works is when I try the same searches using the Graph Explorer I get the results I would expect to see.
I know that Explorer uses a different type of token so I'm wondering if this is and issues related to my token being app-only.
Does anyone know if .../search() actually work for app-only tokens?
Does anyone know if .../search() actually work for app-only tokens?
The answer is yes, ../search() actually work for app-only tokens
Based on my test, the following search API works well for app-only token
https://graph.microsoft.com/v1.0/drive/root/microsoft.graph.search(q='test')
https://graph.microsoft.com/v1.0/drives/{driveid}/root/microsoft.graph.search(q='test')
https://graph.microsoft.com/v1.0/drives/{driveid}/microsoft.graph.search(q='test')
https://graph.microsoft.com/v1.0/sites/root/drive/search(q='test')
For permission config, just put "Files.Read.All, Files.ReadWrite.All, Sites.Read.All, Sites.ReadWrite.All" into the GraphScopes in the project config file as docs states.
Above answer is based on your description:****register app in http://apps.dev.microsoft.com/. You can ignore the SDK although it is the best choice. If you don't have a project config with GraphScopes, you need to pass the scope to auth request, it is difficult for operation.
If your app-only mean register app in SharePoint online, then the Graph Search API won't work. SharePoint doesn't share AccessToken with Graph directly.
Here is the same question again. The answer has been commented by a microsoft developer. He confirmed, it was a bug.
I'm trying to fetch all the sites under our tenant and some are missings. We recently created a new site (not subsite) and we cannot found it when searching with Microsoft Graph.
Here's the request url that we are using:
https://graph.microsoft.com/v1.0/sites/?search=*
I also tried to use this url from beta docs but it's not working either:
https://graph.microsoft.com/beta/sites?filter=root%20ne%20null&select=siteCollection,webUrl
Though, I can found it with the get by path url:
https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}
Does the site need to have a specific setting to appear in the result when searching?
I want to be able to list all the sharepoint sites that exists.
Based on my latest test, the following url not handle same data so different results(Attetion to my code comment):
//just return the team site(subsite of teams/sites)
https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}
//Will return the tenant site collection
https://graph.microsoft.com/beta/sites/root?select=siteCollection,webUrl&filter=root%20ne%20null
To get the modern team sites for the groups, we need to use groups end point from Microsoft Graph. No API to list all the modern team sites directly, we can loop through the groups and then get the site URL with this API: https://graph.microsoft.com/v1.0/groups/<group-id>/drive/root/webUrl.
Please check if the site in your case with issue is a modern team sites?
Some reference from 3rd blog:
https://www.eliostruyf.com/get-the-site-url-of-an-office-365-group-via-the-microsoft-graph/
I have access to a YouTube CMS account (for an MCN). On YouTube I can do lots and lots of things with it and this also includes downloading CSV reports which contain detailed information about earnings.
However I want to do some automatic processing of that data and thus access the data using an API instead of a manual CSV download. It looks like the YouTube Analytics Content Owner Reports should contain these data as well, thus I tried to get some data from this API (for now only using the API Explorer) but the only thing I was able to get was a "Forbidden" response.
The API Explorer tells me that for a CMS account I need to specify contentOwner==OWNER_NAME but there is nowhere an explanation what that OWNER_NAME would be. I tried to just insert the displayed name of my CMS account, replacing spaces with underscores, but no success. How do I find out what my owner name is?
Additionally, when I authenticate using OAuth I receive as usual the list of accounts where I can choose which one to use (e.g. all the YouTube channels I am a manager of), but the CMS account is not listed. However if I go to YouTube I can click on the top right corner and then switch to the CMS. No idea if that is important...
Then again, maybe I am totally on the wrong track, because I want to get the reports for all channels connected to my MCN but that does not mean that I own the content. So maybe I am no content owner? In this case: Which is the correct way to request the reports from the API?
First of all, the CMS account is not a separate account you can log in via Oath. It is more like a privilege and it is connected to one of your google/youtube accounts. This is in contrast to youtube's regular channel-management, where each channel has it's own login credentials.
I attached a screenshot of my youtube account-selector-view, where the CMS belongs to the account name#email.com, which is also the account you have to use for oauth authorization to access your CMS reports.
Furthermore you can see the name of the CMS, in this case it "CMSName". So, generally this is the name you would use for contentOwner==CMSName. However, your CMS Name seems to include whitespaces. Unfortunately, i cannot reconstruct this case because of missing admin-rights, but i would suggest you the _ for whitespaces too, because " " and "%20" do not map the regular expression for valid params.
But you said, that you had no success by trying it. But there are too error scenarios:
403 Forbidden: The name of the CMS could either be wrong or the selected OAth account does not have the required privileges. Do you have all required Scopes and selected the correct account?
400 Bad Request: This happens when the request is invalid per se. So if you choose contentOwner==CMSName as ids param, a filter parameter is always required, e.g. channel==[ChannelIdForWhichIHaveCMSRights]. So, a API request, that should generally work, would look like this: https://www.googleapis.com/youtube/analytics/v1/reports?ids=contentOwner%3D%3D[CONTENTOWNER_ID]&start-date=2015-01-01&end-date=2015-01-15&metrics=views&filters=channel%3D%3D[CHANNEL_ID_WITH_CMS_RIGHTS]&access_token=[OATH_TOKEN_FOR_RIGHT_ACCOUNT]
If both cases won't work for you and you're still getting 403 errors, let us do some debugging and try to fetch the content Owner Id. I will now introduce the YouTube Content ID API https://developers.google.com/youtube/partner/.
A few words in advance: You have to activate the API in your developer console, like any other API you want to use for your app. BUT:
Note: The YouTube Content ID API is intended for use by YouTube content partners and is not accessible to all developers or to all YouTube users. If you do not see the YouTube Content ID API as one of the services listed in the Google Developers Console, see www.youtube.com/partner to learn more about the YouTube Partner Program.
You don't see it in the list auf available APIs, unless your account is connected to a CMS and some time has past... It takes 7-14 days unless the Content ID API is available for your account. This is a information i got from the support, but they told me, that it is an automated step.
So, now lets assume, that you already have access to the Content ID API.
You can fetch a list of contentOwnerShips that belong to an account. You can use the API explorer https://developers.google.com/youtube/partner/docs/v1/contentOwners/list#try-it just use as param fetchMine=true and authorize with the https://www.googleapis.com/auth/youtubepartner-content-owner-readonly scope. The response looks like this:
{
"kind": "youtubePartner#contentOwnerList",
"items": [
{
"kind": "youtubePartner#contentOwner",
"id": "[CMS_ID]",
"displayName": "[DisplayName]",
"primaryNotificationEmails": [
"mail#random.xx"
],
"conflictNotificationEmail": "mail#random.xx",
"disputeNotificationEmails": [
"mail#random.xx"
],
"fingerprintReportNotificationEmails": [
"mail#random.xx"
]
}
]
}
This is where you get your CMS_ID from, you can also use it for any API Request as onBehalfOfContentOwner.
To get a list of all channels that belong to the ownership, simply make this request
"https://www.googleapis.com/youtube/v3/channels?part=contentDetails&managedByMe=true&onBehalfOfContentOwner=[CONTENTOWNER]&access_token=[ACCESS_TOKEN]"
But this request requires the granted "https://www.googleapis.com/auth/youtubepartner" scope.
Hoe this could help you, feel free to ask further questions.