Reputation: 16931
I'm create a service app that runs in the background and changes user's password in Azure Active Directory via Microsoft Graph API. Everything works fine if I give the Application User administrator
or Helpdesk administrator
role. What if I'm not allowed to user role but rather use "API Permissions" and give only permission to change password, nothing else?
I tried to add Directory.AccessAsUser.All
and Directory.ReadWrite.All
API permissions. Even tried to add other permissions. Here is a list of API permissions I had (I know that some of them are not needed, just wanted to do the process of elimination later):
But still getting 403 error
"code": "Authorization_RequestDenied"
"message": "Insufficient privileges to complete the operation."
I'm using Python to achieve that. Here is my code that is working with the Helpdesk administrator
role:
import json
import logging
import requests
import msal # pip install msal
import jwt
user_id = '[email protected]'
tenant_id = 'AZURE TENANT ID'
client_id = 'AZURE CLIENT ID'
secret = 'AZURE CLIENT SECRET'
users_endpoint = 'https://graph.microsoft.com/v1.0/users'
scopes = ['https://graph.microsoft.com/.default']
authority = 'https://login.microsoftonline.com/%s' % tenant_id
app = msal.ConfidentialClientApplication(
client_id,
authority=authority,
client_credential=secret
)
# Get access token
result = app.acquire_token_silent(scopes=scopes, account=None)
if not result:
logging.debug("No suitable token exists in cache. Let's get a new one from AAD.")
result = app.acquire_token_for_client(scopes=scopes)
if "access_token" in result:
access_token = result['access_token'] # JWT access token
token = jwt.decode(access_token, verify=False)
print(token['roles'])
# Updating user's password
pwd_change_payload = {
'passwordProfile': {
'password': "newpassword123$#@",
'forceChangePasswordNextSignIn': False
}
}
usr_pwd_update_resp = requests.patch(
'%s/%s' % (users_endpoint, user_id),
headers={
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
},
data=json.dumps(pwd_change_payload)
)
resp_status_code = usr_pwd_update_resp.status_code
if resp_status_code == 204:
logging.info("Password successfully changed in Azure")
elif resp_status_code == 403:
print("ERROR 403")
print(usr_pwd_update_resp)
else:
print("Unknown error?? " + str(resp_status_code) + ": " + str(usr_pwd_update_resp) )
else:
print(result)
What exactly I need to configure on Azure side to make sure that the above code will work properly
Upvotes: 0
Views: 1103
Reputation: 42043
To update the passwordProfile
of the user, the Directory.AccessAsUser.All
permission is needed. But it is the Delegated permission
, not Application permission
. It means the permission will not take effect in the client credential flow(the confidential_client_secret_sample
you provided uses it).
So if you want to let the Delegated permission
take effect, you need to use a user-interactive way, e.g. interactive_sample
, device_flow_sample
, username_password_sample
(not recommended and not work for MFA-enabled account). And you should note in these samples, they all use PublicClientApplication
, means you need to set Allow public client flows
to Yes
like below.
Besides, if you just want to avoid to use admin role because of the security issue, actually it is unnecessary, because the permissions of Helpdesk Administrator
are less than the combination of Directory.AccessAsUser.All
and Directory.ReadWrite.All
, it is better to use Helpdesk Administrator
role directly in this case.
Upvotes: 0
Reputation: 3485
to be able to change other user passwords you need and admin role such as the ones mentioned or others like Authentication Administrator. Without those you won't be able to do it.
Upvotes: 0