Search code examples
asp.net-coreazure-active-directoryasp.net-core-webapimicrosoft-entra-id

How to grant consent during sign in with Microsoft Entra ID (Azure AD)


I have an ASP.NET Core 7.0 Web API application which exposes a REST API for user login. I have several active user accounts in Azure AD, and I want to sign in to AD using this API.

For this purpose, I am using the NuGet package Microsoft.IdentityModel.Clients.ActiveDirectory, version 5.3.0.

This is my code for signing in:

string clientId = Configuration.GetSection("ClientId").Value;
string domain = Configuration.GetSection("TokenEndpoint").Value;
string[] scopes = { "User.ReadWrite.All" };

IPublicClientApplication app;
app = PublicClientApplicationBuilder.Create(clientId).WithAuthority(domain).Build();

try
{
    var result =  await app.AcquireTokenByUsernamePassword(scopes, userData.email, userData.Password).ExecuteAsync();
    return result;
}
catch (MsalException ex)
{
    Console.WriteLine(ex.Message);
    Console.WriteLine(ex.StackTrace);
    if(ex.InnerException != null){
        Console.WriteLine(ex.InnerException.Message);
        Console.WriteLine(ex.InnerException.StackTrace);
    }
    throw ex;
}

However, this code is returning the following error:

{
   "error":"invalid_grant",
   "error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '******' named '******'. Send an interactive authorization request for this user and resource. Trace ID: ****** Correlation ID: ****** Timestamp: 2024-02-12 08:34:04Z",
   "error_codes":[
      65001
   ],
   "timestamp":"2024-02-12 08:34:04Z",
   "trace_id":"******",
   "correlation_id":"******",
   "suberror":"consent_required"
}

I checked the following resources online:

  1. https://learn.microsoft.com/en-us/answers/questions/545439/aadsts65001-the-user-or-administrator-has-not-cons
  2. AADSTS65001: The user or administrator has not consented to use the application with ID <app-id>
  3. InteractionRequiredAuthError: AADSTS65001: The user or administrator has not consented to use the application with ID
  4. "AADSTS65001: The user or administrator has not consented to use the application" occurs when token is acquired on behalf of a user

Based on the suggestions made in these resources, I made the following changes

  1. In Azure Portal -> Azure Active Directory -> App Registrations -> Your App -> API permissions, add the appropriate API permissions for Microsoft Graph (see screenshot below)
  2. In In Azure Portal -> Azure Active Directory -> App Registrations -> Your App -> Authentication, select both access tokens and ID tokens (see screenshot below)
  3. In Azure Portal -> Azure Active Directory -> Enterprise applications -> Consent and permissions -> User consent settings, check allow user consent for apps (3rd option)
  4. In Azure Portal -> Azure Active Directory -> Enterprise applications -> User settings, set 'users can consent to apps accessing company data on their behalf' to Yes

Can you please provide any clue regarding this error?

Screenshot 1 enter image description here

Screenshot 2 enter image description here


Solution

  • Note that the Microsoft.IdentityModel.Clients.ActiveDirectory library calls the Azure AD Graph API which is deprecated.

    Alternatively, you can use the Microsoft.Identity.Client package for generating access token which calls Microsoft Graph API.


    The error occurred because you are using permissions of the Application type with a username/password flow. Make sure to grant permissions of the Delegated type while using delegated flows like username/password flow, auth code flow, etc.

    You can register an Entra ID application and grant the User.ReadWrite.All permission of the Delegated type like this:

    enter image description here

    To generate the access token via a username/password flow, I ran the below C# code after installing the Microsoft.Identity.Client package:

    using Microsoft.Identity.Client;
    
    namespace Sri
    {
        class Program
        {
            static async Task Main(string[] args)
            {
                string clientId = "appId";
                string domain = "https://login.microsoftonline.com/tenantId/oauth2/v2.0/authorize";
                string[] scopes = { "User.ReadWrite.All" };
    
                IPublicClientApplication app;
                app = PublicClientApplicationBuilder.Create(clientId).WithAuthority(domain).Build();
    
                try
                {
                    UserData userData = new UserData { email = "[email protected]", Password = "xxxxxxxxx" };
                    var result = await app.AcquireTokenByUsernamePassword(scopes, userData.email, userData.Password).ExecuteAsync();
                    Console.WriteLine("Token acquired successfully.");
                    Console.WriteLine($"Access Token: {result.AccessToken}");
                }
                catch (MsalException ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                    if (ex.InnerException != null)
                    {
                        Console.WriteLine(ex.InnerException.Message);
                        Console.WriteLine(ex.InnerException.StackTrace);
                    }
                    throw ex;
                }
            }
        }
        public class UserData
        {
            public string email { get; set; }
            public string Password { get; set; }
        }
    }
    

    Response:

    enter image description here

    To confirm that, you can decode this token by pasting it into the jwt.ms website and check whether aud & scp claims have valid values or not:

    enter image description here

    Now you can use this token to make Microsoft Graph API requests like listing, creating, updating and deleting Azure AD users.