0
votes

Using App-Only access token, the access token (jwt) looks like following

...
"aud": "https://{tenant}-my.sharepoint.com/",
...
"roles": [
    "User.Read.All",
    "TermStore.Read.All",
    "Sites.Read.All"
  ],
...

Then using curl

curl -H "Content-Type: application/x-www-form-urlencoded" -H "Authorization:Bearer {access_token}" 'https://{tenant}-my.sharepoint.com/_api/v2.0/drives/{upn}/root'

Returns

"Unsupported app only token."

If using user login access token, it works properly.

Also, I cannot use "https://graph.microsoft.com/v1.0/drives/{upn}/root/" as the API is subset of "https://{tenant}-my.sharepoint.com/_api/v2.0/".

How should App-Only access token read OneDrive?

Also, the "required permissions" in Azure's web-app for "application permission" and "delegate permission" are different for "Office 365 SharePoint Online", since there is no "File Read" for "application permission". Does this permission matters?

1
what is the value of appidacr?Brad
appidacr": "1",James

1 Answers

1
votes

The "OneDrive Business" API requires a token with an appidacr value of 2.

0 = Public client
1 = Client identified by its id and secret
2 = Client identified by its certificate

The value of 1 mentioned in the comments is an indication that the id/secret was used instead of using a certificate. To set up a certificate for your application follow these instructions and then you can get a token using code like the following:

var context = new AuthenticationContext(authEndpoint); 
X509Certificate2 cert = new X509Certificate2(clientCertificatePfxPath, clientCertificatePfxPassword, X509KeyStorageFlags.MachineKeySet);
ClientAssertionCertificate cac = new ClientAssertionCertificate(ClientId, cert);
var token = context.AcquireToken(audience, cac);

Update 1
The following includes a good example of how to get the token without using ADAL:
http://www.cloudidentity.com/blog/2015/02/06/requesting-an-aad-token-with-a-certificate-without-adal/

Quoting from this source:

POST https://login.windows.net/contoso.onmicrosoft.com/oauth2/token
HTTP/1.1 Content-Type: application/x-www-form-urlencoded
client-request-id: a2ef0cd8-60e5-4620-ac66-6f2a344e075b
return-client-request-id: true Host: login.windows.net
Content-Length: 986
Expect: 100-continue
Connection: Keep-Alive

resource=https%3A%2F%2Fcontoso.onmicrosoft.com%2FTodoListService&client_id=82692da5-a86f-45c9-9d53-2f88d51b478b&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer &client_assertion=eyJhbGciOi[…a lot of stuff…]-j5UBo1A&grant_type=client_credentials

The main things to notice here:
1) it’s a POST to the token endpoint
2) it is a client_credentials grant, as expected
3) you need to specify as client_assertion_type the magic value urn:ietf:params:oauth:client-assertion-type:jwt-bearer

The other thing of interest is in the client_assertion itself, which is the artifact in which the certificate actually comes into play: it’s an assertion you need to create and sign with the certificate you registered as credential for your application. ADAL does this for you, ut if you want to work directly at the protocol level you’ll have to do it yourself.

Follow the link for details on how to generate the JWT that's used for the assertion.

Update 2
James found an even better resource - check out this link for step-by-step instructions on how to manually do certificate auth with Azure AD.