0

I was trying to authenticate to Azure DefaultAzureCredential using @azure/identity in Node js to get the reports of Azure API Management Service.

Things I have done :

  1. Created An API Management Service from Azure Portal

  2. Registered an application with Azure AD and create a service principal using this documentation.

  3. I Have configured environment variables correctly to use DefaultAzureCredential as mentioned in this documentation.

    AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION,

But the authentication is getting failed and I am not able to generate credentials. when I consoled the new DefaultAzureCredential(); response, it says that UnavailableMessage: 'DefaultAzureCredential => failed to retrieve a token from the included credentials',

require("dotenv").config();
const { DefaultAzureCredential } = require("@azure/identity");
const { ApiManagementClient } = require("@azure/arm-apimanagement");

if (!process.env.AZURE_TENANT_ID) throw Error("AZURE_TENANT_ID is missing from environment variables.");
if (!process.env.AZURE_CLIENT_ID) throw Error("AZURE_CLIENT_ID is missing from environment variables.");
if (!process.env.AZURE_CLIENT_SECRET) throw Error("AZURE_CLIENT_SECRET is missing from environment variables.");
if (!process.env.AZURE_RESOURCE_GROUP) throw Error("AZURE_RESOURCE_GROUP is missing from environment variables.");
if (!process.env.AZURE_SERVICE_NAME) throw Error("AZURE_SERVICE_NAME is missing from environment variables.");
if (!process.env.AZURE_SUBSCRIPTION) throw Error("AZURE_SUBSCRIPTION is missing from environment variables.");

const subscriptionId = process.env.AZURE_SUBSCRIPTION;

const credentials = new DefaultAzureCredential();

console.log(credentials);

And I got this Error,

DefaultAzureCredential {
  UnavailableMessage: 'DefaultAzureCredential => failed to retrieve a token from the included credentials',
  _sources: [
    EnvironmentCredential { _credential: [ClientSecretCredential] },
    ManagedIdentityCredential {
      isEndpointUnavailable: null,
      clientId: 'c8xxxxxxxx5ac8',
      identityClient: [IdentityClient]
    },
    AzureCliCredential {},
    VisualStudioCodeCredential {
      cloudName: 'AzureCloud',
      identityClient: [IdentityClient],
      tenantId: 'common'
    }
  ]
}

As one of the answer to a similar question in stack overflow mentioned that The DefaultAzureCredential works even though it shows the unavailable message, I tried moving on to getting reports of an API Management Service using @azure/identity

const client = new ApiManagementClient(credentials, subscriptionId);

const resourceGroupName = process.env.AZURE_RESOURCE_GROUP;
const serviceName = process.env.AZURE_SERVICE_NAME;
const filter = "callCountSuccess";

client.reports
    .listBySubscription(
        resourceGroupName,
        serviceName,
        filter
    )
    .then((result) => {
        console.log(JSON.stringify(result));
    })
    .catch((err) => {
        console.log(err);
    });

But as this is also giving the 403 error,

response: {
    body: `{"error":
    {"code":"AuthorizationFailed",
    "message":
    "The client 'cxxxxxxxxxxxxxxx569' with object id 'cxxxxxxxxxxxxxxx569' 
    does not have authorization to perform action 'Microsoft.ApiManagement/service/reports/read' 
    over scope '/subscriptions/85xxxxxxx3c5/resourceGroups/axxxb/providers/Microsoft.ApiManagement/service/Axxxx/reports/bySubscription' 
    or the scope is invalid. 
    If access was recently granted, please refresh your credentials."}}`,
    headers: HttpHeaders { _headersMap: [Object] },
    status: 403
  },

EDIT

I have added the API Management Sevice Reader Role to The Api management service but I am getting the same error as above. enter image description here

1 Answers1

1

The reason you are running into AuthorizationFailed error is because it looks like you have not assigned any permissions (RBAC role) to your Service Principal.

By default, the Service Principal will not have any permissions to perform operations on an Azure Subscription. You will need to grant appropriate permissions explicitly by assigning suitable RBAC role to your Service Principal.

You can try by assigning Reader role to your Service Principal at Subscription, Resource Group or API Management resource level. You may find this link helpful: https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-steps.

Once appropriate role has been assigned, you should not get this error.

Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241
  • Thanks for the response. I have updated the question with your solution but getting the same error as the previous one. – Ammar Abdul Aziz Oct 06 '21 at 12:22
  • Can you confirm that the client id and object id mentioned in the error message matches with that of your Service Principal? – Gaurav Mantri Oct 06 '21 at 12:25
  • No. The Client Id and Object Id that is shown in the error message is not from my application. Tbh I don't know where is it coming from since I have added my application credentials properly to the .env file against the keys they have mentioned in the documentation. I have taken those credentials from the application's overview page. – Ammar Abdul Aziz Oct 06 '21 at 12:42
  • Hmmm...That's weird. Can you try your request with [`ClientSecretCredential`](https://learn.microsoft.com/en-gb/javascript/api/@azure/identity/clientsecretcredential?view=azure-node-latest) instead of `DefaultAzureCredential`? – Gaurav Mantri Oct 06 '21 at 12:53
  • I'm sorry I am getting the same error. I don't this it's an issue with the credentials. because I am getting a proper 400 Invalid credentials error when I enter these credentials wrongly. This is 403, maybe something to do with the permission. – Ammar Abdul Aziz Oct 06 '21 at 13:05
  • This is definitely a permission related issue. Your Service Principal does not have proper permission to perform the operation. Can you try by assigning `API Management Service Contributor` role to your Service Principal? – Gaurav Mantri Oct 06 '21 at 13:13
  • Perfect! The issue was with the permission. when you asked to assign the Reader role to Service Principle I've mistakenly added this role to the user, not the service principle. Now it's working fine and I've got the expected response. Thank You! – Ammar Abdul Aziz Oct 06 '21 at 13:48