26

I would like to access a user's one drive to upload a document or retrieve a document using Graph API. I've seen multiple examples over the net which requires using the standard login page for the user to login. You need to get the authorization code from the login page and then use it to get a token, which finally can be used to access a resource like drive.

Am looking for a way to do this without going through the login page. I can have my own login page where I can request user to login.

In short, I want to access drive resource of Graph API using a REST client like Postman (right from authorization to accessing the resource). Is this possible?

GarethJ
  • 6,496
  • 32
  • 42

5 Answers5

33

Yes, it is possible if you have the right information - all you need to do is to get a delegated access token.

Explanation:

When dealing with access to resources, Microsoft Graph has two levels of access token requirements:

  • Most methods support Application only tokens, meaning once an OAuth app has consent it can access the resource whenever it wants.
  • But for some methods, it is not enough (they are too sensitive for an automated process) and require a Delegated token, meaning token which contains both a valid Client and User. You can see in each method documentation which token it requires.

Normally delegated access tokens are the result of the two major OAuth flows which require user interaction (Authorization Code Grant and Implicit Grant) but you can also get them from two other flows: Resource Owner Credentials Grant and On-Behalf-Of Grant, which are both supported by Microsoft.

For a full guide on how to setup everything you need in order to use those flows (including Postman examples) you can look at my article:

Getting Access Token for Microsoft Graph Using OAuth REST API

dbJones
  • 762
  • 1
  • 10
  • 31
Eran Hertz
  • 441
  • 4
  • 4
  • 2
    I spent over a week, trying to find an oauth without a user physically signing in.... I LOVE YOU!. PS. Bookings doesn't work service to service and you have to use account credentials – Gavin Thomas Nov 14 '18 at 00:10
  • 2
    You are a legend mate. Why is this nowhere documented on the MS page?! Btw I was using what you described as flow 2 in your blog post. I had to remove the resource param and add scope. That did the trick – tim Jul 20 '20 at 01:42
  • I tried with Client Credential Grant approach from your article and ended up with BadRequest "/me request is only valid with delegated authentication flow.". URL i have tried: "https://graph.microsoft.com/v1.0/me/messages" – Susaj S N Feb 10 '22 at 12:14
7

Yes this is possible. Essentially you grant access application access to Graph API instead of a user.

The documentation for such access is here:

https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service

You'll still need to a request a bearer token to send with all your REST requests, but the bearer token will be for the application itself and not a user.

I set this up for one of my applications using the Graph SDK for .NET, so if you need specific examples for Graph SDK for .NET let me know.

Brian Kraemer
  • 443
  • 3
  • 15
  • 1
    Thanks for replying. I've seen this before, it doesn't serve my purpose. What this enables is, the app itself to make API calls, which microsoft calls "Service to service calls using Client credentials" where there is no context of the user. What I wanted was that the user should be able to login and see only his one drive details. Moreover, with this approach of "Service to service calls using Client credentials", I believe one drive is not accessible. There is only support to user related APIs. – Krishna Chaithanya Muthyala Apr 28 '16 at 03:21
  • I think you can still access drive data with `GET /users//drive` – Brian Kraemer Apr 28 '16 at 14:59
  • 1
    Nope. For the app-only approach (a.k.a "Service to service calls using Client credentials"), it is not possible. In the Azure portal, when configuring the app, you can see that the application permissions don't contain anything related to drive. Only in delegated permissions, they are there. I even tried this using Postman and I get an empty response, but it doesn't give any error though. But am really not interested in this path since I want the user logged in to the app. So, I would still want the user to login using my own custom form to do the activity he intends to do with the drive. – Krishna Chaithanya Muthyala Apr 29 '16 at 05:56
  • 1
    Do you have an example project that demonstrates how to do this? – mheptinstall Mar 23 '17 at 17:41
  • Hi @BrianKraemer - the link is dead (redirects to their home page) - do you know if the page has been replicated somewhere? Thank you! – SamCyanide Mar 01 '18 at 16:10
  • Update link is https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service – Brian Kraemer May 11 '18 at 09:34
  • Hi Brain, i know its almost a year back, but do you still have the examples for Graph SDK for .NET as you mentioned above? I am trying to use graph api without a signed in user, so that I can read all users profile. I have created an app registration in Azure with relevant permission for the application. – NewBieDevRo Apr 08 '19 at 13:17
3

Although this is possible, it's strongly recommended not to do this for individual user access. The Microsoft Graph only supports OAUTH 2.0 as its authZ protocol, and we recommend that you use the flows within OAUTH where the trusted authority be the one to directly handle login credentials. Allowing application code to provide the forms UI for login credentials would open up the attack vector where your app would have direct access to the user's O365 password, which is not a secure approach.

GarethJ
  • 6,496
  • 32
  • 42
  • Yes, I should clarify that it is technically possible using the Resource Owner Credentials Grant, you absolutely should not do this, as from a security posture point of view, having the user's password in plain text flowing through your application when it should be a shared secret between the user and Microsoft is really awful. That grant is primarily supported to enable admin and scripting scenarios and (for now) headless devices. – GarethJ Oct 26 '18 at 02:40
2

I've found the documentation is not helpful, especially in terms of trying to acces the Graph API in the application context. But, I managed to get the access token in the context of the application here:

private static async Task<string> AcquireToken()
{
    var tenant = "yourtenant.onmicrosoft.com";
    var resource = "https://graph.microsoft.com/";
    var instance = "https://login.microsoftonline.com/";
    var clientID = "YourappID";
    var secret = "YourAppSecret";
    var authority = $"{instance}{tenant}";
    var authContext = new AuthenticationContext(authority);
    var credentials = new ClientCredential(clientID, secret);
    var authResult = await authContext.AcquireTokenAsync(resource, credentials);
    return authResult.AccessToken;
}
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Chris J
  • 596
  • 1
  • 8
  • 14
  • What SDK version are you using here, I'm getting multiple issues, with AuthenticationContext doesn't accept single argument, as well as AcquireTokenAsync not existing. – Bruce Burge Jun 01 '19 at 18:27
  • Should be V1.0. Was using this to connect to azure. – Chris J Jun 10 '19 at 17:57
1

Yes, It is possible to access onedrive shared folder with the help of shared url without userlogin.

  1. first you need to get an access token, to hit any microsoft graph API you need access token. follow the link to get access token without user login access token

  2. Encode shared url.

    string sharingUrl = "https://onedrive.live.com/redir?resid=1231244193912!12&authKey=1201919!12921!1"; string base64Value = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(sharingUrl)); string encodedUrl = "u!" + base64Value.TrimEnd('=').Replace('/','_').Replace('+','-');

  3. Discovering an endpoint https://learn.microsoft.com/en-us/onedrive/developer/rest-api/concepts/direct-endpoint-differences?view=odsp-graph-online#discovering-an-endpoint

  4. -for OneDrive personal accounts https://api.onedrive.com/v1.0/shares/{shareIdOrUrl}/driveItem?$expand=children

    OneDrive for Business and SharePoint https://graph.microsoft.com/v1.0/shares/{shareIdOrUrl}/driveItem?$expand=children