Azure Digital Twins APIs is not working with DefaultAzureCredential authentication method as described in the tutorial

I was following the Coding with the Azure Digital Twins APIs tutorial. I have prepared an Azure Digital Twins instance as described by the tutorial. This is my role -

account_role

This is my Azure Digital Twins instance -

ADT_instance

This is my access permissions -

user_access

DefaultAzureCredential method

Then, I have set up local Azure credentials as described by the tutorial. I have signed in to Azure by Azure CLI and also with VS Code extension.

az_login

vsc_extension

But when I was uploading model as instructed by the tutorial, I got an Azure.Identity.AuthenticationFailedException error. Here is the code of my client app -

Code

using System;
using Azure.DigitalTwins.Core;
using Azure.Identity;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Generic;
using Azure;

namespace ADT_demo
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string adtInstanceUrl = "https://digitaltwinsek3p.api.wcus.digitaltwins.azure.net";

            var credential = new DefaultAzureCredential();
            DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);
            Console.WriteLine($"Service client created – ready to go");



            Console.WriteLine();
            Console.WriteLine($"Upload a model");
            var typeList = new List<string>();
            string dtdl = File.ReadAllText("SampleModel.json");
            typeList.Add(dtdl);
            // Upload the model to the service
            await client.CreateModelsAsync(typeList);

            Console.WriteLine("Hello World!");
        }
    }
}


Error

Unhandled exception. Azure.Identity.AuthenticationFailedException: SharedTokenCacheCredential authentication failed: A configuration issue is preventing authentication - check the error message from the server for details.You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details.  Original exception: AADSTS70002: The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https://go.microsoft.com/fwlink/?linkid=2083908.
Trace ID: 9e17bbaa-e120-4d31-af90-121216db0c00
Correlation ID: c2cf4df0-5257-4de6-892c-66855072ad95
Timestamp: 2021-01-18 11:17:11Z
 ---> MSAL.NetCore.4.22.0.0.MsalServiceException:
        ErrorCode: invalid_client
Microsoft.Identity.Client.MsalServiceException: A configuration issue is preventing authentication - check the error message from the server for details.You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details.  Original exception: AADSTS70002: The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https://go.microsoft.com/fwlink/?linkid=2083908.
Trace ID: 9e17bbaa-e120-4d31-af90-121216db0c00
Correlation ID: c2cf4df0-5257-4de6-892c-66855072ad95
Timestamp: 2021-01-18 11:17:11Z
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.ThrowServerException(HttpResponse response, RequestContext requestContext)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.ExecuteRequestAsync[T](Uri endPoint, HttpMethod method, RequestContext requestContext, Boolean expectErrorsOn200OK, Boolean addCommonHeaders)
   at Microsoft.Identity.Client.OAuth2.OAuth2Client.GetTokenAsync(Uri endPoint, RequestContext requestContext, Boolean addCommonHeaders)
   at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint)
   at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint)
   at Microsoft.Identity.Client.OAuth2.TokenClient.SendTokenRequestAsync(IDictionary`2 additionalBodyParameters, String scopeOverride, String tokenEndpointOverride, CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.SendTokenRequestAsync(String tokenEndpoint, IDictionary`2 additionalBodyParameters, CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.CacheSilentStrategy.RefreshAccessTokenAsync(MsalRefreshTokenCacheItem msalRefreshTokenItem, CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.CacheSilentStrategy.TryGetTokenUsingFociAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.CacheSilentStrategy.RefreshRtOrFailAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.CacheSilentStrategy.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.CacheSilentStrategy.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.ApiConfig.Executors.ClientApplicationBaseExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenSilentParameters silentParameters, CancellationToken cancellationToken)
   at Azure.Identity.AbstractAcquireTokenParameterBuilderExtensions.ExecuteAsync[T](AbstractAcquireTokenParameterBuilder`1 builder, Boolean async, CancellationToken cancellationToken)
   at Azure.Identity.MsalPublicClient.AcquireTokenSilentAsync(String[] scopes, IAccount account, Boolean async, CancellationToken cancellationToken)
   at Azure.Identity.SharedTokenCacheCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
        StatusCode: 401
        ResponseBody: {"error":"invalid_client","error_description":"AADSTS70002: The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https://go.microsoft.com/fwlink/?linkid=2083908.\r\nTrace ID: 9e17bbaa-e120-4d31-af90-121216db0c00\r\nCorrelation ID: c2cf4df0-5257-4de6-892c-66855072ad95\r\nTimestamp: 2021-01-18 11:17:11Z","error_codes":[70002],"timestamp":"2021-01-18 11:17:11Z","trace_id":"9e17bbaa-e120-4d31-af90-121216db0c00","correlation_id":"c2cf4df0-5257-4de6-892c-66855072ad95","error_uri":"https://login.microsoftonline.com/error?code=70002"}
        Headers: Cache-Control: no-store, no-cache
Pragma: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
client-request-id: c2cf4df0-5257-4de6-892c-66855072ad95
x-ms-request-id: 9e17bbaa-e120-4d31-af90-121216db0c00
x-ms-ests-server: 2.1.11397.13 - KRSLR2 ProdSlices
x-ms-clitelem: 1,70002,0,99387912.9884,
Set-Cookie: fpc=AgEOOZYkMXtLt3KqlIDdhsj8dx2YAQAAADdll9cOAAAA; expires=Wed, 17-Feb-2021 11:17:11 GMT; path=/; secure; HttpOnly; SameSite=None,x-ms-gateway-slice=prod; path=/; secure; samesite=none; httponly,stsservicecookie=estsfd; path=/; secure; samesite=none; httponly
Date: Mon, 18 Jan 2021 11:17:11 GMT

   --- End of inner exception stack trace ---
   at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex)
   at Azure.Identity.SharedTokenCacheCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.SharedTokenCacheCredential.GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.DefaultAzureCredential.GetTokenFromSourcesAsync(TokenCredential[] sources, TokenRequestContext requestContext, Boolean async, CancellationToken cancellationToken)
   at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex)
   at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.DefaultAzureCredential.GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueFromCredentialAsync(HttpMessage message, Boolean async, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueAsync(HttpMessage message, Boolean async)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.DigitalTwins.Core.DigitalTwinModelsRestClient.AddAsync(IEnumerable`1 models, CreateModelsOptions digitalTwinModelsAddOptions, CancellationToken cancellationToken)
   at Azure.DigitalTwins.Core.DigitalTwinsClient.CreateModelsAsync(IEnumerable`1 dtdlModels, CancellationToken cancellationToken)
   at ADT_demo.Program.Main(String[] args) in C:\Users\<location>\Program.cs:line 29
   at ADT_demo.Program.<Main>(String[] args)

InteractiveBrowserCredential method

But when I used InteractiveBrowserCredential method, with an app registration, that has permissions to the Azure Digital Twins APIs, it worked fine.

Code

using System;
using Azure.DigitalTwins.Core;
using Azure.Identity;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Generic;
using Azure;

namespace ADT_demo
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string adtInstanceUrl = "https://digitaltwinsek3p.api.wcus.digitaltwins.azure.net";
            string clientId = "<your-client-ID>";
            string tenantId = "<your-tenant-ID>";

            var credential = new InteractiveBrowserCredential(tenantId, clientId);
            DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential);
            Console.WriteLine($"Service client created – ready to go");


            Console.WriteLine();
            Console.WriteLine($"Upload a model");
            var typeList = new List<string>();
            string dtdl = File.ReadAllText("SampleModel.json");
            typeList.Add(dtdl);
            // Upload the model to the service
            await client.CreateModelsAsync(typeList);

            Console.WriteLine("Hello World!");
        }
    }
}

Why authentication is not working in DefaultAzureCredential method?

Thank you.

1 answer

  • answered 2021-01-18 17:08 Sebastian Roether

    The documentation states that DefaultAzureCredential is just a wrapper that will try in order:

    EnvironmentCredential
    ManagedIdentityCredential
    SharedTokenCacheCredential
    VisualStudioCredential
    VisualStudioCodeCredential
    AzureCliCredential
    InteractiveBrowserCredential
    

    and as you can see, shared token credentials - the one producing your exception - will be used when found before trying visual studio code credentials or azure CLI credentials.

    So the easy fix would be to replace DefaultAzureCredential with e.g. AzureCliCredential. The long term fix would be to wait for someone else to explain where the shared token credential entries are stored and get rid of them or update them ;-)

    best regards Sebastian