Descrição do problema:
Estou com um problema ao tentar criar/atualizar uma assinatura programaticamente, e ele reclama que só é possível criar uma assinatura com até 2 dias de antecedência. No entanto, quando entro no meu locatário pelo MS Graph Explorer, ele permite até 30 dias.
Aqui está um exemplo de assinatura que estou usando no Graph Explorer. Consigo alterar a data de validade para 6 de maio de 2025 e a assinatura é criada sem problemas.
Aqui está um trecho de dados que retorna quando faço um GET em minhas assinaturas (observe a data de expiração)
Entretanto, no meu aplicativo c# recebo a seguinte mensagem de erro:
O que tentei até agora:
Tentei alternar entre permissões de aplicativo e delegadas no registro do meu aplicativo no Azure. Atualmente, está definido como delegado:
Essa limitação é intencional? Ou existe uma maneira de criar uma assinatura de 30 dias pela API?
Qualquer sugestão será apreciada.
EDIT 1 Aqui está meu código que tenta criar a assinatura:
public async Task<EntraGroupSubscription> CreateSubscriptionAsync(SubscriptionRequest request)
{
try
{
// Get configuration from database
var configurations = await _configRepository.GetAllAsync();
var config = configurations.FirstOrDefault();
if (config == null)
{
throw new InvalidOperationException("No configuration found in the database. Please configure the EntraWatcher first.");
}
_logger.LogInformation("Configuration loaded with ExpirationMinutes: {ExpirationMinutes}", config.ExpirationMinutes);
// Build notification URL details
var notificationUrlDetails = new NotificationUrlDetails
{
AzureSubscriptionId = config.AzureSubscriptionId,
ResourceGroup = config.ResourceGroup,
PartnerTopic = config.PartnerTopic,
Location = config.Location
};
// Log the minutes value that will be used for expiration
var currentTime = DateTime.UtcNow;
// Build the complete subscription request using properties from request and config
var completeRequest = new CompleteSubscriptionRequest
{
ChangeType = request.ChangeType,
NotificationUrlDetails = notificationUrlDetails,
LifecycleNotificationUrlDetails = notificationUrlDetails, // Using same details for both
// Explicitly set the resource to "groups" as per Microsoft documentation
Resource = "groups",
// Set the expiration using the configured minutes from configuration
ExpirationDateTime = DateTime.UtcNow.AddMinutes(config.ExpirationMinutes).ToString("o"), // ISO 8601 format
ClientState = config.ClientState,
Description = request.Description
};
// Map CompleteSubscriptionRequest to Graph API subscription
var graphSubscriptionDto = new Microsoft.Graph.Models.Subscription
{
ChangeType = completeRequest.ChangeType,
NotificationUrl = completeRequest.NotificationUrl,
LifecycleNotificationUrl = completeRequest.LifecycleNotificationUrl,
Resource = completeRequest.Resource,
// Set the expiration date directly using the configured minutes
ExpirationDateTime = DateTime.UtcNow.AddMinutes(config.ExpirationMinutes),
ClientState = completeRequest.ClientState
};
var createdSubscription = await _graphClient.CreateSubscriptionAsync(graphSubscriptionDto);
if (createdSubscription != null)
{
// Map Graph API response to our domain entity
var entraGroupSubscription = _mapper.Map<EntraGroupSubscription>(createdSubscription);
// Add the description which isn't part of the Graph API response
entraGroupSubscription.Description = completeRequest.Description;
// Store subscription in table storage
await StoreSubscriptionAsync(createdSubscription, completeRequest);
return entraGroupSubscription;
}
return null;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating subscription");
throw;
}
}
Este é o método na camada de infraestrutura que cria o cliente gráfico e faz a chamada:
public async Task<Subscription> CreateSubscriptionAsync(Subscription subscription)
{
try
{
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { "Group.ReadWrite.All" });
// Create a new GraphServiceClient with the acquired token
var graphClient = new GraphServiceClient(
new BaseBearerTokenAuthenticationProvider(
new TokenProvider(accessToken)));
// Now make the API call with the new client that has the delegated token
return await graphClient.Subscriptions.PostAsync(subscription);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating subscription in Graph API: {Message}", ex.Message);
throw;
}
}
Segui seu trecho de código e encontrei esta API que é usada para gerenciar assinaturas.
Podemos ver que ele aponta para esse objeto e que ele
expirationDateTime
é obrigatório e tem um tempo de vida diferente para cada tipo de assinatura.Vamos consultar esta seção . Podemos ver que alguns tipos têm um tempo máximo de expiração de 30 dias, mas alguns têm apenas 3 dias. Como você não compartilhou o corpo da sua solicitação GET e seus códigos, receio que esteja trabalhando em tipos de assinatura diferentes.