1
votes

I am trying to create a page in ASP.Net MVC to reset the current user's password. I am using Azure active directory for user authentication. To access, the user's AD information, I am using the C# Graph API client. My code is based on a sample found on GitHub

I am able to make changes to the user's information (such as city, state, email). However, when I attempt to change the password using the PasswordProfile attribute on the user object, I am getting an error saying I have insufficient permissions. I am attempting to change the password as the application and I believe that the source of the permission issue is with the application.

I found the following PowerShell script that is supposed to add the company administrator role to an application. However, the call to Get-MsolServicePrincipal does not return anything. Looking at the output of the command, I don't see any entries that even resemble the name of my application.

#-----------------------------------------------------------
# This will prompt you for your tenant's credential
# You should be able to use your your Azure AD administrative user name
# (in the [email protected] format)
#-----------------------------------------------------------
import-module MSOnline
Connect-MsolService

#-----------------------------------------------------------
# Replace the Application Name with the name of your 
# Application Service Principal
#-----------------------------------------------------------
$displayName = "My Azure AD Application"
$objectId = (Get-MsolServicePrincipal -SearchString $displayName).ObjectId

#-----------------------------------------------------------
# This will add your Application Service Prinicpal to 
# the Company Administrator role
#-----------------------------------------------------------
$roleName = "Company Administrator"              
Add-MsolRoleMember -RoleName $roleName -RoleMemberType ServicePrincipal -RoleMemberObjectId $objectId

I guess my first question is am I correct that the permission issue is with application?

Second, what value to which I should be setting the $displayName variable?

2

2 Answers

3
votes

You need to ensure that your application configuration in Azure Active Directory has the appropriate permissions setup. Adding the rights using what you have above is overkill. You should be adding the required permissions only to your application in the directory.

As a starting point I would suggest you review the Graph API Consent Permission blog post here. You can only reset a password as an account or global administrator using traditional rights but you should be assigning application permissions.

"Read and write directory data" used to provide this permission however I believe this was removed. Now I believe the user has to consent using the OAuth authentication flow to be able to reset a password.

See the changePassword method on the currently logged in user for more information on this. I have a custom desktop application for users to reset their own passwords.

In my application I have the users authenticate to get an access token using their existing password (this also helps me validate their current credentials before changing the password).

var authority = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/" + Domain);
var ctx = new AuthenticationContext(authority, false);
var result = ctx.AcquireToken("https://graph.windows.net", "ClientID", credential);
return result.AccessToken;

The credential property is a UserCredential type using the users UPN and password. I then pass a web request to change the password.

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", UserAccessToken);
var requestUri = $"https://graph.windows.net/me/changePassword?api-version={Constants.ApiVersion}";
var pwdObject = new { currentPassword = curPassword, newPassword = newPass };
var body = new JavaScriptSerializer().Serialize(pwdObject);
var response = client.PostAsync(new Uri(requestUri), new StringContent(body, Encoding.UTF8, "application/json")).Result;

This returns a HTTP 204 if the request was successful, I also trap a AADSTS50126 exception when getting the user token as this indicates the credentials are invalid when obtaining the token.

0
votes

You can change the password from your application only if you give to it the right privilege. The approach explained by Martyn C is the best approach if you can impersonate the user, which, of course, has the permission to change his password. With my approach there's no need to use any UserCredentials since the permissions will be assigned to the application that will be able to change the password for other users. A typical use case is when you need to manage password change from api with a non-interactive flow. This implies you must trust the application's code and use it carefully.

I used to grant the Helpdesk Administrator role to my app which is enough to change password to other users. Through this powershell script:

Install-Module MSOnline
Install-Module AzureAD
Connect-MsolService
Connect-AzureAD

$applicationId = "{your app ID}"
$sp = Get-MsolServicePrincipal -AppPrincipalId $applicationId
Add-MsolRoleMember -RoleObjectId <your Role ID> -RoleMemberObjectId $sp.ObjectId -RoleMemberType servicePrincipal

You should connect using a User with Administrator Privileges on your Active Directory. You can get the propert roleID using this command:

Get-AzureADDirectoryRole

Now your app has enough privileges to call the PATCH method (from Microsoft Docs) to change the password for other users.