Showing posts with label OneDrive. Show all posts
Showing posts with label OneDrive. Show all posts

November 28, 2024

How to use Files.SelectedOperations.Selected permission for SharePoint and OneDrive content

Problem

I needed to grant permission for an Entra Id application to access SharePoint Online and OneDrive folder. I didn't want to grant the broadest Sites.ReadWrite.All permission to all site collections, nor the second broadest permission Sites.Selected to specific site collection. Instead I needed to go very granular, so limit access to specific folder and use the Files.SelectedOperations.Selected permission.

Backgound: Granting permission to whole site collection

Before realizing Sites.Selected was too broad, I tested using it, and it worked great. In order to use the following commands, I used Graph Explorer to which I granted Sites.FullControl.All permission so that it could modify the permissions for SPO items.

1. Get the site collection

First I queried the site (collection) ID for my SharePoint site collection:

HTTP GET https://graph.microsoft.com/v1.0/sites/xyz.sharepoint.com:/sites/jussi


Then with the site ID (it looks something like this: "xyz.sharepoint.com,8e099463-6a83-48c3-9c0e-59c3ca071054,15a706b9-af56-49dd-97ad-51325cee3b66"), I queried current permissions for the site:

HTTP GET https://graph.microsoft.com/v1.0/sites/[SITE_ID]/permissions

No permissions were found, just as expected.

2. Add permissions

To add permissions, you use the permissions endpoint:

HTTP POST https://graph.microsoft.com/v1.0/sites/[SITE_ID]/permissions

with the following payload in the body section of Graph Explorer:

{
  "roles": [
    "write"
  ],
  "grantedToIdentities": [
    {
      "application": {
        "id": "10facd40-ec88-4c62-b5dc-8170a2ccaba1"
      }
    }
  ]
}

3. Removing permissions

You can remove the permissions too, but for that you need the permission ID. You got the permission ID from the result of the query you used when you added the permission earlier, but in case you missed it, you can list the permissions:

HTTP GET https://graph.microsoft.com/v1.0/sites/[SITE_ID]/permissions

Permission ID is the long non-GUID string like this:

"id": "aTowaS50fG1zLnNwLmV4dHwyMGZhY2Q0NC1lYzg4LTRjNjItYjVkYy04MTcwYTJjY2FiYTFAOTJlNTE2MTUtNDkwOS00OGUzLWJhMDYtMmE1ZmMyMzNiNGJi"

So in order to remove the permission:

HTTP DELETE https://graph.microsoft.com/v1.0/sites/[SITE_ID]/permissions/[PERMISSION_ID]


Granting permission to folder level

Alright, I removed the site collection level permissions and started to grant folder level permissions. 

1. Get the drive ID for the library

https://graph.microsoft.com/v1.0/sites/[SITE_ID]/drives

Drive ID is the non-GUID string like:

"id": "b!Y6QJjoNqw0icDlnDygcQVLkGpxVWr91Jl61RMlzuO2a6mn6WqINZRLEDcG_BOOKl"

2. Get the folder ID from the drive by querying all the children items of the folder

HTTP GET https://graph.microsoft.com/v1.0/sites/[SITE_ID]/drives/[DRIVE_ID]/root/children

So, what I now got was the id 01QHBNZNLH6DKOS3GO3FHKHKIC6AGODYML of the folder MyTemplates inside the library Shared Documents, that's the one.

            "createdDateTime": "2024-11-27T07:26:15Z",
            "eTag": "\"{E9D4F067-CE6C-4ED9-A3A9-02F00CE1E18B},1\"",
            "id": "01QHBNZNLH6DKOS3GO3FHKHKIC6AGODYML",
            "lastModifiedDateTime": "2024-11-27T07:26:15Z",
            "name": "MyTemplates",
            "webUrl": "https://xyz.sharepoint.com/sites/jussi/Shared%20Documents/MyTemplates",
            "cTag": "\"c:{E9D4F067-CE6C-4ED9-A3A9-02F00CE1E18B},0\"",
            "size": 20558,
            "createdBy": {
                "user": {
                    "email": "admin@xyz.onmicrosoft.com",
                    "id": "45a44407-f372-45f5-a69d-9f4dd4f704fa",
                    "displayName": "xyz Admin"
                }
            },


3. Add permissions

Following my earlier steps when granting permission to site level, I made call:

HTTP POST https://graph.microsoft.com/v1.0/sites/[SITE_ID]/drives/[DRIVE_ID]/items/[FOLDER_ID]/permissions

using same payload as earlier

{
  "roles": [
    "read"
  ],
  "grantedToIdentities": [
    {
      "application": {
        "id": "10facd40-ec88-4c62-b5dc-8170a2ccaba1"
      }
    }
  ]
}

╯︿╰   I get "Invalid request" error:

{
    "error": {
        "code": "invalidRequest",
        "message": "Invalid request",
        "innerError": {
            "date": "2024-11-28T08:12:45",
            "request-id": "62a82827-5c26-4883-934e-7eabeceead88",
            "client-request-id": "f6cd7714-2199-3a94-3a4b-5df804f1ec37"
        }
    }
}

What is this? Documentation is rather brief. There was a great article by Vasil that discusses permissions that indicated that this should (or at least was) possible, so I started testing further, and finally found a solution.

Solution

When granting application permissions to folder objects (probably same goes for files and lists), the payload you send is slightly different. You don't use grantedToIdentities array, but instead grantedTo object:

{
  "roles": [
    "read"
  ],
  "grantedTo": {
    "application": {
      "id": "10facd40-ec88-4c62-b5dc-8170a2ccaba1"
    }
  }
}

NOTE! This payload doesn't work when granting permission on a site level.


March 4, 2015

Sync any folder to OneDrive without moving it to local OneDrive folder

Problem

I’ve been using c:\work folder forever to store my work related semi-temporary files on my laptop hard drive. Although losing contents of that folder due to hard drive issue or similar wouldn’t cause much downtime in my work (as all important files are stored in the cloud), I still didn’t feel too relaxed with the possibility of losing even 5 minutes of work in case that folder somehow disappeared.

Few times I’ve decided to move my c:\work to OneDrive for Business folder in order to sync work related files automatically to business version of OneDrive hosted in Office 365. However, each time I’ve got frustrated by the fact that finding the OneDrive folder in File Explorer is so difficult.

Sure, using Favorites or Quick Access (as in Windows 10), I can get there pretty easily, but still, it will add at least one additional folder level and lots of clikety clicks with my tired little mouse to get where I want to go. Plus, just looking at the left pane in File Explorer that is so full with items (several instances of OneDrive, DLNA devices just below This PC, Control Panel?!, yet again same libraries, Desktop items at the root, Music, Videos, Pictures, etc.) makes me want to cry.

Solution

Use junction points to direct content from c:\work into your OneDrive folder, such as C:\Users\Jussi\OneDrive - Sulava Oy\Work. After creating junction point such as this, all content you add to c:\work will actually reside in the OneDrive folder, and are synced to OneDrive normally. And best of all, I can still use c:\work like I’ve always used.

Steps how to do this:
  1. Open Command Prompt
  2. Type in mklink /j c:\Work "C:\Users\Jussi\OneDrive - Sulava Oy\Work"


NOTE! If the command above doesn't work, you may not be able to create symbolic link to an existing folder, in that case use steps:
  1. Rename your existing c:\work (or whatever your folder is called) to e.g., c:\work_old
  2. Create Work folder into the OneDrive folder, e.g., C:\Users\Jussi\OneDrive - Sulava Oy\Work
  3. Open Command Prompt
  4. Type in mklink /j c:\Work "C:\Users\Jussi\OneDrive - Sulava Oy\Work"
  5. Move old content from c:\work_old to c:\work and confirm that Work folder under OneDrive folder starts syncing and eventually goes green
NOTE! As there is really just one instance of files on your hard drive, if you remove folder under OneDrive folder, it will also be removed from the junction point location.