Skip to content
This repository has been archived by the owner on Jun 17, 2024. It is now read-only.

Application started throwing Insufficient privileges to complete the operation #27

Open
arun-binary-write opened this issue Nov 4, 2015 · 36 comments

Comments

@arun-binary-write
Copy link

I was trying to update an user using this application, but I started receiving the exception saying Insufficient privileges to complete the operation, access_denied.

{"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}}

It looks very strange though am able to create user, only the update is troubling.

In fact its blocking the production, we are not able to update existing users profile thus blocking user from accessing the underlying application.

@avaranovich
Copy link

+1 I have the same issue, not beeing able to change the password for the existing user.

Tried this one
https://support.microsoft.com/en-us/kb/3004133

but did not help so far

@thomas-frantz
Copy link

I'm getting this issue as well. I was actually running a .NET app as a daemon to create/update AD accounts based on our own internal DB. Now it's just broken with this insufficient permissions, and I have changed nothing. This has pretty much broke something I was just about to deploy.

edit: Would be happy to help track it down, or if I can provide more info. Don't really know what would be helpful, though. Let me know and I'll update/reply.

@dkershaw10
Copy link

What permission scope and update are you trying? We recently made a change such that Directory.ReadWrite no longer allows resetting of user passwords. Is this what you are hitting?

@thomas-frantz
Copy link

It appears to be. After messing with it more, it seems to update users as long as I disable the password setting code.

What would the work around be for this, if that's it? This is a fairly breaking change, we can't be there every few hours to log the service in again, that's why I made it a background type application in the first place.

I've been trying to read up on it, but there's so much information out there it's seriously overwhelming, lol.

Thanks!

Edit: Also I gave it all the permissions in the WAAD application, I'm assuming that's the scope you're wanting to know.

@arun-binary-write
Copy link
Author

actually i have reached out to support folks, they have mentioned " due to recent security enhancement to AAD the application which is accessing the AAD through Graph API should have a role called Company Administrator". There is no way from portal we can set the role for an application, however there is a power shell script which will set role for an application. After setting the role, i can update an user but not his role / group. i.e i can change the password, email.

below is the power shell script

#'===================================================================
#' DISCLAIMER:
#'-------------------------------------------------------------------
#'
#' This sample is provided as is and is not meant for use on a
#' production environment. It is provided only for illustrative
#' purposes. The end user must test and modify the sample to suit
#' their target environment.
#'
#' Microsoft can make no representation concerning the content of
#' this sample. Microsoft is providing this information only as a
#' convenience to you. This is to inform you that Microsoft has not
#' tested the sample and therefore cannot make any representations
#' regarding the quality, safety, or suitability of any code or
#' information found here.
#'
#'===================================================================

$tenant = ""
$tenantGuid = ""
$graphver = "1.5"
$appID = ""

$userVal = "@" + $tenant
$pass = ""
$Creds = New-Object System.Management.Automation.PsCredential($userVal, (ConvertTo-SecureString $pass -AsPlainText -Force))

Connect-MSOLSERVICE -Credential $Creds
$msSP = Get-MsolServicePrincipal -AppPrincipalId $appID -TenantID $tenantGuid

#ID of the Application
$objectId = $msSP.ObjectId

Add-MsolRoleMember -RoleName "Company Administrator" -RoleMemberType ServicePrincipal -RoleMemberObjectId $objectId

@thomas-frantz
Copy link

That did the trick, creating a new user worked fine, and updating current one's worked fine (including the password.)

I'm assuming since this sets the role on the app, it's a permanent fix, and not a temporary workaround?

Also, can you clarify this:

After setting the role, i can update an user but not his role / group

So if I categorize users into groups, I can't change it with just that permission?

@arun-binary-write
Copy link
Author

yes it seems to be a permanent fix.

Regarding role / group change , your understating is correct. I think support team have escalated this to AAD team, am waiting for them to get back on this

@thomas-frantz
Copy link

Out of curiosity, can you if you use Global Administrator, instead of Company? I'm not sure if there's a difference, or if that's a thing. I've read a ton of crap today, and I seem to remember seeing something like that with "Global Administrator" in it. Could be wrong.

Glad you're getting them on it though! Thanks for the help, keeping an eye on this issue.

@arun-binary-write
Copy link
Author

I tried doing global administrator , but it didn't work. Weird though

Sent from Outlook

On Tue, Nov 10, 2015 at 1:36 PM -0800, "Thomas" [email protected] wrote:
Out of curiosity, can you if you use Global Administrator, instead of Company? I'm not sure if there's a difference, or if that's a thing. I've read a ton of crap today, and I seem to remember seeing something like that with "Global Administrator" in it. Could be wrong.

Glad you're getting them on it though! Thanks for the help.


Reply to this email directly or view it on GitHub:
#27 (comment)

@dkershaw10
Copy link

Folks,
[Global/tenant/company administrator are all the same thing.]
We removed a very privileged operation (resetting users passwords) from the Directory.ReadWrite.All app-only and delegated permissions, with the intent to provide an explicit alternative. However there was a rush to get this out before providing the alternative - I apologize for that. That will break the console app. We'll be updating the console app shortly with many improvements, fixes, and changes to account for this and other platform changes.

Please do not use this as a permanent fix in any real solutions. I totally understand why Support suggested the workaround, and that this does solve the problem, to get the console app running again. However, this does not follow the principal of least privilege - you should be granting the application the least privileges to get the job done AND if possible running in delegated mode (where there is a signed-in user context). The second part of the console app shows you how to call in delegated mode, where Graph API evaluates both app permissions AND user permissions before deciding whether to execute the request. If you configure your app to request (for now) Directory.AccessAsUser.All (Access the directory as the signed-in user), this would work and be more secure.

I'd like to understand from folks if you plan on using the app-only flows here, rather than the delegated (app+user) flow? What scenarios are you trying to accomplish where you are resetting user passwords without an administrator being present as part of the reset?

Or is it simply that you are trying to get the console sample to run?

Thanks!

@thomas-frantz
Copy link

I'm currently writing an employee portal for our company, this includes the office staff who already have office 365 accounts (and thus SSO through AzureAD), and about 400-500 out of office staff who do not have (or need) office 365 accounts. They will, however, need portal access.

To do this, I am bringing in their information from our backend system and putting it in AAD and putting them under specific groups. I don't really need to reset their passwords for this, but that is helping speed up development as I can simply run the syncing code again and get a fresh temp password and I can start testing from the beginning. When it goes production, it won't be resetting passwords, besides the first time just to reset their password to a fresh temporary password. It will also need to change groups, regular profile information, delete and create users, things like that.

While I understand that you guys saw this as a security issue, I don't really understand why it was such a crucial issue that it had to have a rushed, breaking change. Furthermore, the amount of information I had to dig through to figure out what was going on and how to fix it was ridiculous. And, ultimately, the only reason I fixed it at all so far is because @techiearun posted that powershell. Now I have concerns of "well, what else are they going to determine is an issue and rush through?" - I can't have this thing in production then you guys decide "well, adding users to a group can't be part of this!" and it breaks the whole syncing process for a day while I dig through Microsoft tech blogs trying to figure out what happened. That's just not acceptable, if that becomes the case. I understand the security concerns, but at the same time, things can't just break.

That said, it's only happened once to me, and I accept the apology and that something was probably going on to warrant it. But, we need an easy way to find out what's going on with this, is there a central place we can stay informed on changes to the API and azure permissions, and other things like that?

Thanks, and sorry if I come across as harsh.

@dkershaw10
Copy link

Thanks for your honest feedback.
I totally understand your concerns, especially around any changes to existing permissions capabilities. Functions like adding and removing members from a group will not be removed from the Directory.ReadWrite.All permission. We do hope to release some new more specific app-only permissions around user and group management. You can already see some of those in the list of delegated permissions - but these will be available side-by-side with the existing Directory.* permissions. I'll work to try and ensure that this kind of thing doesn't happen again. If our team decides that it is imperative to remove a set of functionality from an existing permission, we'll attempt to notify customers/developers ahead of time AND provide an alternative ahead of time, allowing developers to switch or add a new permission, before we take back any functionality on an existing permission. If we do have to go down this road, does this seem acceptable? On notifications - we're looking to start sending out Azure AD message notifications. You can configure this by going to the AD dashboard page in the Azure Management Portal, and clicking "Communication Settings" and filling the form. We also regularly post as updates on the Graph API blog - you'll actually see the same topic discussed there under the latest blog post.

On I'm still trying to understand in your scenario why when syncing the user for the first time, that you set the password on user creation? That should still be possible. I'm probably not quite following your workflow (maybe you need to create the user first, and then update the password in your flows?)

Hope this helps, and again sorry for the issue here.

@thomas-frantz
Copy link

Hey,

Yeah a blog would be great. So would the contact setting in AAD for things like this. Maybe something with a notice that it's going to change, and a temporary workaround or something (or the alternative solution, if that's available) so that we can consider it and get a plan going.

As for the other question: I work for a trucking company, currently the portal can already do SSO for our office employees as we all have office 365 accounts (so they exist in AAD). However, the drivers have no account here nor in office 365 (They have no need for an O365 account, honestly.) The only information we have here is profile information (Name, address, things like that.)

So what the syncing process does is grabs all the drivers and makes them accounts. Essentially with two different paths it can take:

  • Path 1: The driver exists in AAD. If this happens, simply his profile information is updated, no user is created.
  • Path 2: The driver does not exist in the AAD. If this happens, his account is created in AAD, and we create a temporary password for him (this works fine, as we're not resetting the password.)

Because we have no way to completely automate the setup process on our end so that they just end up with their SSO login for our portal, we have a first-time activation process where they visit the portal, fill our some info and get their temp password. This directs them to the MS SSO page where it prompts them to change it, and then back to the portal like normal.

When I say I use the resetting in development, I've basically added also resetting their password to "Path 1", this way while I'm testing the system (It's not deployed yet) I can start fresh with a new temp password each time, and go through the activation process again. This saves me the time of deleting and re-creating their accounts instead (granted that would be automated, too, it would still take more time.)

Hopefully that makes a bit more sense. Essentially the reset is only being used, in this case, to simplify the development (instead of adding delete code, I just add a line to give them a new password.) It also let me test the update code, but that could be done regardless.

Anyway, thanks for the info! I'm glad to see there's some decent commitment to this, and the APIs have actually improved considerably since the first time I looked at them about 6 months ago (there wasn't even a /me path when I started looking at all this.)

@Matthewsre
Copy link

I am currently trying to write integration tests for an application that uses the Active Directory Graph API to add a policy to an Application. In the setup of this test I am trying to add an application to test this with in my test environment and get "Insufficient privileges to complete the operation.".

I have adding the Company Administrator role with the powershell script above, but that did not solve this issue. What would be preventing my test from creating the application? Any help would be appreciated.

EDIT: Nothing changed that I can tell and this is now working today

@dansan
Copy link

dansan commented Jan 4, 2016

Hi,

I'm writing a Python daemon in Linux that synchronizes selected users and their groups from a local LDAP directory to AAD as a way of provisioning them for Office 365 use. Backend systems are Linux-only. We're using the REST-API. The software runs as a non-interactive service using client authorization using the token request flow based on certificates. That has worked great for us, except for this issue.
Two questions:

  • It seems to me, that this permission change not only affects the password attribute, but also the mobile attribute and the permissions to delete users and groups.
    • Can you confirm this?
    • What other attributes and classes are affected?
  • We cannot run PowerShell scripts from Linux.
    • What other method is there for the above workaround?
    • What protocol/API does the PowerShell scipt use to make the change?
  • Is there another non-interactive way to delete users/groups?

@dkershaw10
Copy link

@dansan There has been no change in the permission as described here: https://msdn.microsoft.com/en-us/Library/Azure/Ad/Graph/howto/azure-ad-graph-api-permission-scopes (see Directory.ReadWrite.All details). This permission has never allowed deleting users or groups.
Unfortunately, until we expose more granular app-only permissions it'll be difficult for you to achieve your request. Looks like a gap here - sorry about that. As a stop gap (seeing as this is a one time operation to configure cloud settings/state), maybe you could get a windows client machine, and run the PS once (and I realize this is pretty heavy-handed for a non-Windows org)? NOTE: If you run PS I STRONGLY suggest adding the app's service principal to a LESS privileged role - like the User Admin role (which will allow user/group deletion).

Hope this helps.

@dkershaw10
Copy link

@Matthewsre - sorry for the late response. Is this still a problem, or is this working now?

@mrmercury
Copy link

I'm also interested in knowing if the alternative has been released.

@mrrajeshrai
Copy link

mrrajeshrai commented May 1, 2016

That restriction has been set up from Admin side. Kindly, contact your admin to give privileges to your app. Had the same issue, contacted admin team, once they granted permissions for my app. It worked fine :)

@irwinwilliams
Copy link

@dkershaw10
I was trying to use the Azure AD graph to create graph extensions.
The Subscription Admin made me a Global Admin and I was getting authorization exceptions. Once I ran the script above, #27 (comment) I was able to press through with the extensions I needed to create.
In terms of the calls to the graph, they went something like this (Power Shell):
#$tenant defined previously
$applicationId = "[guid]"
$resource = "applications/$applicationId/extensionProperties"
$uri = "https://graph.windows.net/$tenant/$($resource)?api-version=1.6"

$data = @{"name"="Prefix";
"dataType"="String";
"targetObjects"= @("User");
}
#$authheader defined previously
Invoke-RestMethod -Uri $uri –Headers $authHeader –Method Post –Verbose -Body ($data | ConvertTo-Json) -ContentType "application/json"

@silentbobbert
Copy link

It still seems you need a service principal with the "Company Administrator" role to just do simple read queries of the users in AAD via the Graph API. A user logged in interactively, through Graph Explorer can perform the same operation with no special rights.

Is there any plan to address this? There are legitimate reasons for running services in the background using a Service Principal to query AAD. Promoting that service principal to "Company Administrator" just seems total overkill.

@synesthesia
Copy link

synesthesia commented Oct 27, 2016

Ran into the same issue (Service Principal having rights to create an application in AAD). When trying to add the Company Administrator role I get "This role does not exist", even though Get-MSOLRole clearly shows it in the list....

@webbes
Copy link

webbes commented Nov 28, 2016

This is really stupid. Please remove the ability to assign an "application permission" in the UI, if the application does not actually get the permission when you, as an admin, assigns them. These kind of things really piss me off. The UI pretends your application has the required permissions assigned, and only when you start to search the internet, because you are completely lost on what to do next, as things clearly don't work as expected, you find some information on GITHUB!? that tells you that the UI is telling you nonsense!? Microsoft again wasted so much of my time. And then I see these questions here like "Why are you using app only permissions, and what are you trying to accomplish? Can't you use delegated permissions?" Sure I can, but in my case I'm writing a walk through on how to configure App Only permissions and the UI indicates no problem at all to read all directory users. So the questions are not relevant. The UI is really bad. That is all.

@Giaco9
Copy link

Giaco9 commented Feb 12, 2017

Nothing new about this issue?
I need to grant my application the permission to delete a user in my active directory. How can I accomplish that? I need to assign the Company Administrator role to my app? I have to do it through the Power Shell? Is there a simple script to do it?

@Pikhulya
Copy link

Pikhulya commented Feb 14, 2017

Assigning Admin role will help but that looks like an overkill and not safe approach because the App's Service Principal will then be having unnecessary high privilege.
Azure Portal contains a button which can solve the problem in a safer way: It will result in App Roles assignments which will be recorded in properties appRoleAssignedTo and appRoleAssignments corresponding to the App's and Graph's ServicePrincipals in your tenant so they will be updated to match what you selected in Required Permissions for the Graph inside your App.

This is how the button can be accessed:

  • Click on your application
  • Click "Required permissions"
  • At the top you will see the button "Grant Permissions", that is what you need.

Once you complete that set of steps in the portal and will try to acquire a token, don't be very surprised if it doesn't work immediately - wait for several minutes and try acquiring the token again.

@silentbobbert
Copy link

@Pikhulya have you actually tried your suggestion? As I said in my comments even users without any elevated permissions can read users from a directory as long as the log in interactively. If you have a batch process/windows service/web api etc, using a Service Principal to authenticate against AAD/Graph API then that Service Principal needs to be elevated all the way to "Company Administrator". It didnt matter what checkboxes you checked in the App Registration widget in the portal. No interactive login == no read access to users.

For those guys wanting to delete/update users using a Service Principal, they cant even read users, never mind update/delete them.

Are you saying its now possible to take a new service principal and using the App Registration widget alone, its possible to grant rights to read/update/delete users to that service principal?

@Pikhulya
Copy link

@silentbobbert Yes, I actually tried that suggestion earlier as well as while writing this specific reply - it still works (but don't forget about the delay). The reason why you could read users with a User token is because delegated permission "Read all users' basic profiles" doesn't require Admin role. The reason why you could not do anything while calling the Graph with an Application's token is because any Graph Permission on Application level requires an Admin to stamp those roles into your Service Principal.
So, the fact that you selected checkboxes under Application Permissions section means that you just "declared" that your app Requires those permissions but they would be "materialized" (means actually assigned to your App's Service Principal) only if a need for Admin requirement (specified for every permission) is met.
It could be met by either making the Service Principal an Admin - that is what that aforementioned script does (which, again, looks like an overkill) OR by leveraging that button but you have to be Admin to do that. The same result as clicking that button can also be achieved programmatically (you also have to use an entity - User or Service Principal with Admin privilege) by updating navigational property ServicePrincipal.appRoleAssignments corresponding to your App.

If you click the button or do that programmatically you are in fact granting your application's Service Principal access to those Application Permissions you marked in the UI in Application Permissions section.
You can prove that by executing let's say Get-AzureADServiceAppRoleAssignment while providing ObjectId corresponding to the Graph's Service Principal in your tenant. If you execute that before clicking the button you will not see a record for your application but if you click it and then execute = you will see a record indicating that your App's Service Principal now has access to the Resource Application (Graph in this case) in those roles (permissions) you selected in UI.

You don't need literally new Service Principal for your app in your tenant to achieve what is described above, an app in a tenant could have just 1 Service Principal which has to be updated accordingly as described above.

Did you ask the question above because you tried the suggestion and it didn't work for you?

@silentbobbert
Copy link

@Pikhulya thanks for a detailed reply. I have not revisited this issue for a while. I work at a company who has close links to Microsoft (we are a gold partner in various aspects) and we also have Premier Support etc. The "Company Administrator" role added via older Msol powershell used to be the only way to do what I needed, and it took a lot of head scratching at Microsoft to come up with a working solution for my use case.

My own use case is VSTS builds and release management needing to deploy ARM templates, other AAD Apps, add Reply URLs, deploy App Services which use AAD for authentication etc. The service principal was used because these processes run without a logged in interactive user, and needed to perform actions which needed elevated rights. I was able to get it working using "Company Administrator" and have not revisited it to see if I can delete the Service Principal with way too many rights and replace with a new Service Principal with only the discrete rights I want to assign him.

AAD Apps are AD objects like service principals and users so to create/edit/delete them needs the correct permissions. (From memory AAD Apps are Service Principals?)

@Pikhulya
Copy link

Unnecessary admin permission can be removed from the Service Principal by executing Remove-MsolRoleMember

Service Principal can be thought of like a projection or instance of an Application in any given Tenant, in other words the Application is kind of abstraction/definition/template used to create Service Principals. That is the Service Principal who stores/records (as a result of, for instance, user's Consent) permissions scopes which were granted to an application as well as granted application roles (like with the Graph case being discussed here).
If an Application is multitenant then single instance of Application can have multiple Service Principals "referencing" the application, so each tenant can have its own projection of the application via corresponding Service Principal, so, just in case, again, you can of course delete the SP you have and create new one but an alternative way would be to just update existing one, which way you choose is up to you of course.

@Giaco9
Copy link

Giaco9 commented Feb 19, 2017

Hi @Pikhulya, I followed all your steps but my problem is still there.

I know very well what could be the effects of granting all the permissions to an application or a user, but I think that in that way my problem will be fixed. I will be fine if my app has Admin Permission on my AAD.

But I tried your solution and now I'm going to explain better what I need to do and what I have tried.

Goal:
delete a user from my Active Directory using the API documented here

What I tried:

The response is always:

{
  "odata.error": {
    "code": "Authorization_RequestDenied",
    "message": {
      "lang": "en",
      "value": "Insufficient privileges to complete the operation."
    },
    "requestId": "15ccfa98-e81e-4bf2-a362-504fb1fb9df1",
    "date": "2017-02-19T17:54:42"
  }
}

Randomly both date and requestId fields are missing.

Nevertheless calling the create user API I'm able to create a new user, now I need to delete it.

Now I think is clear what I need. How can I achieve it?

Thanks

@Pikhulya
Copy link

Hi @Giaco9, you are right, the approach I outlined doesn't help with Delete Users. It helps with Read/Create/Update Users and many other operations which resulted in "Insufficient privileges to complete the operation" which are not possible to achieve without making the Service Principal an Admin or without the steps I outlined. So for some cases some kind of Admin role indeed needed but a lot can still be achieved without granting that high privilege.
If you need to delete Users you can employ Add-MsolRoleMember as was outlined by @techiearun but you don't have to leverage Company Administrator, in your case User Account Administrator is enough.

The fact that Delete is blocked as outlined above doesn't make sense to me (taking into account that Update and Create are permitted) but that is what it is.

@Giaco9
Copy link

Giaco9 commented Feb 20, 2017

Thank you @Pikhulya, it works

@njiang
Copy link

njiang commented Mar 30, 2017

@Pikhulya Does this work for B2C? I created an application in my B2C tenant and I can create and assign user to groups. But I cannot reset password, delete and update user. I tried to grant permissions to the app as you explained but it didn't work. I also tried the powershell script but it keeps saying login failed when I tried Connect-MSOLSERVICE with my account (it's a local account). I'm running out of options. Please help!

@sethb75
Copy link

sethb75 commented May 13, 2017

I'm also experiencing problems with B2C. I'm simply trying to read which groups a user belongs to in order to grant/deny them access to various parts of my application. I'm not able to read this groups field however, and get the "Insufficient privileges to complete the operation." error as above.

@pbolduc
Copy link

pbolduc commented May 19, 2017

I had to add a service service principal to the Company Administrator role today using the new Azure AD PowerShell cmdlets

Install Azure AD module (one time)

Install-Module AzureAD

and the cmdlets

Connect-AzureAD
$app = Get-AzureADServicePrincipal -SearchString "your app name"
$role = Get-AzureADDirectoryRole | Where-Object { $_.DisplayName -eq "Company Administrator" }
Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $app.ObjectId

@carlosomarcp
Copy link

I have used before the workaround of adding the service principal to the Company Administrator role, but today, in my new created b2c instance (for a new client) the Company Administrator is not listed in the roles, nor in the roles templates (Get-AzureADDirectoryRoleTemplate) but i found that using the Password Administrator instead of the Company Administrator did the job.

It is the same code as before, but just change the role name.

$role = Get-AzureADDirectoryRole | Where-Object { $_.DisplayName -eq "Password Administrator" }

if Password Administrator is not listed with Get-AzureADDirectoryRole, you can add it with this:

$RoleTemplate = Get-AzureADDirectoryRoleTemplate | Where-Object {$_.DisplayName -eq "Password Administrator"}
Enable-AzureADDirectoryRole -RoleTemplateId $RoleTemplate.ObjectId

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests