Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

The 425 Show profile imageChristos Matskas
Christos Matskas forThe 425 Show

Posted on

     

Delete all users in an Azure AD Tenant programmatically

The first part of "deleting an Azure AD tenant programmatically" is here. Today, we're going to delete all Azure AD users (except our admin account). Me an JP streamed the whole process along with the steps necessary to achieve this, but you can always skip to the code or the blog post below:

Prerequisites

  • VS Code
  • .NET Core 3.1 (or later)
  • An Azure AD B2C tenant

The Azure AD App Registration

To be able to interact with Azure AD, we need to create an App Registration. In Azure AD, got toApp Registrations -> New Registration. Give it a meaningful name and selectmulti-tenant for supported account types. In the new App Registration, navigate to theAuthentication andAdd a Platform. SelectMobile & Desktop, choose the URI that works best for you (I like the MSAL one) and then make sure to select theEnable Public Client Flows option. Save this! Finally, we need to add and admin-consent to the necessary MS Graph permissions. InAPI Permissions press theAdd a permission button, selectDelegated permissions and search for theUser.ReadWrite.All permission. Make sure to press theAdd Permission at the bottom of the window.

Alt Text

Since this is a Console app, we need to provide admin consent prior to authenticating. On theAPI Permissions blade, press theGrant Admin consent for

Alt Text.

We are now ready to build our user deletion code...

Let's write some code

Our code needs to

  • Authenticate the current user (interactive auth)
  • Retrieve all user objects in the directory
  • Ensure we exclude our admin account (otherwise we lose access)
  • batch up the delete operation and execute the batches.

Open up your favorite Terminal and type:
dotnet new console -n tenant_deleter

We also need to add a couple of NuGet packages to make our lives easier when interacting with Azure AD and MS Graph. In the Terminal, type:

dotnet add package Microsoft.Graphdotnet add package Microsoft.Identity.Client
Enter fullscreen modeExit fullscreen mode

Alt Text

Open the project in your favorite code editor (I use VS Code) and add a new file:MsalTokenProvider.cs. Add the following code:

using System;using System.Linq;using System.Net.Http;using System.Threading.Tasks;using Microsoft.Graph;using Microsoft.Identity.Client;namespace tenant_deleter{    // todo: stop building new MsalTokenProviders for every project    public class MsalTokenProvider : IAuthenticationProvider    {        public readonly IPublicClientApplication _client;        private readonly string[] _scopes = {             "https://graph.microsoft.com/User.ReadWrite.All"            };        public MsalTokenProvider(string tenantId)        {            _client = PublicClientApplicationBuilder               // mt app reg in separate tenant               // todo: move to config               .Create("<Your Azure AD App registration Client ID>")               .WithAuthority($"https://login.microsoftonline.com/{tenantId}")               .Build();        }        public async Task AuthenticateRequestAsync(HttpRequestMessage request)        {            AuthenticationResult token;            try            {                // get an account ------ ??????                var account = await _client.GetAccountsAsync();                token = await _client.AcquireTokenSilent(_scopes, account.FirstOrDefault())                    .ExecuteAsync();            }            catch (MsalUiRequiredException)            {                token = await _client.AcquireTokenWithDeviceCode(                    _scopes,                    resultCallback =>                    {                        Console.WriteLine(resultCallback.Message);                        return Task.CompletedTask;                    }                ).ExecuteAsync();            }            request.Headers.Authorization =                    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.AccessToken);        }    }}
Enter fullscreen modeExit fullscreen mode

This code is responsible for signing in to Azure AD and acquiring the Access Token for MS Graph.

Go back intoProgram.cs to add the necessary code:

using System;using System.Net.Http;using System.Threading.Tasks;using Microsoft.Graph;namespace tenant_deleter{    class Program    {        async static Task Main(string[] args)        {            string tenantId;            if (args.Length < 1)            {                Console.WriteLine("gimme a tenant");                tenantId = Console.ReadLine();            }            else            {                tenantId = args[0];            }            var graph = new GraphServiceClient(new MsalTokenProvider(tenantId));            var td = new ThingDeleter(graph);            await td.DeleteAllUsersFromTenant();            Console.WriteLine("*fin*");            Console.ReadLine();        }    }    public class ThingDeleter    {        private readonly GraphServiceClient _graphServiceClient;        public ThingDeleter(GraphServiceClient client)        {            _graphServiceClient = client;        }        // delete all users from tenant        public async Task DeleteAllUsersFromTenant()        {            var me = await _graphServiceClient.Me.Request().Select(x => x.Id).GetAsync();            var users = await _graphServiceClient.Users.Request()                .Select(x => x.Id)                .Top(20)            .GetAsync();            var batch = new BatchRequestContent();            var currentBatchStep = 1;            var pageIterator = PageIterator<User>            .CreatePageIterator(                _graphServiceClient,                users,                (user) =>                {                    if (user.Id == me.Id) return true; //don't delete me                    var requestUrl = _graphServiceClient                            .Users[user.Id]                            .Request().RequestUrl;                    var request = new HttpRequestMessage(HttpMethod.Delete, requestUrl);                    var requestStep = new BatchRequestStep(currentBatchStep.ToString(), request, null);                    batch.AddBatchRequestStep(requestStep);                    if (currentBatchStep == users.Count)                    {                        _graphServiceClient.Batch.Request().PostAsync(batch).GetAwaiter().GetResult();                        currentBatchStep = 1; // batches are 1-indexed, weird                        return true;                    }                    currentBatchStep++;                    return true;                },                (req) =>                {                    return req;                }            );            await pageIterator.IterateAsync();        }    }}
Enter fullscreen modeExit fullscreen mode

You'll notice that the Graph code uses batching to optimize the calls against MS Graph. This is necessary, especially for larger tenants with 1000s of users. The nice thing is that we can also parallelize this to make it ever more efficient :)

Now, we can build the code withdotnet build to make sure that everything builds and that we haven't missed anything.

Finally, let's run the app withdotnet run <your Tenant Id>

Alt Text

Job done. One task down, a few more to go! Check themain blog post on how to delete an Azure AD Tenant.

Show me the code

If you want to clone and run the app, head out to theGitHub Repo

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

More fromThe 425 Show

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp