I am writing an API for user to reset self password. User is logged in an web application which calls MS Graph API.
While trying to self update password(I need to verify the current password too), I am getting below error:
code":"Authorization_RequestDenied","message":"Access to change password operation is denied."
Below is my code:
private static async Task UpdatePassword(string clientId, string clientSecret, string tenantId)
{
try
{
var scopes = new string[] { "https://graph.microsoft.com/.default" };
// Configure the MSAL client as a confidential client
var confidentialClient = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
.WithClientSecret(clientSecret)
.Build();
GraphServiceClient graphServiceClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
{
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await confidentialClient
.AcquireTokenForClient(scopes)
.ExecuteAsync();
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
})
);
await graphServiceClient.Users["9c704dfb-a3ea-528a-937c-d7da45ebcc7a"]
.ChangePassword("OldPassword", "NewPassword").Request().PostAsync();
}catch(Exception e)
{
}
}
I also saw /me endpoints but did not understand how to make that work in my scenario.
I appreciate any help, Thank you.
2
Answers
Your requirement: Writing an API for user to reset self password.
Background: User is logged in an web application which calls MS Graph API.
If you want to create a stand alone web api which exposing a feature to let users update their password, it is impossible. Let’s see the api document, it doesn’t support application api permission. Pls note, application type not support means you can’t write an api project to provide the ability because web api project is considered as a daemon application which only support AAD client credential flow, and client credential flow must use application permission. According your code snippet, you set the scope as
xxx/.default
, this means you are trying to use client credential flow.We can only use
Delegated
api permission. According to the screenshot in your this question, we can see you’ve given theDirectory.AccessAsUser.All
, so I consider you’ve had enough permissions. You can’t realize this feature in a stand-alone api project, but you can do it in the web application which allows users to sign in by AAD.Here’s a sample for users sign in by integrating AAD into the web application. And I think you should have similar code in your web app(providing a login partial view, modify Startup.cs file and add configurations in appsettings.json), what you need to do is following the sample to add code about Graph SDK.
And in your Controller, inject
GraphServiceClient graphServiceClient
and change password with codeawait graphClient.Me.ChangePassword(currentPassword,newPassword).Request().PostAsync();
I agree with @Tiny Wang. Although I have done the same via postman and it’s just a different approach to the solution of your issue.
To change user’s password, you must add Delegated
Directory.AccessAsUser.All
permission for your application.Please note that, the code you mentioned is using
Client credentials flow
that works with only Application permissions.I tried to reproduce the same in my environment and got below results:
I granted below
API permissions
to the Azure AD application in my B2C tenant:Now I generated access token using client credentials flow via Postman like below:
Response:
When I used the above
token
to call below query, I got same error:Response:
To resolve the error, you need to use interactive flows like Authorization Code, Username Password etc…
So, I generated access token using Authorization Code flow via Postman like below:
When I used the above
token
to call below query, password changed successfully like below:Response:
Please note that,
/me/changePassword
endpoint is same as/users/signed_in_user_id/changePassword
endpoint.I tried using
/me/changePassword
endpoint and got same results as below:Code sample in C#:
Reference:
user: changePassword – Microsoft Graph
Update:
To generate Authorization Code flow, use this above code InPrivate mode and Sign into your account you get a code like this below. For reference