13
votes

I've been trying to implement OneDrive Business API according to this OneDrive Release Notes. We've already implemented OneDrive end users API without any issue.

First obvious thing to do is to handle OAuth2 authentication to get right tokens, first to discover {tenant}-my.sharepoint.com specific Tenant OneDrive Business URI and after that get tokens for that tenant. Documenation for that purpose could be found here.

Following that tutorial we have been able to do the following:

  1. Register the App in Azure AD. Done
  2. Sign into OneDrive for Business
    • Log in and get an authorization code. Done
    • Redeem the authorization code for tokens. Done
    • Discover the OneDrive for Business resource URI. FAIL
    • Redeem refresh token for an access token to call OneDrive API. Done
    • Make a request to the OneDrive API. FAIL

It can be appreciated, we had issues on step 2, Discover the OneDrive for Business resource URI and Make a request to the OneDrive API.

Issue on Discover the OneDrive for Business resource URI

The problem with this part of the process is, although we are hitting to api.office.com/discovery/v2.0/me/services with the first Access Token obtained after redeem with resource api.office.com/discovery/, we are not getting in the list of services tenant specific sharepoint URI for OneDrive for Business. Any entry in the list we are getting come with capability = "MyFiles" AND serviceApiVersion = "v2.0" according documentation. In fact any entry in the list has the structure {tenant}-my.sharepoint.com in serviceEndpointUri. This is JSON response i am getting back. I removed some of the sensitive data:

{
"@odata.context" : "https://api.office.com/discovery/v2.0/me/$metadata#allServices",
"value" : [ {
  "capability" : "Directory",
  "providerName" : "Microsoft",
  "serviceAccountType" : 2,
  "serviceApiVersion" : "",
  "serviceEndpointUri" : "http://azure.microsoft.com/",
  "serviceName" : "Microsoft Azure",
  "serviceResourceId" : null
}, {
  "capability" : "MyFiles",
  "providerName" : "Microsoft",
  "serviceAccountType" : 2,
  "serviceApiVersion" : "",
  "serviceEndpointUri" : "http://www.microsoft.com/en-us/office365/online-software.aspx",
  "serviceName" : "Office 365 SharePoint",
  "serviceResourceId" : null
}, {
  "capability" : "RootSite",
  "providerName" : "Microsoft",
  "serviceAccountType" : 2,
  "serviceApiVersion" : "",
  "serviceEndpointUri" : "http://www.microsoft.com/en-us/office365/online-software.aspx",
  "serviceId" : "O365_SHAREPOINT",
  "serviceName" : "Office 365 SharePoint",
  "serviceResourceId" : null
}, {
  "capability" : "MyFiles",
  "providerName" : "Microsoft",
  "serviceAccountType" : 1,
  "serviceApiVersion" : "",
  "serviceEndpointUri" : "https://g.live.com/8seskydrive/HomePageUrl",
  "serviceName" : "OneDrive",
  "serviceResourceId" : null
} ]
}

The problem with this is if i logged in to my portal.office.com and check my sharepoint urls, it is well configured and i can see {tenant}-my.sharepoint.com URI.

Issue on Make a request to the OneDrive API

Apart i am not able to discovery correct tenant sharepoint URI, if i hardcode the URL to redeem next Access Token request with my tenant sharepoint URI, I am getting an access token but when i want to make a call for example to https://{tenant}-my.sharepoint.com/drive/root or any other endpoint i am getting 401 Unauthorize response in every call, even when the token has just been acquired. Here is a handshake example. I am hiding sensitive data:

curl -v 'https://{tenant}-my.sharepoint.com/drives' -H 'Authorization:   Bearer TOKEN_ACQUIRED'
Connected to {tenant}-my.sharepoint.com port 443
GET /drives HTTP/1.1
Host: {tenant}-my.sharepoint.com
Authorization: Bearer TOKEN_ACQUIRED

HTTP/1.1 401 Unauthorized

Could you advice me with this? Is there some configuration missing in my tenant? Is there some configuration missing in my Azure AD App?

BTW, permissions scope on my App i am getting in every redeem are AllSites.FullControl AllSites.Manage MyFiles.Write Sites.Search.All TermStore.ReadWrite.All User.Read.All. I think i have permissions properly set.

Best,

List item

1
Can you confirm that response from the discovery service was for /services and not /allServices?Brad
Never mind, apparently querying "/services" returns an @odata.context for "allServices"... that's a little strange.Brad
How did you acquire the access token to call the discovery service? The Discovery service itself is returning service info objects for both Active Directory accounts and Microsoft Accounts (serviceAccountType : 1 means MSA and 2 means Active Directory. What platform are you on? If you are iOS, .net or Andriod the OneDriveSDKs will handle all of this for youaclev
We are developing our own implementation written in Java. It is a backend ApplicationJuan
Hi aclev, we acquire access token according OneDrive for Business documentation API here dev.onedrive.com/auth/aad_oauth.htm. Apart from that the user which i am authenticating here is an User with a Enterprise License E3 and if i logged in with this user to portal Office 365 i am seeing OneDrive for Business activated. In fact i could access OneDrive for Business in this user going to https://{mytenant}-my.sharepoint.com/persona/{user}Juan

1 Answers

0
votes

Might be a bit late, but this blog article addresses how to use the OneDrive API and OneDrive for Business API exactly the same. Here is a quick Java code snippet:

CloudRail.setAppKey("[CloudRail License Key]");

// CloudStorage cs = new OneDrive(redirectReceiver, "[clientIdentifier]", "[clientSecret]", "[redirectUri]", "[state]");
CloudStorage cs = new OneDriveBusiness(redirectReceiver, "[clientID]", "[clientSecret]", "[redirectUri]", "[state]");

new Thread() {
    @Override
    public void run() {
        cs.createFolder("/TestFolder");
        InputStream stream = null;
        try {
            stream = getClass().getResourceAsStream("Data.csv");
            long size = new File(getClass().getResource("Data.csv").toURI()).length();
            cs.upload("/TestFolder/Data.csv", stream, size, false);
        } catch (Exception e) {
            // TODO: handle error
        } finally {
            // TODO: close stream
        }
    }
}.start();