We're curretly making a multi-tenant app where admin users can log on Office365 and manipulate other users' emails. We want to add a schema extension on created Message, but I end up with a AccessDenied error.
Note that I use the arxone_path schema extension, that is Available (you can try to use it).
I first set up the delegated permission Mail.ReadWrite on my app registration on Azure (like said on https://learn.microsoft.com/en-us/graph/api/opentypeextension-post-opentypeextension?view=graph-rest-1.0#permissions ). I also added Mail.ReadWrite.Shared permission. Using the user's access token, I can actually fetch, create, delete or update Message of another user. But if I try to update a message to add a schema extension like this:
PATCH https://graph.microsoft.com/v1.0/{{user}}/messages/{{message}}
Content-Type: application/json
{
"arxone_path": {
"path":"some/path"
}
}
I always get this response :
HTTP/1.1 403 Forbidden
Content-type: application/json
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "a95b0641-63e9-4601-82f2-d8c4ed6d64d8",
"date": "2020-01-16T16:12:29"
}
}
}
To sum up, I can:
Edit one of the connected user's own message -> OK
Add extension of the connected user's own message -> OK
Edit another user message -> OK
Add extension of another user message -> NOT OK
You cannot add an Open Extension to a users objects using delegated access token for another user. You would need to have that user sign in and use their delegated access token.
The other approach is to use application permissions (app-only) and request User.ReadWrite.All which will require Admin Consent by an Administrator.
I believe this url says you may need additional permissions (depending on the account type) when trying to create an open Extension.
Delegated (work or school)
User.ReadWrite.All
Delegated (personal Microsoft Account)
User.ReadWrite
Application
User.ReadWrite.All
Related
I am trying to rech the endpoint
https://graph.microsoft.com/v1.0/users/{emailaddress}/mailFolders('InBox') but am receiving
Error Access Denied response.
I have granted both Mail.Read.Shared and Mail.ReadWrite.Shared on delegated permission.
The scenario I have is that in Azure AD there are a number of users , Manager#acme.com and Tests#acme.com , so they exist under the same tennant /organization.
I have an app whereby I login as Manager#acme.com as the current user. I the create a connection to the App using client id , secret etc and receive an Auth toke n to use in my api calls.
but when i try to call
https://graph.microsoft.com/v1.0/users/Tests#acme.com/mailFolders('InBox') with that token I
get the following error:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again."
}
}
Do i ned to grant both Mail.Read.Shared and Mail.ReadWrite.Shared on Application level ?
Or do i need to create a shared folder in Outlook ?
I don't believe Mail.Read.Shared or Mail.ReadWrite.Shared exist as assignable application permissions.
The only permission your App Registration should need is Mail.Read, unless you're intending on the using Graph to delete / send emails etc.
You will likely also need an ApplicationAccessPolicy. You can either create one in the Exchange Online Admin Center, or through PowerShell. I recommend you create a mail enabled security group for all addresses which you need to access and grant restricted access to your app through that policy.
I prefer PowerShell, so in that case you would need the ExchangePowerShell module, and connect to Exchange Online. You'll need some Exchange admin role to be able to do this.
So, let's assume you've created a mail enabled security group called GraphAccessibleUsers#acme.com. You can set the property to hide this from the GAL so users can't see it.
You would then create a policy as follows:
New-ApplicationAccessPolicy -AccessRight RestrictAccess -AppId "<Your-App-Registration-Id" -PolicyScopeGroupId GraphAccessibleUsers#acme.com -Description "Allow App access to users in GraphAccessibleUsers#acme.com"
The -PolicyScopeId parameter will accept:
Name
Distinguished name (DN)
Display name
Email address
GUID
If you only have a few addresses, you may opt to create an individual ApplicationAccessPolicy for each email address.
Finally, I don't think your Graph API URI is correct.
If you want to access the Inbox of Tests#acme.com, then try this instead:
https://graph.microsoft.com/v1.0/users/Tests#acme.com/mailFolders/Inbox
Please refer to mailFolder Resource Type here.
My company is using Microsoft 365 Business Standard licenses. We are using email through these accounts. We also have a few shared mailboxes. We are trying to create an app that uses the microsoft graph application permissions (rather than the delegated permissions) so the application can access one of the shared mailboxes without needing to be authenticated under the current user.
This is the steps we have taken so far:
Within Microsoft Azure, we have an application in which we have granted application api permissions for Mail.Read, and we have accepted Admin consent.
We authorized as an app, not as a user, in the application using this endpoint https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize, pointing out the required parameters for sending a request. Then, MS API builds this link:
https://login.microsoftonline.com/{some_string}/oauth2/v2.0/authorize?state={some_string}&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2F.default&response_type=code&approval_prompt=auto&redirect_uri=http%3A%2F%2Flocalhost&client_id={some_string}
When we follow the link, we get to the standard authorization form on the site. After we log in, a link is created, where we take the code and create the token: http://localhost/?code={some_string}&state={some_string}&session_state={some_string}
When we try to hit this endpoint: https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages, we get this response:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"date": "2020-09-14T11:22:30",
"request-id": "{some_string}",
"client-request-id": "{some_string}"
}
}
}
I am thinking that hitting this endpoint https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages requires us to pass the token previously generated and/or specify which application is making the query?
Any help or direction on what needs to be done to make this query work would be greatly appreciated. Thank you!
I am thinking that hitting this endpoint https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages requires us to pass the token previously generated and/or specify which application is making the query?
Yes you would need to send the AccessToken in the Authorization header, you should also include the x-anchormailbox header which helps route the request to correct mailbox eg
GET https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer EwAoA8l6BAAU ... 7PqHGsykYj7A0XqHCjbKKgWSkcAg==
X-AnchorMailbox: sharedmailbox#domain.com
The other thing you might want to check is to ensure you have the correct scopes in your token you can use https://jwt.io/ for that
In order to use application permissions you will need to use the client credentials auth flow (not the authorization code auth flow which uses delegated permissions). To get a token make a request against "/oauth2/v2.0/token" and specify "grant_type=client_credentials" in the request. See examples of client credentials auth flow here for more details: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
I am attempting to use the "List Contacts" Microsoft Graph v1.0 API (https://learn.microsoft.com/en-us/graph/api/user-list-contacts?view=graph-rest-1.0) to retrieve the contacts of various users in my organization. In other words I want to list contacts in a delegated fashion.
My problem is that this API only seems to work for the user associated with the access token, e.g.:
Get Microsoft Graph API token for user "A"
Request to https://graph.microsoft.com/v1.0/users/USER_A_ID/contacts works fine
Request to https://graph.microsoft.com/v1.0/users/USER_B_ID/contacts fails
The error returned by the API is:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "[REQUEST_ID]",
"date": "[DATE]"
}
}
}
I have verified that the token contains the "Contacts.Read" scope by decoding the JWT token and examining the "scp" field, so I do not understand why the APIs saying that access is denied. Any ideas as to why this is failing?
Your need Contacts.Read.Shared or Contacts.ReadWrite.Shared, Your current Contacts.Read scope will only allow you to access the current users Contacts Folder. The other thing is the user requesting will still need to be granted the underlying delegate rights to the Target Mailbox Folder ( via Outlook delegation or Add-MailboxFolderPermission eg they need to be able to access the folder via Outlook or OWA).
I am trying to develop a simple background app to connect to my onedrive account (work) and regularly download some files.
I followed this tutorial https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-client-creds
I have registered the app here https://apps.dev.microsoft.com/portal/register-app
I have written down the client_id and client_secret
To get an access token I make a POST request to
https://login.microsoftonline.com/common/oauth2/v2.0/token
with the following form encoded data
{
'client_id': 'clientid here',
'client_secret': 'secret is here',
'scope': 'https://graph.microsoft.com/.default',
'grant_type': 'client_credentials',
}
I get back an access_token
{'ext_expires_in': 0,
'token_type': 'Bearer',
'expires_in': 3600,
'access_token': 'eyJ0eXAiOiJKV1QiLCJhbGciO---SHORTENED FOR BREVITY'}
Next I make a GET request (with Bearer header properly set) to https://graph.microsoft.com/v1.0/me
and get this eror response (which I get for any endpoint fwiw)
{
"error": {
"code": "BadRequest",
"message": "Current authenticated context is not valid for this request",
"innerError": {
"request-id": "91059f7d-c798-42a1-b3f7-2487f094486b",
"date": "2017-08-05T12:40:33"
}
}
}
I have these permissions configured in the app setting
Any ideas what might be wrong?
I'll file a bug to improve this awful error message. The problem is that you are making a request using application permissions (client_credentials flow) - where there is no signed-in user context. Your request is to /me, and /me is basically an alias for the signed-in user - and in this case there isn't one!
You should try a call to https://graph.microsoft.com/v1.0/users instead. But, before you do that. In the app registration portal, you've selected delegated permissions, but you are calling with application permissions. You should remove the delegated permissions, and select the appropriate application permissions - to call users, select User.Read.All for example. Then make sure to consent/reconsent your app by going to the /adminconsent endpoint.
Please also read more on permissions and delegated and application permissions here: https://developer.microsoft.com/en-us/graph/docs/concepts/permissions_reference
Hope this helps,
i used https://graph.microsoft.com/v1.0/users/{{Emailid}}/messages to get all the messages in my inbox
In clientCredential flow you are accessing as an with Client secret or with client certificate . So Graph API no linger understands who is me. So you need use https://graph.microsoft.com/v1.0/users/<Your_userId> or https://graph.microsoft.com/v1.0/users/<your_userprincipalname>.
eg.https://graph.microsoft.com/v1.0/users/1sd1353as..
or
eg.https://graph.microsoft.com/v1.0/users/John_doe#contso.com
Reference: https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http
My goal is to allow users to change and reset their own passwords within my application. We do not want users to be redirected to consent pages.
I've followed the instructions defined here:
But I'm running into the following error:
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "19c43c69-f553-470e-9432-617395f5f8f5",
"date": "2017-06-01T17:24:11"
}
}
}
My patch request:
PATCH /v1.0/users/2b6c3114-d81b-429d-af7e-c822a456ebba HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJ...xnsYVw
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 73f...d6
{
"passwordProfile": {
"password": "w",
"forceChangePasswordNextSignIn": false
}
}
Here's my graph permissions:
Delegated permissions:
User.Read, User.ReadWrite, Directory.AccessAsUser.All*, Directory.ReadWrite.All*, User.ReadWrite.All*
Application Permissions:
Directory.ReadWriteAll*, User.Read.All*, User.ReadWrite.All*
* Admin Consent Required
I understand that the scope Directory.AccessAsUser.All is required when using the passwordProfile property. Since this isn't available as an application permission, does this mean I have to get access on behalf of a user and use the Authorization Code grant? I don't see any possible way to avoid user consent when using authorization codes to retrieve a token.
EDIT 1
I've tried getting the token using the client_credentials grant_type but I always receive a message that the scope is invalid if I don't use a scope of https://graph.microsoft.com/.default:
POST /tenantid/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: 006...85
client_id={id}&scope=https://graph.microsoft.com/User.Read&client_secret={secret}&grant_type=client_credentials
So I will caveat this answer with the fact that there may be good reasons for doing what you are doing, but you should be aware of all the things that the organization will lose by bypassing Azure AD sign-in and related features like SSPR. Please see this excellent blog post that describes some of the things you'll lose - plus while this is still relevant, there are now MORE security features that your customer will lose, like conditional access.
Anyways, assuming you want to press ahead...
For your scenario (an app service that bypasses Azure AD SSPR and change password experiences), there is an option for change password (that it appears we did not document - filing a bug for that) and regrettably nothing I can offer for password reset. Let me address the first one.
Change Password - in Microsoft Graph (although not documented) you'll find the "changePassword" method on user - ../users/{id}/changePassword, which takes the old password and a new password. This API works ONLY for the signed-in user (so it requires the delegated OAuth2 code flow). It requires an admin to consent for Directory.AccessAsUser.All (although we are looking at adding a more granular permission).
Reset password - there is no app-only permission exposed by Microsoft Graph for this. This is an extremely powerful permission to grant to an application. You've already been given the workaround by support, for an admin to explicitly grant this using powershell. This grants your app a lot of privileges to your customer's resources. Alternatively, there is a delegated permission (Directory.AccessAsUser.All) that allows an admin user to reset another user's password. However this wouldn't be a self-service experience.
Hope this helps,
I have resolved this after talking to Microsoft.
Turns out that app registrations need a role assigned to them.
Install the Azure AD Module -
https://learn.microsoft.com/en-us/powershell/msonline/
Open a
“Microsoft Azure Active Directory Module for Windows PowerShell”
command prompt:
$AADCreds = Get-Credential // You will be prompted for your credentials
Import-Module MSOnline Connect-MsolService -Credential $AADCreds Get-MsolServicePrincipal -AppPrincipalId "" // Note: Copy the ObjectId for your Service Principal
Add-MsolRoleMember -RoleName "" -RoleMemberObjectId -RoleMemberType ServicePrincipal
I used "User Account Administrator" for the directory role.