-
Notifications
You must be signed in to change notification settings - Fork 252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
User
creation with AdditionalData
set fails with ODataError
"The following extension properties are not available"
#2680
Comments
Thanks for raising this @Eagle3386 From the error log, The following extension properties are not available:
extension_{appId}_CustomerIds,extension_{appId}_TenantId,extension_{appId}_TenantIds. It looks like the extension properties being sent to the API may not be setup. Did you intend to use string interpolation to insert an I believe if you use the API documentaion here, you should be able to list the correct names to use for the extension properties and whether they are available in the tenant you are trying to call. |
@andrueastman Nope, that's just me, redacting the app ID - in the actual exception, it's Furthermore, rest assured, the extension properties are 100% correct - no doubt about it.
Here's even a screenshot from our Azure B2C tenant's And using the Graph API you've linked to, I get this: For convenience, the relevant columns as text:
So, I already confirmed that everything is set up as required, yet the API complains where it shouldn't even try to start & simply do what it's ordered to: create a user with additional data / extension properties. |
User
creation with AdditionalData´ set fails with
ODataError` "The following extension properties are not available"User
creation with AdditionalData
set fails with ODataError
"The following extension properties are not available"
Thanks for coming back to this @Eagle3386 When performing the request using the console app vs the service, do they use the same appId and permissions? |
Yes, of course they do! Besides, how could I possibly get Here's the POC app's relevant code snippet as kinda proof: private static GraphServiceClient AppClient { get; set; }
private static ClientSecretCredential Credential { get; set; }
private static Settings Settings { get; set; }
public static async Task<string> CreateUserAsync()
{
var user = await AppClient.Users
.PostAsync(new()
{
AccountEnabled = true,
AdditionalData = new Dictionary<string, object>
{
{ "extension_abc[…]423_CustomerIds", "1,2,3" },
{ "extension_abc[…]423_TenantId", (int)1u },
{ "extension_abc[…]423_TenantIds", "4,5,6" }
},
CompanyName = "Test Co.",
DisplayName = "Test Pilot",
GivenName = "Test",
Identities =
[
new()
{
Issuer = "{ourB2Csubdomain}.onmicrosoft.com",
IssuerAssignedId = "[email protected]",
SignInType = "emailAddress",
}
],
Mail = "[email protected]",
PasswordPolicies = "DisablePasswordExpiration",
PasswordProfile = new()
{
ForceChangePasswordNextSignIn = false,
Password = "Test12345!"
},
PreferredDataLocation = "EUR",
PreferredLanguage = "de-DE",
Surname = "Pilot",
UsageLocation = "DE",
})
.ConfigureAwait(false);
user = await AppClient.Users[user.Id]
.GetAsync(configuration => configuration.QueryParameters.Select =
[
"extension_abc[…]423_CustomerIds",
"extension_abc[…]423_TenantId",
"extension_abc[…]423_TenantIds",
"GivenName",
"Id",
"Identities",
"Surname"
])
.ConfigureAwait(false);
return $"Name: {user.GivenName} {user.Surname
}\nMail: {user.Identities![0].IssuerAssignedId
}\nID: {user.Id
}\nCustomer IDs: {string.Join(", ", user.AdditionalData.First(data => data.Key.EndsWith("CustomerIds")).Value)
}\nTenant ID: {user.AdditionalData.First(data => data.Key.EndsWith("TenantId")).Value
}\nTenant IDs: {string.Join(", ", user.AdditionalData.First(data => data.Key.EndsWith("TenantIds")).Value)}";
}
public static async Task<string> GetAppOnlyAccessTokenAsync() =>
(await (Credential ?? throw new NullReferenceException("Graph uninitialized for app-only auth."))
.GetTokenAsync(new TokenRequestContext([ "https://graph.microsoft.com/.default" ]))).Token;
public static void InitializeGraphForAppOnlyAuth(Settings settings)
{
Settings = settings ?? throw new NullReferenceException($"{nameof(Settings)} cannot be null.");
Credential ??= new(Settings.TenantId, Settings.ClientId, Settings.ClientSecret);
AppClient ??= new(Credential, [ "https://graph.microsoft.com/.default" ]);
} … which returns: User created:
Name: Test Pilot
Mail: [email protected]
ID: d0a9aeb0-2a4a-47eb-83fa-c79d89fae676
Customer IDs: 1,2,3
Tenant ID: 1
Tenant IDs: 4,5,6 Using that snippet's code for retrieval inside the actual web-service, the user's Key: @odata.context
Value: https://graph.microsoft.com/v1.0/$metadata#users(extension_abc[…]423_CustomerIds,extension_abc[…]423_TenantId,extension_abc[…]423_TenantIds,givenName,id,identities,surname)/$entity … without any exception, so querying works, just as the extension properties are there. So, can we finally switch from "Where's the error in my code?" to "Where's the bug in Graph?" For example, you could tell me how I can enable Graph Explorer to connect to our B2C tenant, because it pretty much only connects to our workforce one. Lastly, rest assured that I already tried the user creation via Graph Explorer & it perfectly created the user, including the extension properties - though, as already stated, it creates them in the workforce tenant which is obviously not what's desired. |
Are you able to capture the request-id and client request id from the error when it fails? Using this, we can file an issue with the API team to understand what could be wrong in this scenario. You should be able to use the guidance here and retrieve the properties from innerError |
Yes, of course! Thanks for asking, @andrueastman! 👍🏻 There you go:
|
Thanks for this. I've raised an issue with the workload and will give feedback based on what they find. https://portal.microsofticm.com/imp/v5/incidents/details/549539260/summary |
Thanks so much, @andrueastman! 👏🏻 |
@Eagle3386 Feedback from the API team is that the string interpolated here is incorrect. It looks like you may be interpolating the tenant_id instead instead of the app_id in the failing scenario. From their perspective, the extension attributes exist but the request has the incorrect id that look like the tenant id. Any chance you can double check to confirm? |
@andrueastman please report precisely back to them: You're wrong, in multiple ways & right from the start:
So, once again: I did double checke - Again! - yet, the error remains the same - just like the code remains to comply with both, the API & its docs, too. Now please, with all due respect as I don't feel you're taking this seriously: rather do debug the given |
Apologies for any frustrations here. I may have not shared enough details before. The team has indeed debugged the request id. The request id shared above here has the following details from the back-end logs. The API team has also confirmed the extension properties do not exist in the given tenant based of the information coming in from the request. App ID : The received request on the backend logs shows the error as where the id matches the tenant id and not the app id Any chance you can confirm if this info is incorrect from your end? If not I can feedback any inconsistencies back to them... |
Thanks for the extra info here. I've fed this new request id back to the API team issue request and will give an update on any new findings from their point of view. |
Again, thanks so much, @andrueastman! 👏🏻 |
@Eagle3386 We've received feedback from the API teams. According to the request, the App ID for the request is The API team gives the feedback that the extension properties in this tenant are setup with another AppId that has the format According to the team, the AppId that should be used is the AppId that is used to configure the extension properties in the tenant and not the AppId that makes the request. https://learn.microsoft.com/en-us/graph/extensibility-overview?tabs=http#directory-microsoft-entra-id-extensions Would it be possible to confirm if this is the information is consistent from your end? |
@andrueastman You're the man - and the API team as well, thanks so much! ❤️ It's the Some more background/context: Lastly, since I fail to find the proper paragraph within the docs: what to change inside my custom policy so that it includes the extension properties as claims within the |
I believe the correct links for the documentation of that scenario would be the following depending on what you're trying to achieve. |
@andrueastman Thanks for both links, but I'm still struggling with your help: First of all: since Azure B2C isn't converted into the Entra "naming scheme", yet, are the docs you've linked to still correct/relevant? |
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
toint
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:
Code snippet for the actual setup in
Program.cs
of the web-service: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
Configuration
Other information
I find the Graph SDK docs regarding Azure B2C user properties rather confusing, because the summary of
AdditionalData
states:while the one for
Extensions
states (emphasis by me):Because that suggests 2 things: a) use
AdditionalData
for reading and writing, butExtensions
only for reading - why 2 properties for basically the same amount of information?The text was updated successfully, but these errors were encountered: