Microsoft Graph API accessing Excel doc permissions - excel

I am diving into the Microsoft Graph API and want to use its features to interact with an Excel workbook. I intend to create a client side application that interfaces with my API which in turn interfaces with Microsoft Graph API.
I ran into some confusion with the Microsoft Graph permission documentation. When sifting through the Excel API documentation, I saw that in order to Update Range or Get Worksheet (or really any endpoint) I need to have Delegated (work or school account) permission. I then looked at the Graph permission doc mentioned above and it says:
Delegated permissions are used by apps that have a signed-in user present. For these apps either the user or an administrator consents to the permissions that the app requests and the app is delegated permission to act as the signed-in user when making calls to Microsoft Graph. Some delegated permissions can be consented to by non-administrative users, but some higher-privileged permissions require administrator consent.
To me, this reads "a user must login using oauth to interact with a workbook via the API". I'm hoping that is not the case, because I want to have the workbook data publicly available and to have read/write permission. I understand I will have to authenticate some (admin) user within my organization in order to retrieve/update a workbook (via the Graph API) stored in OneDrive, for example, but I just wanted to see the requirements for accessing the workbook.

Looks like you intend to use Excel workbook as a central source data rather than an individual user based store. In that case you can access API without a user sign-in by using application level consent. See here. Client "app" will call into a server (such as nodeJs) and that in-turn will make API calls to Microsoft Graph to interact with Excel workbook. This server-to-Graph call is abstracted from the client app and hence secure.
The downside of this approach is that you'll need server implementation and you can't implement single page application that doesn't require server side implementation. It is not a big hurdle - just takes different set-up.

Related

Basic Microsoft Graph App to retrieve a shared Excel File

I am trying to understand Microsoft Graph APIs but I found them kind of confusing. There's an excel file that is shared with me on OneDrive. I want to download it using Microsoft Graphs. I was able to generate the app and set up its configurations and permissions so that I can send a request and get an authorization token that I can use to send requests.
However, I have a couple problems, even in Graph Explorer, which I use as my account, not as the app.
To find out the file Id that is shared with me, I used the "files shared with me" API that is under OneDrive. (https://graph.microsoft.com/v1.0/me/insights/shared)
I copied the id that I get from there and used it in "worksheets in a workbook" API under Excel category. https://graph.microsoft.com/v1.0/me/drive/items/{drive-item-id}/workbook/worksheets)
However I got Item Not found error. The problem is, even though I can see it on oneDrive as a shared object I can't seem to open it using the second API.
How can I download the Excel file that is shared with me through OneDrive? Which API should I use? The app that will send the requests is a standalone app that will send the requests without human authorization. I don't know the correct terminology here but Microsoft doesn't allow it to have a /me request, it gets "/me request is only valid with delegated authentication flow.", therefore I probably need someway for app to see that oneDrive link. But I was unable to find a working way.
The error message "/me request is only valid with delegated authentication flow." means what it says. There are two main ways to authenicate a application with the graph API. Application authenication and On behalf of user authencitation. So the error message is telling you that you are using the application authenication and the API path /me is only accessable with On behalf of user authencitation (e.g. delegated authentication). This makes sense because when using the application authenication who is me?
The API endpoints says what authentication types they support. If you take the worksheets API it says under permissions section:
Permission type - Permissions (from least to most privileged)
Delegated (work or school account) - Files.ReadWrite
Delegated (personal Microsoft account) - Not supported.
Application - Not supported.
Which is telling us that Application and Delegated for personal Microsoft accounts are not supported and that Delegated for work/school accounts requires the Files.ReadWrite permission.
To download the drive item you can use the download item API.
This supports both Application and Delgated permissions. For Application permisions you will not be able to use the /me path though. You will most likely have to use something like:
/users/{userId}/drive/items/{item-id}/content
I am assuming your file is stored in a work account one drive storage and not in one of the other storage places (AD group, etc).

(spfx) Can the granted permissins extend beyond the permissions of the currently logged in user?

I use the SharePoint Framework because I want to access Teams messages through the Graph API using the MSGraphClient.
I have two end goals:
Building a webpart with delegated permissions
Archive messages from a Teams channel using some kind of app permissions instead (?)
I know that the permission scopes have to be approved by an admin in the Sharepoint Admin center. However, I am a little confused regarding the actual scope of these permissions, bear in mind that I need to abide by the local data protection laws, so my app/webpart may not have access to just everything.
I would like to know whether the permissions granted to my MSGraphClient by the Sharepoint Admin can extend beyond the permissions of the currently logged in user.
I cannot tell from the documentation in which cases the permissions are delegated and in which cases their are actual application permissions.
For example, if my MSGraphClient is granted the permission "ChannelMessage.Read.All", can the currently logged in user read "all" messages of all users, or only those messages that he actually has access to?
Are all of the permissions granted through the Sharepoint Admin Center delegated?
Appart from that, if I wanted to have access to messages regardless of the permissions of the currently logged in user, would I need to use an app token from Azure? If so, is it possible to restrict these permissions to only include reading privileges of specific Teams channels?
The permissions of SPFx web part cannot extend beyond the currently logged-in user. To have extended permissions, you need server-side code. In share point, the thing you are looking for is probably called app-only permissions.
For SPFx web part, running in the browser, this is not possible (and does not make any sense because this would immediately compromise the security). Means, SPFx web part cannot do more than a user can do.
For your case, I would build a service, that has all necessary permissions granted. Basically, a normal web app, that is hosted on a server (can be in a form of azure function or a normal web app, i.e. a website), that, when called, would go and archive these messages. This app should have access to all channels it needs to archive. Then this app can provide some API that can be called from your web part (in case you still want a web part)
Then in that server app you can validate if the user has appropriate permissions to do what he's intended to do. You do that in server-side code, to which user has no access. Doing that it in the browser (in JavaScript) does not make any sense because the user has full access to JavaScript in the browser and can edit it any way he wants.

Azure Active directory API permissions

I have got a scenario where I would like to retrieve calendar bookings/meetings from Exchange using Graph APIs. These meetings should only be available in the application running on control/touch panel located in that room. In order to do that, I have registered an App in Azure AD and using MSAL's .NET PublicClientApplication with necessary API permission i.e. Calendars.Read which requires Admin consent and I am using Device code flow in the application which generates a code whenever I try to run the app.
I see that it's also possible to configure a ConfidentialClient which acts on behalf of application and not the user. Also, this requires a pre-consent from Admin.
Question :
Not sure which type of authentication mechanism is best suitable in this Scenario ?
Is it possible to make API permissions for e.g. "Calendars.Read" to work for a specific account? Like in this case just for that room
Not sure which type of authentication mechanism is best suitable in this Scenario ?
I think both of them could meet your requirement, for the security, I recommend you to use the option one. Something you should note, if you are using the delegated permission Calendars.Read with auth code flow, the user need to log in the App, then the app do operations on behalf of the user, essentially the permission comes from the user.
If you use the application permission Calendars.Read, it uses the client credential flow, the permission comes from the application, it means everyone in the room can use the application to retrieve calendar bookings/meetings.
Is it possible to make API permissions for e.g. "Calendars.Read" to work for a specific account? Like in this case just for that room
No, you could not make the API permission to work just for a specific account.

Requesting Azure AD permissions on-demand

We have a multi-tenant single page app (and backend) that uses Azure AD for authenticating users. We'd like do queries to customer's Azure AD for retrieving groups but make it an opt-in behavior for customers (tenants). The reasoning behind that is that not all customers necessary need the functionality and would rather not grant us access to their AAD unnecessarily.
Is there some way of implementing this with Azure AD?
I've been trying to test with different OAuth /authorize calls with resource IDs and scopes but mostly I end up with "AADSTS65001: The user or administrator has not consented to use the application with ID ''. Send an interactive authorization request for this user and resource." error. Configuring the web app or backend to require the permission would surely fix the error but that will also make the approval of it mandatory for all users of the app.
Is there a way of using the authorize/consent API to request access to a new application on-demand?
An ugly work-around that should work would be to have 2 client IDs and 2 backend IDs with different permissions but ADAL.js doesn't seem to be designed to work with multiple Client IDs (it's singleton, for starters). Also Application Permissions should of course work but I'm not sure how much of those are required to search for groups.
Is there a way of using the authorize/consent API to request access to
a new application on-demand?
Do take a look at Azure AD v2.0. With their incremental & dynamic consent model, it is possible to do so though I am not sure if this specific functionality (managing groups) is available there.
I had a discussion with Azure AD team member recently about this (as we are also facing the same problem) and he suggested that we take a look at this.
Essentially the way things work in Azure AD v2.0 is that you start with basic set of permissions (like sign in, read profile etc.). Then when some tenant need specific permission, you essentially ask them to grant those permissions to your application at that time only. What this means is that different users in your application have granted different permissions to your application.
If you are using MSAL, and looking for a way to dynamically change your scopes before authenticating, have a look at this: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/configuration.md#msalguard---dynamic-auth-request
More here: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/configuration.md#platformbrowserdynamic

Silently log onto Microsoft Graph?

Since I have my users log in and password, can I silently log into their Microsoft Graph?
I want to fetch info from Office 365 API from a server app, so therefor I cannot have a Microsoft Login Window popping up.
Thanks
You want to use the confidential client flow for authenticating the Graph API. See the section "Daemon or Server Application to Web API" in this document for details. Of course you'll need to be the admin of you Azure AD, or have the admin's trust and blessing, in order to use this flow as the user isn't involved in the process themselves.
I've been trying to use it for calendaring apps. The flow login works fine but be aware that there are some limitations on using the Graph API with this authentication flow type (specifically interacting with Unified Groups calendars in my case).

Resources