Can not access other users' data using Microsoft Graph API - microsoft-graph-api

This is my app's api permissions
api permissions
This is my postman settings
postman settings
I can get token successfully using an AD admin account
I can get all users successfully
user list
I can create calendar event successfully using this AD admin' user id
enter image description here
I can not create calendar event using another user id
enter image description here

First, this is the document api for introducing the api permission, you can see Permission type with Delegated and Application.
The second, this is the section for introducing the request example, you can see that there are 2 types /me and /users/{id | userPrincipalName}.
The difference between the 2 kinds of api permission is that, using Delegated permission means we need to make users sign in first to generate the access token and call the api, while Application permission not. So when we use Delegated api permission, we can use api request like /me because the token contained the user information so graph api knows who is me and me is authorized to access this api. So we can also use users/user_principle_name_of_the_signed_in_user here. But it doesn't mean we can use another user principle name here, because other users aren't authorized in the access token.
How can we put any user of your tenant into the request and call the api successfully? We need to use Application permission here. When you add api permission, you may notice it and please add application api permission. Then we need to use client credential flow to generate access token with application permission. Then you may try yor failed request with the new token.
Application permission means you are calling the graph api on behalf the application, so it doesn't require users to sign in, but using delegated permission is much more safe since it will generate access token with limited scope(the api permission you defined in the token generating request), but client credential flow uses /.defalut as the scope, this means all the application api permission in the azure ad application will be added to the generated token, you can't control which application permission is allowed and which is not allowed in one token.

Related

Microsoft Identity Platfrom on behalf of user vs Code flow

I am reading documents for Microsoft Identity Platform to implement api and protecting it by using Microsoft Identity platform and I do understand some what OAuth code Grant flow and Client Credential flow (for daemon apps).
Now when I am reading the documents it is keep mentioning authorization on 'behalf of user' and and 'behalf of itself'. So my question is "on behalf of user" is same as Code Grant flow?. Similarly if client credential flow is "on behalf of itself'.
If not then what is the difference between 'On behalf of user' vs Code grant flow.
Really want to understand as it keeping me in confusion.
Thanks
Azure AD supports the following OAuth flows/grants:
Implicit
Authorization code (with/without PKCE)
On-behalf-of
Client credentials
Device code
Resource owner password credentials
Refresh token
Link to docs: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols
In most of these, the application will get an access token that allows it to perform requests on behalf of the signed in user.
The access token contains both information of the app that requested token but also the signed in user's information.
This allows the target API to check both the application's access (scopes aka delegated permissions) and the user's access (roles/other form of access control).
The "on-behalf-of" flow might be a bit confusing here, but it has a specific purpose: exchange an access token obtained with one of the other flows (except client credentials) for a new access token.
It is used in scenarios where a client app uses e.g. authorization code flow to call API A, and API A wants to then call API B on behalf of that same user.
Client credentials flow is the only different one; when using it an application only provides its own credentials and a user is not involved.
Thus the access token only contains application information, and the application will perform requests as itself.
The target API will usually only check the roles in the token (application permissions, app roles with allowed member type application), though it can also check the id of the calling app if it has a list of allowed applications stored somewhere.

Does Microsoft Graph work without User.Read scope?

My question is, does Microsoft Graph work without User.Read scope ? I am not able to request the email profile openid permissions directly.
It throws AccessDenied error. So is User.Read pre requisite for email profile or openid ?
User.Read is just the delegated permission for getting the user profile using MS Graph Get User. If your app does not need to read the user profile you don't need this permission but in most cases you do because you app is acting on behalf of the user.
Does Microsoft Graph work without User.Read scope ?
No, but in most cases, you need the scope to read user profile and call /me endpoints.
You should check the api document to see if calling that api required User.Read permission.
For instance: I wanna call this api to list emails, and we can see that this api provides 2 kinds of permissions, one is for delegate, another is for application(this means client credential flow is supported). All the api permissions are listed here and we need to go to azure ad portal to add the api permission to your azure ad application which used to generate access token.
After generating the access token, you can user jwt decode tool to check if your access token contains correct scopes(for delegate permission) or roles(for application permission). Using a correct token to call the api will not lead to AccessDenied error. By the way, newly added permission may be deferrable to take effect.

OAuth access to EWS on behalf of a user

I have had success using OAuth 2.0 with EWS when using admin permission. Now I am trying to set it up so that an individual user can log in and grant access for himself. So I start a browser with this URL:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=f3f92d23-29dd-4465-828e-35300884ef61&redirect_uri=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fnativeclient&response_type=code&scope=offline_access%20Calendars.ReadWrite.All%20Contacts.ReadWrite.All%20Mail.ReadWrite.All%20Tasks.ReadWrite%20User.ReadBasic.All
The browser allows me to log in to my test account, but then this error is returned:
error=invalid client
description=AADSTS650053 The application 'my app name' asked for scope 'Calendars.ReadWrite.All' that
doesn't exist on the resource '00000003-0000-0000-c000-000000000000'
In Azure, when looking at the API permissions for my application, I have 11 Exchange permissions, including both Application and Delegated permissions for Calendars.ReadWrite.All, in addition to all of the others that I requested.
What's going on here?
Because EWS is a legacy API it doesn't implement the more restrictive permission model that the Graph and Outlook REST API uses. The only permission that will work for Delegate access is EWS.AccessAsUser.All (Scope https://outlook.office.com/EWS.AccessAsUser.All). This gives full access to every folder in a Mailbox (and any mailboxes the user has been granted access to).It looks like you application registration already includes that permission so
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=f3f92d23-29dd-4465-828e-35300884ef61&redirect_uri=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fnativeclient&response_type=code&scope=offline_access%20https%3A%2F%2Foutlook.office.com%2FEWS.AccessAsUser.All
should work

How to protect an API using Azure Active Directory, App Registrations and Enterprise Applications

I have an backend API in an Azure Website that I like to protect using Azure AD.
As I understand it I'll first do an App Registration, use information registration as part of the sign in to get a token back to the client.
I can then send that token to the API and validate the token in the backend API to verify it.
But don't that token give access to all resources in the subscription? How to I restrict the App Registration to only be allowed to access that specific API? And not also another API in the subscription?
I also like to have a set of users that are allowed to access the API. If I'll just allow everyone to log in using the App Registration, everyone that's in my AD will receive a token back?
Can I somehow use a Enterprise Application to restrict access to the API only and only allow a set of users?
Or is there another way of doing this?
But don't that token give access to all resources in the subscription? How to I restrict the App Registration to only be allowed to access that specific API? And not also another API in the subscription?
A token only gives access to the API identified by the audience (aud) claim in the token.
Nothing more.
So if your client app asks for an access token to your API, that token is only valid on that API.
I also like to have a set of users that are allowed to access the API. If I'll just allow everyone to log in using the App Registration, everyone that's in my AD will receive a token back?
Can I somehow use a Enterprise Application to restrict access to the API only and only allow a set of users?
Yes.
You can find the enterprise app (service principal) for the API, enable Require user assignment, and then assign the users/groups you want to have access to the API from Users/Groups tab of the enterprise app.
Access token acquisition will then fail for users who are not assigned.
If you are using the same app registration for both the client and API, then you have to remember that you should acquire an access token regardless to call the API.
Don't use the id token.
Also in that case, a user who is not assigned to the app will fail login.

Getting an Access Token for back-end server use

I need to get an access token for my server to user without a user having to authenticate.
I do this for DropBox and want to do it for OneDrive.
I have a service that needs to save files in its own OneDrive acct and then also copy some files to users' accts.
For the user we will authenticate with either the Token or Code flow. However, for the server I just want to have access token. In DropBox you get the access token on the App Settings page, but I can't figure out how to do it for Graph
Assuming you're talking about OneDrive Business, it sounds like you want to get an app-only token. Such a token will require a tenant administrator to consent, but after that it can access the service without any user.
If you're talking about OneDrive Personal the scenario isn't possible - all tokens are required to have app and user claims, and therefore require to sign in.

Resources