Library version used
latest
.NET version
net 8
Scenario
ConfidentialClient - service to service (AcquireTokenForClient)
Is this a new or an existing app?
This is a new app or experiment
Issue description and reproduction steps
Bug
The WithClientAssertion(Func<AssertionRequestOptions, CancellationToken, Task<ClientSignedAssertion>>) overload in ConfidentialClientApplicationBuilder does not validate the delegate parameter for null, unlike every other WithClientAssertion overload.
Expected Behavior
Passing null should throw ArgumentNullException(nameof(clientSignedAssertionProvider)) at build time, consistent with other overloads.
Actual Behavior
Passing null succeeds at build time. The null delegate is stored and causes a NullReferenceException at runtime when MSAL attempts to invoke it during token acquisition. The XML doc also incorrectly claims MsalClientException is thrown.
Root Cause
The overload at ConfidentialClientApplicationBuilder.cs:333-338 passes the delegate directly to WithClientAssertionInternal without a null guard:
// Current code — no null check
public ConfidentialClientApplicationBuilder WithClientAssertion(Func<AssertionRequestOptions,
CancellationToken, Task<ClientSignedAssertion>> clientSignedAssertionProvider)
{
return WithClientAssertionInternal(
clientSignedAssertionProvider: clientSignedAssertionProvider);
}
All other overloads validate first:
// Other overloads — correct pattern (lines 292, 311)
if (clientAssertionAsyncDelegate == null)
{
throw new ArgumentNullException(nameof(clientAssertionAsyncDelegate));
}
### Relevant code snippets
```csharp
Expected behavior
Fix
- Add null validation to the overload:
public ConfidentialClientApplicationBuilder WithClientAssertion(Func<AssertionRequestOptions,
CancellationToken, Task> clientSignedAssertionProvider)
{
if (clientSignedAssertionProvider == null)
{
throw new ArgumentNullException(nameof(clientSignedAssertionProvider));
}
return WithClientAssertionInternal(
clientSignedAssertionProvider: clientSignedAssertionProvider);
}
- Update XML doc: change to on line
332.
- Add a unit test verifying ArgumentNullException is thrown.
Files to Change
┌───────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────┐
│ File │ Change │
├───────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ src/client/Microsoft.Identity.Client/AppConfig/ConfidentialClientApplicationBuilder.cs │ Add null guard + fix XML doc │
├───────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ tests/Microsoft.Identity.Test.Unit/PublicApiTests/ConfidentialClientApplicationTests.cs │ Add test for null delegate │
└───────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────┘
Context
Identity provider
Microsoft Entra ID (Work and School accounts and Personal Microsoft accounts)
Regression
No response
Solution and workarounds
No response
Library version used
latest
.NET version
net 8
Scenario
ConfidentialClient - service to service (AcquireTokenForClient)
Is this a new or an existing app?
This is a new app or experiment
Issue description and reproduction steps
Bug
The
WithClientAssertion(Func<AssertionRequestOptions, CancellationToken, Task<ClientSignedAssertion>>)overload inConfidentialClientApplicationBuilderdoes not validate the delegate parameter for null, unlike every otherWithClientAssertionoverload.Expected Behavior
Passing
nullshould throwArgumentNullException(nameof(clientSignedAssertionProvider))at build time, consistent with other overloads.Actual Behavior
Passing
nullsucceeds at build time. The null delegate is stored and causes aNullReferenceExceptionat runtime when MSAL attempts to invoke it during token acquisition. The XML doc also incorrectly claimsMsalClientExceptionis thrown.Root Cause
The overload at
ConfidentialClientApplicationBuilder.cs:333-338passes the delegate directly toWithClientAssertionInternalwithout a null guard:Expected behavior
Fix
public ConfidentialClientApplicationBuilder WithClientAssertion(Func<AssertionRequestOptions,
CancellationToken, Task> clientSignedAssertionProvider)
{
if (clientSignedAssertionProvider == null)
{
throw new ArgumentNullException(nameof(clientSignedAssertionProvider));
}
}
332.
Files to Change
┌───────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────┐
│ File │ Change │
├───────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ src/client/Microsoft.Identity.Client/AppConfig/ConfidentialClientApplicationBuilder.cs │ Add null guard + fix XML doc │
├───────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ tests/Microsoft.Identity.Test.Unit/PublicApiTests/ConfidentialClientApplicationTests.cs │ Add test for null delegate │
└───────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────┘
Context
Identity provider
Microsoft Entra ID (Work and School accounts and Personal Microsoft accounts)
Regression
No response
Solution and workarounds
No response