onedrive: add support for no admin mode

Add tenant_url configuration option for accessing OneDrive/SharePoint
without admin privileges. When tenant_url is set, rclone uses the
SharePoint v2.0 API endpoint instead of the standard Microsoft Graph
API.

Co-Authored-By: KyokoMiki <161209740+kyokomiki@users.noreply.github.com>
This commit is contained in:
TaterLi
2020-06-23 15:00:44 +08:00
committed by Nick Craig-Wood
parent 930a733594
commit 7bd05530eb
2 changed files with 76 additions and 2 deletions

View File

@@ -154,6 +154,21 @@ See: https://github.com/rclone/rclone/issues/1716
`,
Default: fs.SizeSuffix(-1),
Advanced: true,
}, {
Name: "tenant_url",
Help: `The tenant URL for non-admin OneDrive access.
Set this to your SharePoint tenant URL to use the SharePoint v2.0 API
endpoint instead of the standard Microsoft Graph API. This allows
accessing business OneDrive without admin consent.
The URL can be found in your browser's developer tools by searching
for "driveAccessToken" in the network requests. Look for the
".driveUrl" field which contains the tenant URL and drive ID.
Example: https://your-tenant.sharepoint.com/_api`,
Default: "",
Advanced: true,
}, {
Name: "chunk_size",
Help: `Chunk size to upload files with - must be multiple of 320k (327,680 bytes).
@@ -471,7 +486,15 @@ isn't always desirable to set the permissions from the metadata.
// Get the region and graphURL from the config
func getRegionURL(m configmap.Mapper) (region, graphURL string) {
region, _ = m.Get("region")
graphURL = graphAPIEndpoint[region] + "/v1.0"
// Check if tenant_url is provided for non-admin mode
tenantURL, _ := m.Get("tenant_url")
if tenantURL != "" {
graphURL = tenantURL + "/v2.0"
}
return region, graphURL
}
@@ -764,6 +787,7 @@ type Options struct {
Region string `config:"region"`
UploadCutoff fs.SizeSuffix `config:"upload_cutoff"`
ChunkSize fs.SizeSuffix `config:"chunk_size"`
TenantURL string `config:"tenant_url"`
DriveID string `config:"drive_id"`
DriveType string `config:"drive_type"`
RootFolderID string `config:"root_folder_id"`
@@ -1070,6 +1094,10 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
rootURL := graphAPIEndpoint[opt.Region] + "/v1.0" + "/drives/" + opt.DriveID
if opt.TenantURL != "" {
rootURL = opt.TenantURL + "/v2.0" + "/drives/" + opt.DriveID
}
oauthConfig, err := makeOauthConfig(ctx, opt)
if err != nil {
return nil, err
@@ -2738,7 +2766,13 @@ func (o *Object) ID() string {
// and returns itemID, driveID, rootURL.
// Such a normalized ID can come from (*Item).GetID()
func (f *Fs) parseNormalizedID(ID string) (string, string, string) {
rootURL := graphAPIEndpoint[f.opt.Region] + "/v1.0/drives"
var rootURL string
if f.opt.TenantURL != "" {
rootURL = f.opt.TenantURL + "/v2.0/drives"
} else {
rootURL = graphAPIEndpoint[f.opt.Region] + "/v1.0/drives"
}
if strings.Contains(ID, "#") {
s := strings.Split(ID, "#")
return s[1], s[0], rootURL
@@ -2933,7 +2967,12 @@ func (f *Fs) changeNotifyNextChange(ctx context.Context, token string) (delta ap
}
func (f *Fs) buildDriveDeltaOpts(token string) rest.Opts {
rootURL := graphAPIEndpoint[f.opt.Region] + "/v1.0/drives"
var rootURL string
if f.opt.TenantURL != "" {
rootURL = f.opt.TenantURL + "/v2.0/drives"
} else {
rootURL = graphAPIEndpoint[f.opt.Region] + "/v1.0/drives"
}
return rest.Opts{
Method: "GET",

View File

@@ -237,6 +237,41 @@ credentials.
anyone with the *Client ID* and *Client Secret* can access your
OneDrive files. Take care to safeguard these credentials.
### Non-admin access to Business OneDrive
If you do not have admin access to your organization's OneDrive for
Business, you can still connect by manually providing the SharePoint
tenant URL and drive ID. This works by overriding the base API URL
from the standard Microsoft Graph endpoint to the SharePoint v2.0
endpoint.
#### Steps to manually obtain credentials
1. Open your browser and navigate to `https://[your-tenant].sharepoint.com/`
2. Open Developer Tools (press F12) and go to the **Network** tab.
3. Search for `driveAccessToken` in the network requests.
4. Extract the following information from the response:
```json
".driveUrl": "{tenant_url}/v2.0/drives/{drive_id}",
".driveAccessToken": "access_token={access_token}"
```
#### Rclone configuration
Use the extracted values to configure your remote:
```ini
type = onedrive
token = {"access_token":"{access_token}","token_type":"Bearer","refresh_token":"","expiry":"2045-12-31T23:59:59Z"}
drive_id = {drive_id}
tenant_url = {tenant_url}
drive_type = business
```
Since the exact expiry time cannot be determined from web traffic,
set the expiry to a future date. Note that the token will eventually
expire and you will need to repeat the process to obtain a new one.
### Modification times and hashes
OneDrive allows modification times to be set on objects accurate to 1