msgraph-sdk-dotnet
msgraph-sdk-dotnet copied to clipboard
PreAuthorizedApplications and Oauth2PermissionScopes are not created anymore using Microsoft.Graph 5.0.0-preview.10
Describe the bug
I am trying to create an app registration and a corresponding service principal.
I noticed that PreAuthorizedApplications and Oauth2PermissionScopes are ignored when calling PatchAsync.
To Reproduce
var graphClient = new GraphServiceClient(new AzureCliCredential());
var (servicePrincipal, application) = await graphClient.CreateOrUpdateApplication("test123");
public static class GraphServiceClientExtensions
{
private const string ManageResourceGroups = "ResourceGroups.Create";
public static async Task<ServicePrincipal> CreateOrUpdateServicePrincipal(this GraphServiceClient client,
Application application, ServicePrincipal servicePrincipal)
{
var servicePrincipalResult = await client.TryGetServicePrincipalExists(application.DisplayName);
if (!servicePrincipalResult.Exists)
return await client.ServicePrincipals.PostAsync(servicePrincipal);
servicePrincipal.Id = servicePrincipalResult.ServicePrincipal.Id;
await client.ServicePrincipals[servicePrincipalResult.ServicePrincipal.Id].PatchAsync(servicePrincipal);
return servicePrincipal;
}
public static async Task<(ServicePrincipal servicePrincipal, Application application)> CreateOrUpdateApplication(this GraphServiceClient client, string applicationName)
{
var application = (await client.Applications
.GetAsync(x => x.QueryParameters.Filter = $"displayname eq '{applicationName}'")).Value
.SingleOrDefault() ??
await client.Applications.PostAsync(new Application { DisplayName = applicationName });
var permissionId = Guid.NewGuid().ToString();
if (!application.Api.PreAuthorizedApplications.Any() && !application.Api.Oauth2PermissionScopes.Any())
{
application.Api = new ApiApplication
{
PreAuthorizedApplications = new List<PreAuthorizedApplication>(),
Oauth2PermissionScopes = new List<PermissionScope>()
};
}
if (!application.Api.Oauth2PermissionScopes.Exists(x => x.Value == "user_impersonation"))
{
application.Api.Oauth2PermissionScopes.Add(new()
{
Id = permissionId,
AdminConsentDescription = "AdminConsentDescription",
AdminConsentDisplayName = "AdminConsentDisplayName",
IsEnabled = true,
Type = "User",
UserConsentDescription = "UserConsentDescription",
UserConsentDisplayName = "UserConsentDisplayName",
Value = "user_impersonation"
});
}
else
{
permissionId = application.Api.Oauth2PermissionScopes.Single(x => x.Value == "user_impersonation").Id;
}
if (!application.AppRoles.Exists(x => x.Value == ManageResourceGroups))
{
application.AppRoles = new List<AppRole>();
application.AppRoles.Add(new()
{
Id = Guid.NewGuid().ToString(),
DisplayName = "Manage Resource Groups",
Description = "Manage Resource Groups",
IsEnabled = true,
Origin = "Application",
Value = ManageResourceGroups,
AllowedMemberTypes = new List<string> { "Application", "User" },
});
}
application.IdentifierUris = new List<string> { $"api://{application.AppId}" };
await client.Applications[application.Id].PatchAsync(application);
// TODO PreAuthorizedApplications does not provisioning anymore
// Maybe it is a bug in the preview version
application.Api.PreAuthorizedApplications = new List<PreAuthorizedApplication>
{
new()
{
// Azure CLI
AppId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46",
DelegatedPermissionIds = new List<string> { permissionId }
}
};
await client.Applications[application.Id].PatchAsync(application);
var servicePrincipal = await client.CreateOrUpdateServicePrincipal(application, new ServicePrincipal
{
DisplayName = application.DisplayName,
AppId = application.AppId,
AppRoleAssignmentRequired = true,
Tags = new List<string> { "HideApp" }
});
return (servicePrincipal, application);
}
public class ServicePrincipalResult
{
public ServicePrincipalResult(bool exists, ServicePrincipal? servicePrincipal)
{
Exists = exists;
ServicePrincipal = servicePrincipal;
}
[MemberNotNullWhen(true, nameof(ServicePrincipal))]
public bool Exists { get; }
public ServicePrincipal? ServicePrincipal { get; }
}
public static async Task<ServicePrincipalResult> TryGetServicePrincipalExists(this GraphServiceClient client,
string displayName)
{
var principals = (await client.ServicePrincipals.GetAsync(x =>
x.QueryParameters.Filter = $"displayName eq '{displayName}'")
).Value;
return new ServicePrincipalResult(principals.Any(), principals.SingleOrDefault());
}
}
Expected behavior
Authorized client applications should show Azure Cli (04b07795-8ddb-461a-bbee-02f9e1bf7b46) with scope api://{AppId}/user_impersonation in Azure portal or when I retrieve the application from Graph API PreAuthorizedApplications and Oauth2PermissionScopes should not be empty.
Additional information
I noticed that when I create new instances for Api, PreAuthorizedApplications and Oauth2PermissionScopes, then at least
Oauth2PermissionScopes seem to work correctly.
application.Api = new ApiApplication
{
PreAuthorizedApplications = new List<PreAuthorizedApplication>(),
Oauth2PermissionScopes = new List<PermissionScope>()
};