Closed markes20754 closed 9 months ago
Thanks for raising this @markes20754
The linked article shows that the request is made to https://graph.microsoft.com/v1.0/invitations
while this package will make requests to https://graph.microsoft.com/beta/invitations
which may behave differently. Any chance this is resolved if you switch to the v1.0 package or change the baseUrl value in the GraphServiceClient
constructor?
Hi @andrueastman I tried setting v1.0 as the endpoint and beta endpoints. Both result in the same error. NOTE: the New-MGBetaInvitation (which uses the /beta endpoint) works properly so I don't think this is an issue between the v1.0 and beta endpoints. Thanks!
@markes20754 Thanks for the extra information. Are you by any chance able to capture a trace of the payload sent to the API when using Powershell so that we can compare with the one generated by the SDK to identify the discrepancy?
@andrueastman I was able to capture both in a fiddler trace. It appears that the PowerShell module is actually passing the Azure AD InvitedUser object information in the request body where the .NET invitation is not.
High level logic that works in Powershell:
Similar logic is done in .NET -- Here's the code snip which includes the Azure AD user object as the InvitedUser property but it's not passed in the request. First screen shot shows the PS call to get the user and then invite that user. Second screen shot is .net but it's not including the invited user information. From looking at the code, it appears that .InvitedUser is read only and is only creating a new guest in the tenant and can't convert an existing user to external.
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options); var _graphServiceClient = new GraphServiceClient(clientSecretCredential, scopes); var usrAzureUser = new User = _graphServiceClient.Users("gemma.perry@UPNSUFFIXREMOVED").GetAsync.Result;
var invitation = new Invitation() { InvitedUser = usrAzureUser, InvitedUserEmailAddress= "gemma.perry@UPNSUFFIXREMOVED", InviteRedirectUrl ="https://myapplications.azure.us/contoso.us", SendInvitationMessage = true, };
POWERSHELL FIDDLER TRACE -- NOTE invitedUser is passed
.NET FIDDLER TRACE -- NOTE invitedUser property data is missing
Thanks for the information here @markes20754
The missing property is due to the backingstore which tries to send only changed values if the data is a response from the API.
You can resolve this by adding this line so that all the data is sent back.
var usrAzureUser = await graphClient.Users["user-id"].GetAsync();
usrAzureUser.BackingStore.InitializationCompleted = false; // add this line so that all properties are serialized.
var invitation = new Invitation()
{
InvitedUser = usrAzureUser,
InvitedUserEmailAddress = "user@contoso.com",
InviteRedirectUrl = "https://myapplications.azure.us/contoso.us",
SendInvitationMessage = true,
};
var jsonString = KiotaJsonSerializer.SerializeAsString(invitation);
@andrueastman - Many thanks. That resolved the issue. I'll submit some updated documentation notes to the invitation manager page: https://learn.microsoft.com/en-us/graph/api/resources/invitation?view=graph-rest-1.0
Thanks for confirming @markes20754
I'm using the invitation resource to try to send B2B invitations to "convert" locally synced AAD accounts to external accounts as documented here: https://learn.microsoft.com/en-us/entra/external-id/invite-internal-users . This works as documented at the end of the article when using methods such as powershell New-MGInviation, New-MGBetaInvitation. However, I'm running into an issue when posting the .NET Invitation Resource type from a .NET application, It appears that the library may want to create a new user rather than converting the existing user. Specifically, the Graph returns "The invited user already exists in the directory as objectID: {AAD objID}. They can use that account to sign in to shared apps and resources."
I'm using Microsoft.Graph.Beta
Am I using this incorrectly or is there something that is always trying to create a new guest user rather than trying to convert an existing internal user to a guest? Thanks!
Here's the sample code snip: and screenshot of result: