How to get additional data (user principle name) with change notifications if Graph user is Hard deleted?

151 views Asked by At

I have subscribed to change notifications for MS graph users resource in my ASP.NET Core Web API. So far I am receiving notifications when a user is updated or deleted (soft delete).

Subscription:

var subscriptionObj = new Subscription();
subscriptionObj.ChangeType = "updated,deleted";
subscriptionObj.NotificationUrl = $"{notificationUrl}";
subscriptionObj.Resource = "/users";
subscriptionObj.ExpirationDateTime = DateTime.Now.AddDays(5);
subscriptionObj.ClientState = $"{clientState}";

var newSubscription = await graphClient.Subscriptions.Request().AddAsync(subscriptionObj);

Receive notifications:

using (StreamReader reader = new StreamReader(requestBbody))
{
    string content = await reader.ReadToEndAsync();
    var notifications = JsonConvert.DeserializeObject<GraphNotifications>(content);

    foreach (var notification in notifications.Values)
    {
        var resource = notification.Resource;
        var resourceDataId = notification.ResourceData?.Id;

        if (notification.ChangeType == "updated")
        {
            try
            {
                var azureUser = await graphClient.Users[resourceDataId].Request().GetAsync();

                // DB update method call
                DbUpdate(azureUser.UserPrincipalName)
            }
            catch (Exception)
            {
                var directoryObjectSoftDeleted = await graphClient.Directory.DeletedItems[resourceDataId].Request().GetAsync();
                var azureUserSoftDeleted = (Microsoft.Graph.User)directoryObjectSoftDeleted;

                // DB update method call
                DbUpdate(azureUserSoftDeleted.UserPrincipalName)
            }
        }

        // Need to handle: if hard delete
        // else
        // {
        //     var azureUserDeleted = await graphClient.Users[resourceDataId].Request().GetAsync();
        //     DbUpdate(azureUserDeleted.UserPrincipalName)
        // }
    }

}

I get the Azure user by resource data id and I find the email address (user principle name) that belongs to the updated/deleted resource and using that email I query the users and update database for respective users.

For now, everything works as expected, but I wonder how can I get resource data id if the user is hard deleted. Even though I get the resource data id how can I then query for azure user by giving the resource data id (object id) because resource could not be found if the user is hard deleted. I want to remove all the hard deleted and soft deleted graph users in my DB. How can I achieve this?

2

There are 2 answers

1
user2250152 On

There is no subscription for hard deleted items. If users are permanently deleted 30 days after initial deletion, you can create a new column or table in your DB to store a date when user should be permanently deleted.

catch (Exception)
{
    var directoryObjectSoftDeleted = await graphClient.Directory.DeletedItems[resourceDataId]
                                       .Request()
                                       .Select("userPrincipalName,deletedDateTime").GetAsync();
    var azureUserSoftDeleted = (Microsoft.Graph.User)directoryObjectSoftDeleted;

    // DB update method call
    DbUpdate(azureUserSoftDeleted.UserPrincipalName, azureUserSoftDeleted.DeletedDateTime);
}

Periodically check if the hard deletion date has already expired and then remove user from db.

0
Md Farid Uddin Kiron On

I wonder how can I get resource data id if the user is hard deleted.

Well, first of all, a user or resource deletion typically after 30 days called as hard deleted which is not only you but also Microsoft itself cannot recover or can able to retrieve any meta-data or anything because they removed forever as @user2250152 pointed out.

https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/users-restore

However, you could always extract your soft-delete user or resource information within next 30 days by using graph API.

Currently, deleted items functionality is only supported for the application, servicePrincipal, group, administrative unit, and user resources. Please refer this official docs.

var graphClient = new GraphServiceClient(requestAdapter);

var result = await graphClient.Directory.DeletedItems["{YourUserObjectID}"].GetAsync();

Note: Please refer to this official document for more detials.