microsoftgraph / microsoftgraph/msgraph-sdk-dotnet
`User` creation with `AdditionalData` set fails with `ODataError` "The following extension properties are not available"
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 789
- Forks
- 264
- Avg merge
- 15h 17m
- Merged PRs (30d)
- 3
Description
Describe the bug
I'm trying to create users in an Azure B2C tenant via Graph which fails when using the code inside a gRPC web-service, but succeeds in a console POC-style app - using the exact same code snippet?!
Fun fact: setting the 2nd extension property without casting it from uint to int results in the API only complaining about that property, not the other 2.
Expected behavior
Code succeeds, no matter which way its run.
How to reproduce
Code snippet of the actual Graph code:
var user = await graphServiceClient.Users
.PostAsync(new()
{
AccountEnabled = true,
AdditionalData = new Dictionary<string, object>
{
{ "extension_{appId}_CustomerIds", "1,2,3" },
{ "extension_{appId}_TenantId", (int)1u },
{ "extension_{appId}_TenantIds", "4,5,6" }
},
CompanyName = "Test Co.",
DisplayName = "Test Pilot",
GivenName = "Test",
Identities =
[
new()
{
Issuer = "{ourB2Csubdomain}.onmicrosoft.com",
IssuerAssignedId = "quacks@example.net",
SignInType = "emailAddress",
}
],
Mail = "quacks@example.net",
PasswordPolicies = "DisablePasswordExpiration",
PasswordProfile = new()
{
ForceChangePasswordNextSignIn = false,
Password = "Test12345!"
},
PreferredDataLocation = "EUR",
PreferredLanguage = "de-DE",
Surname = "Pilot",
UsageLocation = "DE",
})
.ConfigureAwait(false);
Code snippet for the actual setup in Program.cs of the web-service:
// … code left out for brevity…
var configuration = builder.Configuration;
var isNonProduction = !builder.Environment.IsProduction();
// … code left out for brevity…
.AddAuthentication()
.AddMicrosoftIdentityWebApi(options =>
{
LogCompleteSecurityArtifact = ShowPII = isNonProduction;
builder.Configuration.Bind(Constants.AzureAdB2C, options);
options.TokenValidationParameters = new()
{
// … code left out for brevity…
};
},
options => builder.Configuration.Bind(Constants.AzureAdB2C, options),
subscribeToJwtBearerMiddlewareDiagnosticsEvents: isNonProduction)
.EnableTokenAcquisitionToCallDownstreamApi(options =>
{
// … code left out for brevity…
options.EnablePiiLogging = isNonProduction;
options.LogLevel = isNonProduction ? LogLevel.Always : LogLevel.Info;
})
.AddMicrosoftGraphAppOnly(_ =>
new(
new Azure.Identity.ClientSecretCredential(
configuration[$"{Constants.AzureAdB2C}:{nameof(MicrosoftIdentityOptions.TenantId)}"],
clientId,
clientSecret,
new()
{
Diagnostics =
{
// … code left out for brevity…
},
IsUnsafeSupportLoggingEnabled = isNonProduction
})))
.AddInMemoryTokenCaches(options =>
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(isNonProduction ? 14 : 90))
// … code left out for brevity…
SDK Version
5.58
Latest version known to work for scenario above?
AFAICT: none
Known Workarounds
None, because neither using a POC-style console app nor adding those extension properties via PATCH HTTP request is suitable - I expect the Graph API to handle user creation successfully even when extension properties are part of the request's payload.
Debug output
Click to expand log
Microsoft.Graph.Models.ODataErrors.ODataError:
The following extension properties are not available:
extension_{appId}_CustomerIds,extension_{appId}_TenantId,extension_{appId}_TenantIds.
at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.ThrowIfFailedResponse(
HttpResponseMessage response,
Dictionary`2 errorMapping,
Activity activityForAttributes,
CancellationToken cancellationToken)
at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](
RequestInformation requestInfo,
ParsableFactory`1 factory,
Dictionary`2 errorMapping,
CancellationToken cancellationToken)
at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](
RequestInformation requestInfo,
ParsableFactory`1 factory,
Dictionary`2 errorMapping,
CancellationToken cancellationToken)
at Microsoft.Graph.Users.UsersRequestBuilder.PostAsync(
User body,
Action`1 requestConfiguration,
CancellationToken cancellationToken)
at My.Services.Migration.GraphService.CreateUser(CreateUserRequest request, ServerCallContext context)
in D:\Code\Services\My.Services.Migration\GraphService.cs:line 24
Configuration
- OS: Windows 11, latest patches & Ubuntu Ubuntu 22.04.4 LTS, latest patches
- architecture: x64 (Windows) & x86_64 (Ubuntu)
Other information
I find the Graph SDK docs regarding Azure B2C user properties rather confusing, because the summary of AdditionalData states:
Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
while the one for Extensions states (emphasis by me):
The collection of open extensions defined for the user. Read-only. Supports $expand. Nullable.
Because that suggests 2 things: a) use AdditionalData for reading and writing, but Extensions only for reading - why 2 properties for basically the same amount of information?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at GraphService.cs line 24 and review the Graph and authentication setup in Program.cs. Reproduce the user-creation request with SDK 5.58, then inspect the serialized request and resulting extension-property error while comparing it with the console and PATCH cases. Done means the cause of the differing behavior is identified and a supported create-user path or SDK correction is established.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, csharp
- Domain
- api, authentication
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100