microsoft-identity-web: [Bug] Null reference exception calling AcquireTokenByAuthorizationCode when client secret is not specified (need to improve error message)

Which Version of MSAL are you using ? 4.5.1

Platform .NET Core 3

What authentication flow has the issue?

  • Web App
    • Authorization code

Is this a new or existing app? c. This is a new app or experiment

Repro This is based on https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Acquiring-tokens-with-authorization-codes-on-web-apps but using WithB2CAuthority rather than WithAuthority.

IConfidentialClientApplication cca = ConfidentialClientApplicationBuilder
	.Create(AzureAdB2COptions.ClientId)
	.WithRedirectUri(AzureAdB2COptions.RedirectUri)
	.WithB2CAuthority(AzureAdB2COptions.Authority)
	.Build();

var builder = cca.AcquireTokenByAuthorizationCode(new[] { "openid" }, context.ProtocolMessage.Code);
AuthenticationResult result = await builder.ExecuteAsync();

Expected behavior I was expecting to retrieve an access token in line with https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-oauth-code#2-get-a-token

Actual behavior Exception is thrown by ExecuteAsync(). Stack-trace as follows (awaits removed):

at Microsoft.Identity.Client.Internal.ClientCredentialWrapper.get_Thumbprint()
at Microsoft.Identity.Client.Internal.JsonWebToken.JWTHeaderWithCertificate..ctor(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.JsonWebToken.EncodeHeaderToJson(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.JsonWebToken.Encode(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.JsonWebToken.Sign(ClientCredentialWrapper credential, Boolean sendCertificate)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialHelper.CreateClientCredentialBodyParameters(ICoreLogger logger, ICryptographyManager cryptographyManager, ClientCredentialWrapper clientCredential, String clientId, AuthorityEndpoints endpoints, Boolean sendX5C)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<SendTokenRequestAsync>d__21.MoveNext()
at Microsoft.Identity.Client.Internal.Requests.AuthorizationCodeRequest.<ExecuteAsync>d__3.MoveNext()
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__14.MoveNext()
at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.<ExecuteAsync>d__2.MoveNext()

Possible Solution I had a look at the master (512d74e) and at RequestBase.cs line 300 there is a condition if (AuthenticationRequestParameters.ClientCredential != null) which must be succeeding to get that stack trace. I would have expected this to be null as I’m executing AcquireTokenByAuthorizationCode and not a client credentials grant.

The WebApp-OpenIDConnect-DotNet sample includes .WithClientSecret(AzureAdB2COptions.ClientSecret) and using this makes the exception go away, but doesn’t resolve the problem because it generates an error in B2C: “'AADB2C90079: Clients must send a client_secret when redeeming a confidential grant”.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (2 by maintainers)

Most upvoted comments

In appsettings.json in AzureAd add ClientSecret with proper value it helped me with the same exception.

In appsettings.json in AzureAd add ClientSecret with proper value it helped me with the same exception.

Make sure your ClientSecret/ClientId are not missing! This was my issue as well.

I am facing a similar issue currently

---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.Identity.Client.Internal.ClientCredentialWrapper.get_Thumbprint()
   at Microsoft.Identity.Client.Internal.JsonWebToken.JWTHeaderWithCertificate..ctor(ClientCredentialWrapper credential, Boolean sendCertificate)
   at Microsoft.Identity.Client.Internal.JsonWebToken.Encode(ClientCredentialWrapper credential, Boolean sendCertificate)
   at Microsoft.Identity.Client.Internal.JsonWebToken.Sign(ClientCredentialWrapper credential, Boolean sendCertificate)
   at Microsoft.Identity.Client.Internal.Requests.ClientCredentialHelper.CreateClientCredentialBodyParameters(ICoreLogger logger, ICryptographyManager cryptographyManager, ClientCredentialWrapper clientCredential, String clientId, AuthorityEndpoints endpoints, Boolean sendX5C)
   at Microsoft.Identity.Client.OAuth2.TokenClient.<SendTokenRequestAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.<SendTokenRequestAsync>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<FetchNewAccessTokenAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.<ExecuteAsync>d__3.MoveNext()<---